@flashbacktech/tsclient 0.4.33

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,1953 @@
1
+ type TokenProvider = () => string | null | Promise<string | null>;
2
+ type UnauthorizedHandler = () => void | Promise<void>;
3
+
4
+ /**
5
+ * Returns the org id the platform admin is currently impersonating, or
6
+ * undefined when not impersonating. Resolved per-request so a UI toggle
7
+ * takes effect on the next call without rebuilding the client. Honored
8
+ * by the server only for users in the configured ADMIN_ORGANIZATION;
9
+ * non-admins receive a 403.
10
+ */
11
+ type ImpersonationProvider = () => string | undefined | Promise<string | undefined>;
12
+ interface BaseClientOptions {
13
+ baseUrl: string;
14
+ getToken?: TokenProvider;
15
+ onUnauthorized?: UnauthorizedHandler;
16
+ fetch?: typeof fetch;
17
+ debug?: boolean;
18
+ defaultHeaders?: Record<string, string>;
19
+ getImpersonateOrgId?: ImpersonationProvider;
20
+ }
21
+ type QueryValue = string | number | boolean | string[] | null | undefined;
22
+ type Query = Record<string, QueryValue>;
23
+ interface RequestOptions {
24
+ /**
25
+ * Query string params. Plain object; we serialize string/number/boolean,
26
+ * repeat arrays, and drop undefined/null values.
27
+ */
28
+ query?: object;
29
+ body?: unknown;
30
+ headers?: Record<string, string>;
31
+ /** Skip the bearer token (used for public endpoints like /user/login). */
32
+ skipAuth?: boolean;
33
+ }
34
+ declare class BaseClient {
35
+ readonly baseUrl: string;
36
+ private readonly getToken?;
37
+ private readonly onUnauthorized?;
38
+ private readonly fetchImpl;
39
+ private readonly debug;
40
+ private readonly defaultHeaders;
41
+ private readonly getImpersonateOrgId?;
42
+ constructor(options: BaseClientOptions);
43
+ get<T>(path: string, options?: RequestOptions): Promise<T>;
44
+ post<T>(path: string, options?: RequestOptions): Promise<T>;
45
+ put<T>(path: string, options?: RequestOptions): Promise<T>;
46
+ patch<T>(path: string, options?: RequestOptions): Promise<T>;
47
+ delete<T>(path: string, options?: RequestOptions): Promise<T>;
48
+ request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
49
+ private buildUrl;
50
+ }
51
+
52
+ declare enum ProviderType {
53
+ LOCAL = "LOCAL",
54
+ GOOGLE = "GOOGLE",
55
+ MICROSOFT = "MICROSOFT",
56
+ GITHUB = "GITHUB",
57
+ WEB3_STELLAR = "WEB3_STELLAR"
58
+ }
59
+ declare enum AccessType {
60
+ READ = "READ",
61
+ WRITE = "WRITE",
62
+ ADMIN = "ADMIN"
63
+ }
64
+ declare enum OrgRoles {
65
+ USER = 0,
66
+ BILLING = 1,
67
+ WORKSPACES = 2,
68
+ ADMINISTRATORS = 254,
69
+ OWNER = 255
70
+ }
71
+ interface UserSummary {
72
+ id: string;
73
+ name: string;
74
+ lastName: string;
75
+ email: string;
76
+ orgRole?: number | null;
77
+ }
78
+
79
+ interface AuthUser {
80
+ id: string;
81
+ email: string;
82
+ name: string;
83
+ lastName?: string;
84
+ orgId?: string | null;
85
+ orgRole?: number | null;
86
+ provider?: string | null;
87
+ validated?: boolean;
88
+ mfaRequired?: boolean;
89
+ }
90
+ interface SessionTokens {
91
+ accessToken: string;
92
+ refreshToken?: string;
93
+ tokenId?: string;
94
+ expiresAt?: number;
95
+ }
96
+ /**
97
+ * Returned by login / refresh / SSO exchange. The backend may return either
98
+ * a fully-verified session (`accessToken` set) or a "pending MFA" challenge
99
+ * (`verificationTokenId` set, `accessToken` absent). Consumers branch on
100
+ * whether `accessToken` is present.
101
+ */
102
+ interface SessionResponse extends Partial<SessionTokens> {
103
+ success: boolean;
104
+ user?: AuthUser;
105
+ verificationTokenId?: string;
106
+ message?: string;
107
+ error_code?: string;
108
+ }
109
+ interface LoginRequest {
110
+ email: string;
111
+ password: string;
112
+ }
113
+ interface RegisterRequest {
114
+ email: string;
115
+ password: string;
116
+ firstName: string;
117
+ lastName: string;
118
+ companyName?: string;
119
+ website?: string;
120
+ isBusiness?: boolean;
121
+ activationUid?: string;
122
+ activationToken?: string;
123
+ }
124
+ interface ActivateRequest {
125
+ uid: string;
126
+ token: string;
127
+ registrationInfo?: Record<string, unknown>;
128
+ }
129
+ interface ResetPasswordRequest {
130
+ token: string;
131
+ newPassword: string;
132
+ }
133
+ interface RefreshRequest {
134
+ refreshToken: string;
135
+ provider?: ProviderType;
136
+ }
137
+ interface ExchangeCodeRequest {
138
+ code: string;
139
+ redirectUri?: string;
140
+ }
141
+ interface SimpleResponse$2 {
142
+ success: boolean;
143
+ message?: string;
144
+ error_code?: string;
145
+ }
146
+
147
+ declare class AuthClient {
148
+ private readonly http;
149
+ constructor(http: BaseClient);
150
+ login(body: LoginRequest): Promise<SessionResponse>;
151
+ register(body: RegisterRequest): Promise<SessionResponse>;
152
+ logout(refreshToken?: string): Promise<SimpleResponse$2>;
153
+ refresh(body: RefreshRequest): Promise<SessionResponse>;
154
+ activate(body: ActivateRequest): Promise<SessionResponse>;
155
+ requestVerification(email: string): Promise<SimpleResponse$2>;
156
+ requestPasswordReset(email: string): Promise<SimpleResponse$2>;
157
+ resetPassword(body: ResetPasswordRequest): Promise<SimpleResponse$2>;
158
+ exchangeGoogle(body: ExchangeCodeRequest): Promise<SessionResponse>;
159
+ }
160
+
161
+ declare enum MFAType {
162
+ GOOGLE_AUTH = "GOOGLE_AUTH",
163
+ MAGIC_LINK = "MAGIC_LINK",
164
+ PASSKEY = "PASSKEY"
165
+ }
166
+ interface MFAStatus {
167
+ isEnabled: boolean;
168
+ isRequired: boolean;
169
+ isEnforced: boolean;
170
+ enabledMethods: MFAType[];
171
+ primaryMethod?: MFAType | null;
172
+ sessionVerified: boolean;
173
+ }
174
+ interface MFASetupResponse {
175
+ success: boolean;
176
+ data?: {
177
+ mfaType: MFAType;
178
+ secret?: string;
179
+ qrCode?: string;
180
+ backupCodes?: string[];
181
+ };
182
+ message?: string;
183
+ }
184
+ interface MFAVerifySetupRequest {
185
+ mfaType: MFAType;
186
+ code?: string;
187
+ credential?: Record<string, unknown>;
188
+ }
189
+ interface MFAVerifyLoginRequest {
190
+ mfaType: MFAType;
191
+ code?: string;
192
+ credential?: Record<string, unknown>;
193
+ }
194
+ interface MFASimpleResponse {
195
+ success: boolean;
196
+ message?: string;
197
+ data?: unknown;
198
+ }
199
+ interface MFAVerifyLoginResponse {
200
+ success: boolean;
201
+ accessToken?: string;
202
+ refreshToken?: string;
203
+ tokenId?: string;
204
+ expiresAt?: number;
205
+ user?: unknown;
206
+ message?: string;
207
+ error_code?: string;
208
+ }
209
+ interface MagicLinkSendResponse {
210
+ success: boolean;
211
+ message?: string;
212
+ }
213
+ interface MagicLinkActivateRequest {
214
+ token: string;
215
+ }
216
+
217
+ declare class MfaClient {
218
+ private readonly http;
219
+ constructor(http: BaseClient);
220
+ getStatus(): Promise<MFAStatus>;
221
+ getMethods(): Promise<MFAType[]>;
222
+ setup(body: {
223
+ mfaType: MFAType;
224
+ email?: string;
225
+ }): Promise<MFASetupResponse>;
226
+ verifySetup(body: MFAVerifySetupRequest): Promise<MFASimpleResponse>;
227
+ enable(mfaType: MFAType): Promise<MFASimpleResponse>;
228
+ disable(mfaType: MFAType): Promise<MFASimpleResponse>;
229
+ setPrimary(mfaType: MFAType): Promise<MFASimpleResponse>;
230
+ sendMagicLink(): Promise<MagicLinkSendResponse>;
231
+ activateMagicLink(body: MagicLinkActivateRequest): Promise<MFAVerifyLoginResponse>;
232
+ verifyLogin(body: MFAVerifyLoginRequest): Promise<MFAVerifyLoginResponse>;
233
+ }
234
+
235
+ interface UserProfile {
236
+ id: string;
237
+ email: string;
238
+ name: string;
239
+ lastName?: string;
240
+ orgId?: string | null;
241
+ orgRole?: number | null;
242
+ provider?: string | null;
243
+ validated?: boolean;
244
+ mfaRequired?: boolean;
245
+ createdAt?: string;
246
+ }
247
+ interface UpdateUserRequest {
248
+ name?: string;
249
+ lastName?: string;
250
+ email?: string;
251
+ password?: string;
252
+ currentPassword?: string;
253
+ }
254
+ interface UpdateUserResponse {
255
+ success: boolean;
256
+ data?: UserProfile;
257
+ message?: string;
258
+ }
259
+
260
+ declare class UserClient {
261
+ private readonly http;
262
+ constructor(http: BaseClient);
263
+ getProfile(): Promise<UserProfile>;
264
+ update(body: UpdateUserRequest): Promise<UpdateUserResponse>;
265
+ }
266
+
267
+ interface Organization {
268
+ id: string;
269
+ name: string;
270
+ domain: string;
271
+ address1?: string | null;
272
+ address2?: string | null;
273
+ city?: string | null;
274
+ zipcode?: string | null;
275
+ phone?: string | null;
276
+ state?: string | null;
277
+ country?: string | null;
278
+ website?: string | null;
279
+ is_business: boolean;
280
+ mfaEnforced: boolean;
281
+ reposDisabled?: boolean;
282
+ allowDebug: boolean;
283
+ }
284
+ interface UpdateOrganizationRequest {
285
+ name?: string;
286
+ domain?: string;
287
+ address1?: string;
288
+ address2?: string;
289
+ city?: string;
290
+ zipcode?: string;
291
+ phone?: string;
292
+ state?: string;
293
+ country?: string;
294
+ website?: string;
295
+ is_business?: boolean;
296
+ mfaEnforced?: boolean;
297
+ }
298
+ interface OrganizationUser {
299
+ id: string;
300
+ email: string;
301
+ name: string;
302
+ lastName?: string;
303
+ orgRole?: number | null;
304
+ validated?: boolean;
305
+ createdAt?: string;
306
+ }
307
+ interface CreateOrganizationUserRequest {
308
+ email: string;
309
+ firstName?: string;
310
+ lastName?: string;
311
+ orgRole?: number;
312
+ }
313
+ /** Covers name, lastName, and/or role updates — all fields optional. */
314
+ interface UpdateOrgUserRequest {
315
+ name?: string;
316
+ lastName?: string;
317
+ orgRole?: number;
318
+ }
319
+ interface AcceptInviteRequest {
320
+ token: string;
321
+ password: string;
322
+ }
323
+ interface SimpleOrgResponse {
324
+ success: boolean;
325
+ message?: string;
326
+ data?: unknown;
327
+ }
328
+
329
+ declare class OrganizationClient {
330
+ private readonly http;
331
+ constructor(http: BaseClient);
332
+ get(orgId: string): Promise<Organization>;
333
+ update(orgId: string, body: UpdateOrganizationRequest): Promise<Organization>;
334
+ listUsers(): Promise<OrganizationUser[]>;
335
+ updateUser(userId: string, body: UpdateOrgUserRequest): Promise<SimpleOrgResponse>;
336
+ /** Backend currently returns 501. Surfaced for forward-compat. */
337
+ createUser(body: CreateOrganizationUserRequest): Promise<SimpleOrgResponse>;
338
+ /** Backend currently returns 501. Surfaced for forward-compat. */
339
+ deleteUser(userId: string): Promise<SimpleOrgResponse>;
340
+ /** Accept an org invite: verifies the one-time token and sets the user's password. */
341
+ acceptInvite(body: AcceptInviteRequest): Promise<SimpleOrgResponse>;
342
+ /**
343
+ * Platform-admin only: list every org for the impersonation picker.
344
+ * The server returns 403 when the caller's home org is not the
345
+ * configured ADMIN_ORGANIZATION; render the picker only when the
346
+ * authenticated user has `isPlatformAdmin === true`.
347
+ */
348
+ listAll(): Promise<Array<{
349
+ id: string;
350
+ name: string;
351
+ allowDebug: boolean;
352
+ }>>;
353
+ /**
354
+ * Platform-admin only: enable or disable the debug surface for an org.
355
+ * Returns the updated org entry with the new allowDebug value.
356
+ */
357
+ setAllowDebug(orgId: string, allow: boolean): Promise<{
358
+ id: string;
359
+ name: string;
360
+ allowDebug: boolean;
361
+ }>;
362
+ }
363
+
364
+ interface ProjectMember {
365
+ userId: string;
366
+ role: string;
367
+ user: UserSummary;
368
+ }
369
+ interface Project {
370
+ id: string;
371
+ name: string;
372
+ orgId: string;
373
+ default: boolean;
374
+ users: ProjectMember[];
375
+ }
376
+ interface CreateProjectRequest {
377
+ name: string;
378
+ }
379
+ interface UpdateProjectRequest {
380
+ name?: string;
381
+ }
382
+ interface AddMemberRequest {
383
+ userId: string;
384
+ role: AccessType | string;
385
+ }
386
+ interface UpdateMemberRoleRequest {
387
+ role: AccessType | string;
388
+ }
389
+
390
+ interface SimpleResponse$1 {
391
+ success: boolean;
392
+ message?: string;
393
+ }
394
+ declare class ProjectsClient {
395
+ private readonly http;
396
+ constructor(http: BaseClient);
397
+ list(): Promise<Project[]>;
398
+ get(projectId: string): Promise<Project>;
399
+ create(body: CreateProjectRequest): Promise<Project>;
400
+ update(projectId: string, body: UpdateProjectRequest): Promise<Project>;
401
+ delete(projectId: string): Promise<SimpleResponse$1>;
402
+ addMember(projectId: string, body: AddMemberRequest): Promise<SimpleResponse$1>;
403
+ updateMemberRole(projectId: string, userId: string, body: UpdateMemberRoleRequest): Promise<SimpleResponse$1>;
404
+ removeMember(projectId: string, userId: string): Promise<SimpleResponse$1>;
405
+ }
406
+
407
+ type StorageType = 'S3' | 'GCS' | 'BLOB';
408
+ type ModeType = 'NORMAL' | 'MIRROR';
409
+ interface Sandbox {
410
+ id: string;
411
+ name: string;
412
+ storageType: string;
413
+ mode: string;
414
+ orgId: string;
415
+ userId: string;
416
+ projectId: string | null;
417
+ createdAt: string;
418
+ disabled?: boolean;
419
+ }
420
+ interface CreateSandboxRequest {
421
+ name: string;
422
+ projectId: string;
423
+ storageType?: StorageType;
424
+ mode?: ModeType;
425
+ }
426
+ interface UpdateSandboxRequest {
427
+ name?: string;
428
+ }
429
+ interface ListSandboxesQuery {
430
+ projectId?: string;
431
+ }
432
+
433
+ interface SimpleResponse {
434
+ success: boolean;
435
+ message?: string;
436
+ }
437
+ declare class SandboxesClient {
438
+ private readonly http;
439
+ constructor(http: BaseClient);
440
+ list(query?: ListSandboxesQuery): Promise<Sandbox[]>;
441
+ get(sandboxId: string): Promise<Sandbox>;
442
+ create(body: CreateSandboxRequest): Promise<Sandbox>;
443
+ update(sandboxId: string, body: UpdateSandboxRequest): Promise<Sandbox>;
444
+ delete(sandboxId: string): Promise<SimpleResponse>;
445
+ }
446
+
447
+ type ProviderID = 'AWS' | 'BEDROCK' | 'GCP' | 'AZURE' | 'SSH' | 'GITHUB' | 'GITLAB' | 'AZURE_DEVOPS' | 'OPENAI' | 'ANTHROPIC' | 'GEMINI' | string;
448
+ interface Credential {
449
+ id: string;
450
+ provider: ProviderID;
451
+ label: string;
452
+ metadata: Record<string, unknown>;
453
+ displayHint?: string;
454
+ createdAt: string;
455
+ }
456
+ interface CreateCredentialRequest {
457
+ provider: ProviderID;
458
+ label: string;
459
+ secret: string;
460
+ metadata?: Record<string, unknown>;
461
+ projectId: string;
462
+ }
463
+ interface UpdateCredentialRequest {
464
+ label?: string;
465
+ secret?: string;
466
+ metadata?: Record<string, unknown>;
467
+ }
468
+ interface ListCredentialsQuery {
469
+ projectId: string;
470
+ provider?: ProviderID;
471
+ capability?: 'storage' | 'ai' | 'compute' | 'vcs';
472
+ }
473
+ interface SandboxCredential {
474
+ sandboxId: string;
475
+ credentialId: string;
476
+ provider: ProviderID;
477
+ label: string;
478
+ displayHint?: string;
479
+ createdAt: string;
480
+ }
481
+ interface GatewayToken {
482
+ id: string;
483
+ sandboxId: string;
484
+ label: string;
485
+ createdAt: string;
486
+ }
487
+ interface CreateGatewayTokenRequest {
488
+ label: string;
489
+ }
490
+ interface CreateGatewayTokenResponse {
491
+ token: GatewayToken;
492
+ secret: string;
493
+ }
494
+ interface SimpleKeysResponse {
495
+ success: boolean;
496
+ message?: string;
497
+ data?: unknown;
498
+ }
499
+
500
+ declare class GatewayTokensClient {
501
+ private readonly http;
502
+ constructor(http: BaseClient);
503
+ list(sandboxId: string): Promise<GatewayToken[]>;
504
+ /**
505
+ * create returns both the persisted token row and the plaintext bearer
506
+ * (`secret`). The bearer is shown only here; surface it to the user
507
+ * immediately. If they navigate away without copying, they have to
508
+ * delete the token and create a new one.
509
+ */
510
+ create(sandboxId: string, body: CreateGatewayTokenRequest): Promise<CreateGatewayTokenResponse>;
511
+ delete(sandboxId: string, tokenId: string): Promise<SimpleKeysResponse>;
512
+ }
513
+
514
+ type FieldType = 'text' | 'password' | 'number' | 'textarea' | 'pem' | 'json' | 'stringList';
515
+ interface FieldSpec {
516
+ /** JSON-pointer-ish: "secret" | "metadata.<key>". */
517
+ path: string;
518
+ label: string;
519
+ type: FieldType;
520
+ required: boolean;
521
+ /** True for fields that hold credential material — UI hides the value. */
522
+ secret?: boolean;
523
+ default?: unknown;
524
+ placeholder?: string;
525
+ help?: string;
526
+ }
527
+ declare const CAP_STORAGE = 1;
528
+ declare const CAP_AI = 2;
529
+ declare const CAP_COMPUTE = 4;
530
+ declare const CAP_VCS = 8;
531
+ declare const CAP_GENERAL = 255;
532
+ interface ProviderSpec {
533
+ id: string;
534
+ displayName: string;
535
+ /**
536
+ * Bitmask of CAP_* values describing what kinds of operations this
537
+ * credential can drive. Sourced from the Provider master table; mirror
538
+ * declared inline below so the frontend can render its tabs / filters
539
+ * without a runtime round-trip.
540
+ */
541
+ capabilities: number;
542
+ fields: FieldSpec[];
543
+ }
544
+ declare const PROVIDER_CATALOG: Record<string, ProviderSpec>;
545
+ declare function listProviders(): ProviderSpec[];
546
+ declare function getProvider(id: string): ProviderSpec | undefined;
547
+ declare function isSecretPath(path: string): boolean;
548
+ declare function isMetadataPath(path: string): path is `metadata.${string}`;
549
+ declare function metadataKey(path: string): string | undefined;
550
+ /** getValueAt reads the FieldSpec.path from a separate (secret, metadata) tuple. */
551
+ declare function getValueAt(secret: string, metadata: Record<string, unknown>, path: string): unknown;
552
+ /** setValueAt writes to (secret, metadata). Returns the updated tuple. */
553
+ declare function setValueAt(secret: string, metadata: Record<string, unknown>, path: string, value: unknown): {
554
+ secret: string;
555
+ metadata: Record<string, unknown>;
556
+ };
557
+ /**
558
+ * validate runs the structural checks for a credential payload. Returns
559
+ * an error string on failure, or null on success. Mirrors the Go-side
560
+ * Validate() in internal/providers/validators.go.
561
+ */
562
+ declare function validate(providerId: string, label: string, secret: string, metadata: Record<string, unknown>): string | null;
563
+ declare function computeDisplayHint(providerId: string, metadata: Record<string, unknown>): string;
564
+
565
+ declare class SandboxCredentialScope {
566
+ private readonly http;
567
+ constructor(http: BaseClient);
568
+ list(sandboxId: string): Promise<SandboxCredential[]>;
569
+ attach(sandboxId: string, credentialId: string): Promise<SimpleKeysResponse>;
570
+ detach(sandboxId: string, credentialId: string): Promise<SimpleKeysResponse>;
571
+ }
572
+ declare class CredentialsClient {
573
+ private readonly http;
574
+ readonly sandbox: SandboxCredentialScope;
575
+ readonly gatewayTokens: GatewayTokensClient;
576
+ constructor(http: BaseClient);
577
+ list(query: ListCredentialsQuery): Promise<Credential[]>;
578
+ create(body: CreateCredentialRequest): Promise<Credential>;
579
+ update(credentialId: string, body: UpdateCredentialRequest): Promise<Credential>;
580
+ delete(credentialId: string): Promise<SimpleKeysResponse>;
581
+ /**
582
+ * providers fetches the server-side catalog. The tsclient ships its
583
+ * own catalog mirror in ./providers.ts that the frontend can use
584
+ * synchronously; this endpoint is the runtime source of truth and
585
+ * picks up customer extensions added server-side without a tsclient
586
+ * republish.
587
+ */
588
+ providers(): Promise<ProviderSpec[]>;
589
+ }
590
+
591
+ /**
592
+ * Chat-mode types for the agent engine. The new SDK speaks `sandboxId` and
593
+ * `projectId`; the legacy `repoId` / `workspaceId` are still accepted on the
594
+ * scope tuple as fallbacks during the frontend transition.
595
+ */
596
+ interface ChatScope {
597
+ orgId: string;
598
+ userId: string;
599
+ sandboxId: string;
600
+ projectId?: string;
601
+ /** @deprecated Use `sandboxId`. Carried only to ease the cutover. */
602
+ repoId?: string;
603
+ /** @deprecated Use `projectId`. Carried only to ease the cutover. */
604
+ workspaceId?: string;
605
+ }
606
+ type ChatSessionSource = 'adhoc' | 'template';
607
+ type ChatMessageRole = 'user' | 'assistant' | 'system';
608
+ type ChatMessageKind = 'text' | 'question' | 'answer' | 'tool_call' | 'tool_result';
609
+ interface ChatSession {
610
+ id: string;
611
+ org_id: string;
612
+ workspace_id: string;
613
+ repo_id: string;
614
+ user_id: string;
615
+ title?: string;
616
+ agent_environment_id?: string;
617
+ source: ChatSessionSource;
618
+ template_id?: string;
619
+ /** M3 Stage 4: populated when this session was spawned by the
620
+ * scheduler dispatcher firing a `ChatSchedule` row. The frontend
621
+ * uses it to render the "Scheduled run" ribbon + hide the
622
+ * composer. NULL on every attended session. */
623
+ schedule_id?: string | null;
624
+ /** M3 Stage 4: mirror of `schedule_id != null` — true for sessions
625
+ * the scheduler created with `Loop.Unattended = true`. */
626
+ unattended?: boolean;
627
+ created_at: string;
628
+ updated_at: string;
629
+ last_message_at?: string | null;
630
+ /** Sum of `cost_usd_micros` across this session's `execution_receipts`.
631
+ * Populated only by list endpoints; absent on single-session fetches. */
632
+ total_cost_usd_micros?: number | null;
633
+ /** Sum of prompt + completion tokens across this session's LLM calls.
634
+ * Populated only by list endpoints; absent on single-session fetches. */
635
+ total_tokens?: number | null;
636
+ }
637
+ interface ChatMessage {
638
+ id: string;
639
+ conversation_id: string;
640
+ org_id: string;
641
+ repo_id: string;
642
+ user_id: string;
643
+ turn_id: string;
644
+ role: ChatMessageRole;
645
+ kind: ChatMessageKind;
646
+ content?: string;
647
+ plan_id?: string;
648
+ clarification_session_id?: string;
649
+ metadata?: Record<string, unknown>;
650
+ created_at: string;
651
+ }
652
+ interface CreateChatSessionRequest {
653
+ title?: string;
654
+ workspace_id: string;
655
+ repo_id: string;
656
+ agent_environment_id?: string;
657
+ source?: ChatSessionSource;
658
+ template_id?: string;
659
+ }
660
+ interface CreateChatSessionResponse {
661
+ conversation_id: string;
662
+ session: ChatSession;
663
+ }
664
+ interface ListChatSessionsResponse {
665
+ sessions: ChatSession[];
666
+ next_cursor?: string;
667
+ }
668
+ interface ListChatSessionsQuery {
669
+ cursor?: string;
670
+ limit?: number;
671
+ }
672
+ interface GetChatSessionResponse {
673
+ session: ChatSession;
674
+ messages: ChatMessage[];
675
+ }
676
+ interface PostChatMessageRequest {
677
+ text: string;
678
+ attachments?: Array<Record<string, unknown>>;
679
+ template_params?: Record<string, unknown>;
680
+ auto_approve?: boolean;
681
+ }
682
+ interface PostChatMessageResponse {
683
+ message_id: string;
684
+ turn_id: string;
685
+ }
686
+ interface AnswerChatQuestionRequest {
687
+ question_id: string;
688
+ selected_ids?: string[];
689
+ custom_text?: string;
690
+ }
691
+ interface AnswerChatQuestionResponse {
692
+ status: 'accepted';
693
+ }
694
+ /**
695
+ * Response from POST /chat/sessions/:id/messages/:turn_id/cancel — the
696
+ * Stop affordance the dashboard fires to interrupt an in-flight turn.
697
+ * The engine still emits a terminal `done` SSE event with
698
+ * status="context_cancelled" after this returns; the frontend renders a
699
+ * muted "Cancelled" marker on that event rather than on this response.
700
+ */
701
+ interface CancelChatTurnResponse {
702
+ status: 'cancelling';
703
+ turn_id: string;
704
+ }
705
+ /**
706
+ * Body the dashboard POSTs to
707
+ * /chat/sessions/:id/messages/:turn_id/confirm/:tool_call_id when the
708
+ * user clicks approve / deny on the M3 confirmation modal. `note` is
709
+ * optional free-text rationale surfaced in the synthesised
710
+ * "DENIED:" tool result on deny so the model can see *why* the user
711
+ * said no.
712
+ *
713
+ * `apply_to_session` opts the user into sticky-allow: when present
714
+ * with decision='allow', every subsequent tool call in this chat
715
+ * session that classifies into the same category dispatches without
716
+ * re-prompting. Ignored when decision='deny'. Default: false.
717
+ */
718
+ interface ConfirmChatToolCallRequest {
719
+ decision: 'allow' | 'deny';
720
+ note?: string;
721
+ apply_to_session?: boolean;
722
+ }
723
+ interface ConfirmChatToolCallResponse {
724
+ status: 'accepted';
725
+ }
726
+ /**
727
+ * Action categories the M3 policy engine recognises (see
728
+ * docs/design/chat-loop/chat-loop-m3-safety-scheduling.md §4). `read`
729
+ * is implicit / always allowed and never appears in a grant set —
730
+ * include the mutating eight in the union so the schedule editor's
731
+ * category multi-select can be typed.
732
+ */
733
+ type ActionCategory = 'write_data' | 'create_resource' | 'delete_data' | 'destroy_resource' | 'scale_capacity' | 'modify_iam' | 'modify_network' | 'execute_runtime';
734
+ /** Run status stamped on agent_chat_schedules.last_run_status. */
735
+ type ChatScheduleRunStatus = 'success' | 'blocked' | 'failed' | 'running';
736
+ /**
737
+ * ChatSchedule mirrors one row of agent_chat_schedules (M3 Stage 4).
738
+ * The scheduler dispatcher fires due rows on its tick interval and
739
+ * spawns an unattended chat session per firing — see ChatSession's
740
+ * `schedule_id` / `unattended` fields for the audit linkage.
741
+ */
742
+ interface ChatSchedule {
743
+ id: string;
744
+ org_id: string;
745
+ workspace_id?: string;
746
+ repo_id: string;
747
+ created_by_user_id: string;
748
+ name: string;
749
+ prompt: string;
750
+ cron_expr: string;
751
+ /** IANA timezone name (e.g. "Europe/Madrid"). The cron expression
752
+ * resolves in this timezone — "0 9 * * *" with timezone
753
+ * "Europe/Madrid" fires at 09:00 Madrid time, including DST
754
+ * transitions. Defaults to "UTC" on the server when omitted. */
755
+ timezone: string;
756
+ /** Subset of the repo's effective category grant. `read` is implicit
757
+ * — empty array == read-only schedule. */
758
+ granted_categories: ActionCategory[];
759
+ enabled: boolean;
760
+ max_runtime_minutes: number;
761
+ max_consecutive_failures?: number;
762
+ concurrency_policy: string;
763
+ next_fire_at?: string;
764
+ last_fire_at?: string;
765
+ last_run_status?: ChatScheduleRunStatus;
766
+ consecutive_failures: number;
767
+ total_runs: number;
768
+ total_successes: number;
769
+ created_at: string;
770
+ updated_at: string;
771
+ }
772
+ interface CreateChatScheduleRequest {
773
+ workspace_id?: string;
774
+ name: string;
775
+ prompt: string;
776
+ cron_expr: string;
777
+ /** IANA timezone (e.g. "Europe/Madrid"). Frontend should default to
778
+ * `Intl.DateTimeFormat().resolvedOptions().timeZone`. Server
779
+ * defaults to "UTC" when omitted and rejects unknown names with
780
+ * `invalid_timezone` (HTTP 400). */
781
+ timezone?: string;
782
+ granted_categories?: ActionCategory[];
783
+ /** Defaults to true on the server when omitted. */
784
+ enabled?: boolean;
785
+ max_runtime_minutes?: number;
786
+ max_consecutive_failures?: number;
787
+ concurrency_policy?: string;
788
+ }
789
+ interface UpdateChatScheduleRequest {
790
+ name?: string;
791
+ prompt?: string;
792
+ cron_expr?: string;
793
+ /** IANA timezone. Pass to change; omit to leave unchanged.
794
+ * Changing timezone alone (without cron_expr) still recomputes
795
+ * `next_fire_at` since the wall-clock target shifts. */
796
+ timezone?: string;
797
+ /** Pass an empty array to relax to read-only; omit to leave
798
+ * unchanged. */
799
+ granted_categories?: ActionCategory[];
800
+ enabled?: boolean;
801
+ max_runtime_minutes?: number;
802
+ max_consecutive_failures?: number;
803
+ concurrency_policy?: string;
804
+ }
805
+ interface ListChatSchedulesResponse {
806
+ schedules: ChatSchedule[];
807
+ }
808
+ interface ChatScheduleEnvelope {
809
+ schedule: ChatSchedule;
810
+ }
811
+ /** Response from GET /v1/agent/repos/:repo_id/schedules/:id/runs.
812
+ *
813
+ * Each entry is a full `ChatSession` row — `id` is the conversation id
814
+ * the SchedulesTab uses to navigate into the standard chat session
815
+ * viewer (which renders the unattended ribbon when `unattended` is
816
+ * true, which is always true for scheduled runs). */
817
+ interface ListChatScheduleRunsResponse {
818
+ runs: ChatSession[];
819
+ }
820
+ interface ClarificationOption {
821
+ id: string;
822
+ label: string;
823
+ description?: string;
824
+ }
825
+ type ChatEventType = 'phase' | 'question' | 'plan_draft' | 'step_started' | 'step_completed' | 'step_failed' | 'step_progress' | 'narration' | 'assistant_message' | 'done' | 'session_title' | 'tool_call_started' | 'tool_call_finished' | 'llm_call_finished' | 'tool_call_confirmation_required';
826
+ type ChatPhase = 'classifying' | 'clarifying' | 'executing' | 'answering' | 'done';
827
+ interface ChatPhasePayload {
828
+ phase: ChatPhase;
829
+ }
830
+ interface ChatQuestionPayload {
831
+ question_id: string;
832
+ prompt: string;
833
+ kind: string;
834
+ options?: ClarificationOption[];
835
+ default?: string;
836
+ role?: string;
837
+ }
838
+ interface ChatStepEventPayload {
839
+ step_id: string;
840
+ status: string;
841
+ started_at?: string;
842
+ completed_at?: string;
843
+ error?: string;
844
+ description?: string;
845
+ }
846
+ /**
847
+ * Sent with `plan_draft` once per turn when the chat-loop's model calls
848
+ * the report_plan tool to declare a multi-step task breakdown. The
849
+ * dashboard renders steps as a live checklist; matching step_started /
850
+ * step_completed / step_failed events with step_id = "step-N" move the
851
+ * checklist status as the model progresses.
852
+ */
853
+ interface ChatPlanDraftPayload {
854
+ turn_id: string;
855
+ steps: string[];
856
+ summary?: string;
857
+ }
858
+ /**
859
+ * Sent with `tool_call_started`, once per chat-loop tool dispatch BEFORE
860
+ * the tool runs. Pairs with `tool_call_finished` via tool_call_id.
861
+ */
862
+ interface ChatToolCallStartedPayload {
863
+ turn_index: number;
864
+ tool_name: string;
865
+ tool_call_id: string;
866
+ /** Short human-readable preview of the arguments, truncated. */
867
+ summary: string;
868
+ /**
869
+ * Model-authored 3–10 word user-facing description of what this call
870
+ * accomplishes (e.g. "Listing S3 buckets"). The dashboard renders this
871
+ * verbatim as the live tool-call label, replacing "Calling bash".
872
+ * Missing / empty → renderer falls back to the tool name.
873
+ */
874
+ intent?: string;
875
+ }
876
+ /**
877
+ * Sent with `tool_call_finished`, once per chat-loop tool dispatch AFTER
878
+ * the tool returns.
879
+ */
880
+ interface ChatToolCallFinishedPayload {
881
+ turn_index: number;
882
+ tool_name: string;
883
+ tool_call_id: string;
884
+ /** Short human-readable preview of stdout/stderr, truncated. */
885
+ summary: string;
886
+ }
887
+ /**
888
+ * Sent with `llm_call_finished` once per successful LLM round-trip during
889
+ * a chat-loop turn. The dashboard's budget badge uses this as a fast
890
+ * invalidation signal so the displayed spend tracks the persisted total
891
+ * in near real time, instead of waiting for the 30 s poll. Failed LLM
892
+ * calls do not emit.
893
+ */
894
+ interface ChatLLMCallFinishedPayload {
895
+ turn_index: number;
896
+ model: string;
897
+ /** USD cost in micros (1e-6 USD) attributed to this LLM call. Zero
898
+ * when no pricing row matched the model — clients should still treat
899
+ * the event as a refetch hint. */
900
+ cost_delta_micros: number;
901
+ }
902
+ /**
903
+ * Sent with `tool_call_confirmation_required` when the M3 policy hook
904
+ * classifies a tool call into a category that is permitted at the
905
+ * org/workspace/repo level but is also in the chat session's
906
+ * `confirm_categories` set — the user wants to approve each invocation
907
+ * inline before the engine dispatches it. The chat loop suspends until
908
+ * the dashboard POSTs the user's decision to
909
+ * `/v1/agent/chat/sessions/:id/messages/:turn_id/confirm/:tool_call_id`
910
+ * (or until the 4-minute confirmer timeout elapses, which is treated as
911
+ * an implicit deny — safe default).
912
+ *
913
+ * Unattended (scheduled) runs never emit this event — confirm collapses
914
+ * to deny when no human is connected.
915
+ */
916
+ interface ChatToolCallConfirmationRequiredPayload {
917
+ turn_index: number;
918
+ tool_call_id: string;
919
+ tool_name: string;
920
+ /** Truncated stringification of the tool args, suitable for the
921
+ * modal preview. Full args remain in the surrounding
922
+ * `tool_call_started` event for the debug view. */
923
+ args_preview: string;
924
+ /** One of the M3 action categories (write_data, create_resource,
925
+ * delete_data, destroy_resource, scale_capacity, modify_iam,
926
+ * modify_network, execute_runtime). */
927
+ category: string;
928
+ /** Human-readable explanation from the policy engine — e.g.
929
+ * "category \"delete_data\" requires inline confirmation". Rendered
930
+ * in the modal as a hint about *why* the agent is asking. */
931
+ rationale?: string;
932
+ }
933
+ interface ChatStepProgressPayload {
934
+ step_id: string;
935
+ message: string;
936
+ progress_pct?: number;
937
+ }
938
+ interface ChatNarrationPayload {
939
+ step_id?: string;
940
+ text: string;
941
+ }
942
+ interface ChatAssistantMessagePayload {
943
+ message_id: string;
944
+ content: string;
945
+ citations?: string[];
946
+ }
947
+ interface ChatDonePayload {
948
+ turn_id: string;
949
+ plan_id?: string;
950
+ status?: string;
951
+ /** LLM id the chat-loop ran this turn against (M2/I5). The badge
952
+ * renders this next to the spend so the user can see which model
953
+ * was selected by the per-repo provider resolver. Empty when the
954
+ * turn aborted before the resolver picked one (rare). */
955
+ model_used?: string;
956
+ }
957
+ interface ChatSessionTitlePayload {
958
+ title: string;
959
+ }
960
+ interface ChatEvent {
961
+ conversation_id: string;
962
+ turn_id: string;
963
+ type: ChatEventType;
964
+ plan_id?: string;
965
+ step_id?: string;
966
+ payload?: ChatPhasePayload | ChatQuestionPayload | ChatPlanDraftPayload | ChatStepEventPayload | ChatStepProgressPayload | ChatNarrationPayload | ChatAssistantMessagePayload | ChatDonePayload | ChatSessionTitlePayload | ChatToolCallStartedPayload | ChatToolCallFinishedPayload | ChatLLMCallFinishedPayload | ChatToolCallConfirmationRequiredPayload | unknown;
967
+ timestamp: string;
968
+ event_id?: number;
969
+ }
970
+ /**
971
+ * Per-LLM-call audit row written by the chat-loop's recorder.Record (one row
972
+ * per Chat.Completions.New call). Mirrors execution_receipts on the engine
973
+ * side. All numeric token / cost fields are nullable because they weren't
974
+ * tracked for failed calls or pre-migration rows.
975
+ */
976
+ interface DebugReceipt {
977
+ id: string;
978
+ flow_id: string;
979
+ org_id: string;
980
+ status: string;
981
+ duration_ms?: number | null;
982
+ model_used?: string | null;
983
+ layer?: string;
984
+ operation?: string;
985
+ attempt_number: number;
986
+ error?: string | null;
987
+ prompt_tokens?: number | null;
988
+ completion_tokens?: number | null;
989
+ cached_prompt_tokens?: number | null;
990
+ cost_usd_micros?: number | null;
991
+ prompt?: string | null;
992
+ response?: string | null;
993
+ created_at: string;
994
+ }
995
+ /**
996
+ * Debug surface — consolidated payload returned by
997
+ * `GET /api/agentengine/v1/agent/chat/sessions/:id/debug`.
998
+ */
999
+ interface DebugPayload {
1000
+ session: ChatSession | null;
1001
+ messages: ChatMessage[] | null;
1002
+ receipts: DebugReceipt[];
1003
+ }
1004
+
1005
+ interface OpenChatStreamOptions {
1006
+ scope: ChatScope;
1007
+ conversationId: string;
1008
+ onEvent: (event: ChatEvent) => void;
1009
+ onError?: (err: Event) => void;
1010
+ lastEventId?: string;
1011
+ /** Heartbeat in ms before the polyfill considers the connection stale. Default: 60000. */
1012
+ heartbeatTimeout?: number;
1013
+ }
1014
+ interface ChatStreamHandle {
1015
+ close(): void;
1016
+ }
1017
+
1018
+ declare class ChatSessionsScope {
1019
+ private readonly http;
1020
+ constructor(http: BaseClient);
1021
+ create(scope: ChatScope, body: CreateChatSessionRequest): Promise<CreateChatSessionResponse>;
1022
+ list(scope: ChatScope, query?: ListChatSessionsQuery): Promise<ListChatSessionsResponse>;
1023
+ get(scope: ChatScope, conversationId: string): Promise<GetChatSessionResponse>;
1024
+ delete(scope: ChatScope, conversationId: string): Promise<void>;
1025
+ }
1026
+ declare class ChatMessagesScope {
1027
+ private readonly http;
1028
+ constructor(http: BaseClient);
1029
+ post(scope: ChatScope, conversationId: string, body: PostChatMessageRequest): Promise<PostChatMessageResponse>;
1030
+ /**
1031
+ * Interrupts an in-flight chat-loop turn. The engine cancels the turn's
1032
+ * Go context and asks the sandbox service to kill any in-flight docker
1033
+ * exec inside the per-session container (the container itself survives
1034
+ * so the next turn keeps its filesystem state). Returns 404 when no
1035
+ * turn matches `turnId` — covers the race where the user clicks Stop
1036
+ * just after the turn already finished.
1037
+ *
1038
+ * The engine still emits a terminal `done` SSE event with
1039
+ * status="context_cancelled" after this returns; the frontend should
1040
+ * render its "Cancelled" marker on that event rather than on this
1041
+ * response, so a reload mid-cancel still ends in the same UI state.
1042
+ */
1043
+ cancel(scope: ChatScope, conversationId: string, turnId: string): Promise<CancelChatTurnResponse>;
1044
+ /**
1045
+ * Deliver the user's allow/deny decision on an M3 confirmation modal
1046
+ * (fired when the policy hook emits a
1047
+ * `tool_call_confirmation_required` SSE event). The chat-loop has
1048
+ * suspended waiting on this call; on allow it dispatches the tool, on
1049
+ * deny it synthesises a "DENIED:" tool result so the model can react.
1050
+ * Returns 404 when no pending confirmation exists for the given
1051
+ * (turn, tool_call) — usually means the 4-minute confirmer timeout
1052
+ * already elapsed.
1053
+ */
1054
+ confirmToolCall(scope: ChatScope, conversationId: string, turnId: string, toolCallId: string, body: ConfirmChatToolCallRequest): Promise<ConfirmChatToolCallResponse>;
1055
+ }
1056
+ declare class ChatQuestionsScope {
1057
+ private readonly http;
1058
+ constructor(http: BaseClient);
1059
+ answer(scope: ChatScope, conversationId: string, turnId: string, body: AnswerChatQuestionRequest): Promise<AnswerChatQuestionResponse>;
1060
+ }
1061
+ /**
1062
+ * Debug scope — fetches the consolidated payload (session, messages) used by
1063
+ * the dashboard Debug tab. Keyed by conversation ID.
1064
+ */
1065
+ declare class ChatDebugScope {
1066
+ private readonly http;
1067
+ constructor(http: BaseClient);
1068
+ getByConversation(scope: ChatScope, conversationId: string): Promise<DebugPayload>;
1069
+ }
1070
+ /**
1071
+ * Schedules scope — manages the M3 Stage 4 cron-driven prompt
1072
+ * schedules. Repo-scoped: list / create / get / update / delete are
1073
+ * keyed by (repo, schedule_id). The dispatcher fires due schedules
1074
+ * server-side on its tick; the SDK only handles the CRUD surface.
1075
+ *
1076
+ * Endpoint shape:
1077
+ * GET /v1/agent/repos/:repo_id/schedules
1078
+ * POST /v1/agent/repos/:repo_id/schedules
1079
+ * GET /v1/agent/repos/:repo_id/schedules/:id
1080
+ * PUT /v1/agent/repos/:repo_id/schedules/:id
1081
+ * DELETE /v1/agent/repos/:repo_id/schedules/:id
1082
+ */
1083
+ declare class ChatSchedulesScope {
1084
+ private readonly http;
1085
+ constructor(http: BaseClient);
1086
+ private repoPath;
1087
+ list(scope: ChatScope): Promise<ListChatSchedulesResponse>;
1088
+ create(scope: ChatScope, body: CreateChatScheduleRequest): Promise<ChatScheduleEnvelope>;
1089
+ get(scope: ChatScope, scheduleId: string): Promise<ChatScheduleEnvelope>;
1090
+ update(scope: ChatScope, scheduleId: string, body: UpdateChatScheduleRequest): Promise<ChatScheduleEnvelope>;
1091
+ delete(scope: ChatScope, scheduleId: string): Promise<{
1092
+ status: 'deleted';
1093
+ }>;
1094
+ /**
1095
+ * List recent chat sessions spawned by a schedule's cron tick — used
1096
+ * by the SchedulesTab "Runs" panel to surface real audit trail
1097
+ * instead of dumping the user into the global chat list.
1098
+ *
1099
+ * Each entry is a full ChatSession row; `.id` is the conversation id
1100
+ * the dashboard navigates to (`/chat/:conversationId`). All rows are
1101
+ * unattended (the scheduler is the only writer of `schedule_id`),
1102
+ * which makes the chat session viewer render the "Scheduled run"
1103
+ * ribbon and hide the composer.
1104
+ *
1105
+ * Server returns the 50 most-recent rows; no cursor pagination in
1106
+ * v1 (deferred until the long-tail audit case proves real).
1107
+ */
1108
+ listRuns(scope: ChatScope, scheduleId: string): Promise<ListChatScheduleRunsResponse>;
1109
+ }
1110
+ declare class ChatClient {
1111
+ private readonly http;
1112
+ private readonly streamDeps;
1113
+ readonly sessions: ChatSessionsScope;
1114
+ readonly messages: ChatMessagesScope;
1115
+ readonly questions: ChatQuestionsScope;
1116
+ readonly debug: ChatDebugScope;
1117
+ readonly schedules: ChatSchedulesScope;
1118
+ constructor(http: BaseClient, streamDeps: {
1119
+ baseUrl: string;
1120
+ getToken?: TokenProvider;
1121
+ });
1122
+ openStream(options: OpenChatStreamOptions): Promise<ChatStreamHandle>;
1123
+ }
1124
+
1125
+ interface Template {
1126
+ id: string;
1127
+ org_id: string;
1128
+ workspace_id?: string;
1129
+ repo_id?: string;
1130
+ name: string;
1131
+ description?: string;
1132
+ prompt?: string;
1133
+ blueprint?: Record<string, unknown>;
1134
+ trust_level?: string;
1135
+ /** AWS | GCP | AZURE — drives discovery UI (icons, etc.). */
1136
+ cloud_provider?: string;
1137
+ created_at: string;
1138
+ updated_at: string;
1139
+ }
1140
+ interface CreateAgentTemplateRequest {
1141
+ name: string;
1142
+ description?: string;
1143
+ prompt: string;
1144
+ workspace_id?: string;
1145
+ repo_id?: string;
1146
+ }
1147
+ interface ListAgentTemplatesQuery {
1148
+ workspace_id?: string;
1149
+ repo_id?: string;
1150
+ cursor?: string;
1151
+ limit?: number;
1152
+ }
1153
+ interface ListAgentTemplatesResponse {
1154
+ templates: Template[];
1155
+ next_cursor?: string;
1156
+ }
1157
+ interface SimpleAgentResponse {
1158
+ status?: string;
1159
+ success?: boolean;
1160
+ message?: string;
1161
+ }
1162
+ interface FineTuneParams {
1163
+ [key: string]: unknown;
1164
+ }
1165
+ interface ScheduledTask {
1166
+ id: string;
1167
+ org_id: string;
1168
+ template_id: string;
1169
+ name: string;
1170
+ cron: string;
1171
+ timezone?: string;
1172
+ enabled: boolean;
1173
+ fine_tune?: FineTuneParams;
1174
+ created_at: string;
1175
+ updated_at: string;
1176
+ }
1177
+ interface CreateScheduledTaskRequest {
1178
+ template_id: string;
1179
+ name: string;
1180
+ cron: string;
1181
+ timezone?: string;
1182
+ enabled?: boolean;
1183
+ fine_tune?: FineTuneParams;
1184
+ }
1185
+ interface ListScheduledTasksQuery {
1186
+ org_id: string;
1187
+ template_id?: string;
1188
+ cursor?: string;
1189
+ limit?: number;
1190
+ }
1191
+ interface ListScheduledTasksResponse {
1192
+ tasks: ScheduledTask[];
1193
+ next_cursor?: string;
1194
+ }
1195
+
1196
+ declare class TemplatesClient {
1197
+ private readonly http;
1198
+ constructor(http: BaseClient);
1199
+ list(query?: ListAgentTemplatesQuery): Promise<ListAgentTemplatesResponse>;
1200
+ create(body: CreateAgentTemplateRequest): Promise<Template>;
1201
+ delete(templateId: string): Promise<SimpleAgentResponse>;
1202
+ }
1203
+
1204
+ declare class ScheduledTasksClient {
1205
+ private readonly http;
1206
+ constructor(http: BaseClient);
1207
+ list(query: ListScheduledTasksQuery): Promise<ListScheduledTasksResponse>;
1208
+ create(body: CreateScheduledTaskRequest): Promise<ScheduledTask>;
1209
+ delete(taskId: string, orgId: string): Promise<SimpleAgentResponse>;
1210
+ }
1211
+
1212
+ interface ResourceTreeResource {
1213
+ id: string;
1214
+ name: string;
1215
+ resourceProviderId: string;
1216
+ region: string | null;
1217
+ accessLevel: string | null;
1218
+ isActive: boolean;
1219
+ metadata?: Record<string, unknown>;
1220
+ }
1221
+ interface ResourceTreeCategory {
1222
+ name: string;
1223
+ resources: ResourceTreeResource[];
1224
+ }
1225
+ interface ResourceTreeGrouping {
1226
+ id: string;
1227
+ name: string;
1228
+ providerGroupingId: string;
1229
+ groupingTypeId: string;
1230
+ groupingTypeName: string;
1231
+ level: string;
1232
+ children: ResourceTreeGrouping[];
1233
+ categories: ResourceTreeCategory[];
1234
+ }
1235
+ interface ResourceTreeCredential {
1236
+ credentialId: string | null;
1237
+ provider: string;
1238
+ groupings: ResourceTreeGrouping[];
1239
+ }
1240
+ interface ResourceTreeResponse {
1241
+ success: boolean;
1242
+ repoId: string;
1243
+ credentials: ResourceTreeCredential[];
1244
+ }
1245
+ interface ResourceTreeQuery {
1246
+ /** Case-insensitive substring filter applied to resource leaf names. */
1247
+ search?: string;
1248
+ /**
1249
+ * When false (default), default auto-provisioned network resources
1250
+ * (e.g. AWS default VPCs/subnets, GCP "default" network) are hidden.
1251
+ * Pass true to include them.
1252
+ */
1253
+ showDefault?: boolean;
1254
+ }
1255
+ /** Direction of edge traversal during the BFS expansion. */
1256
+ type SubgraphDirection = 'out' | 'in' | 'both';
1257
+ interface SubgraphRequest {
1258
+ /** Resource ids to start the BFS from. Either this or seedNameTokens must be non-empty. */
1259
+ seedResourceIds?: string[];
1260
+ /** Case-insensitive substring matches against CloudResource.name. */
1261
+ seedNameTokens?: string[];
1262
+ /** Default 2 on the server. */
1263
+ depth?: number;
1264
+ /** Filter to specific edge kinds (e.g. "writes_to", "reads_from"). */
1265
+ edgeKinds?: string[];
1266
+ /** Filter to specific edge domains (e.g. "data", "auth"). */
1267
+ edgeDomains?: string[];
1268
+ /** Default "both". */
1269
+ direction?: SubgraphDirection;
1270
+ /** Default 80, hard cap 200. */
1271
+ maxNodes?: number;
1272
+ }
1273
+ interface CloudResourceContainerRef {
1274
+ id: string;
1275
+ name: string;
1276
+ providerGroupingId: string;
1277
+ groupingType?: {
1278
+ id: string;
1279
+ providerId: string;
1280
+ level: string;
1281
+ name: string;
1282
+ description: string;
1283
+ };
1284
+ }
1285
+ interface CloudResource {
1286
+ id: string;
1287
+ repoId: string;
1288
+ credentialId?: string | null;
1289
+ providerId: string;
1290
+ categoryName: string;
1291
+ groupingId: string;
1292
+ resourceProviderId: string;
1293
+ name: string;
1294
+ region: string;
1295
+ accessLevel: string;
1296
+ metadata: Record<string, unknown> | null;
1297
+ discoveredAt: string;
1298
+ lastSeenAt: string;
1299
+ isActive: boolean;
1300
+ container?: CloudResourceContainerRef | null;
1301
+ groupingPath?: string;
1302
+ }
1303
+ /**
1304
+ * Directed dependency edge. Reads as "src depends on dst" (delete dst,
1305
+ * src breaks). edgeDomain is a tag set (e.g. ["data", "control"]).
1306
+ */
1307
+ interface CloudResourceEdge {
1308
+ id: string;
1309
+ repoId: string;
1310
+ srcResourceId: string;
1311
+ dstResourceId: string;
1312
+ edgeKind: string;
1313
+ edgeDomain: string[];
1314
+ attributes: Record<string, unknown> | null;
1315
+ discoveredAt: string;
1316
+ lastSeenAt: string;
1317
+ isActive: boolean;
1318
+ }
1319
+ interface SubgraphResponse {
1320
+ success: boolean;
1321
+ nodes: CloudResource[];
1322
+ edges: CloudResourceEdge[];
1323
+ /** True when the BFS hit maxNodes before exhausting the requested depth. */
1324
+ truncated: boolean;
1325
+ }
1326
+ /**
1327
+ * One live scan-coordination row. At most one per (repoId, credentialId)
1328
+ * at any time. Expired leases (expiresAt < now) are reclaimable by the
1329
+ * next AcquireScanLease call — they should NOT be rendered as "active"
1330
+ * in the UI.
1331
+ */
1332
+ interface CloudScanLease {
1333
+ repoId: string;
1334
+ credentialId: string;
1335
+ leaseId: string;
1336
+ startedAt: string;
1337
+ expiresAt: string;
1338
+ /**
1339
+ * Free-form metadata the agent passed in (regions, providers,
1340
+ * tenant scope). The dashboard renders this verbatim when surfacing
1341
+ * "another scan is running" notices so the user knows what's blocked.
1342
+ */
1343
+ scopeHint?: Record<string, unknown> | null;
1344
+ }
1345
+ /**
1346
+ * Append-only history of completed scans. Drives the "last refreshed at"
1347
+ * badge and the per-scope deltas (added / removed) shown next to the
1348
+ * resource tree.
1349
+ */
1350
+ interface CloudScanHistory {
1351
+ id: string;
1352
+ repoId: string;
1353
+ credentialId: string;
1354
+ startedAt: string;
1355
+ endedAt: string;
1356
+ status: 'completed' | 'partial' | 'failed' | 'expired';
1357
+ /** The ReconcileScope that was applied, when present. */
1358
+ scope?: ReconcileScope | null;
1359
+ resourcesUpserted: number;
1360
+ resourcesRemoved: number;
1361
+ partialFailureCount: number;
1362
+ }
1363
+ /**
1364
+ * Tells the backend "I scanned these (tenant, region) tuples to
1365
+ * completion." The backend hard-deletes any prior resource in the listed
1366
+ * scopes that was not in this run's payload — that's how the tree
1367
+ * shrinks when cloud resources are torn down. Tuples with any partial /
1368
+ * failed collector are deliberately omitted by the agent so partial
1369
+ * scans never wipe data.
1370
+ */
1371
+ interface ReconcileScope {
1372
+ tuples: ReconcileTuple[];
1373
+ }
1374
+ interface ReconcileTuple {
1375
+ /** Tenant native id (AWS account number, GCP project, Azure subscription guid). */
1376
+ tenantLocalKey: string;
1377
+ /** Exact region match. Honours "*" / "global" / empty for non-regional services. */
1378
+ region: string;
1379
+ }
1380
+ /**
1381
+ * 409 body returned by POST /repos/:repoId/scans/lease when another scan
1382
+ * is already in flight for the same (repoId, credentialId). The frontend
1383
+ * is expected to surface `inProgress.scopeHint` + a friendly age-elapsed
1384
+ * label so the user knows when to retry.
1385
+ */
1386
+ interface ScanInProgressError {
1387
+ success: false;
1388
+ message: string;
1389
+ inProgress: CloudScanLease;
1390
+ }
1391
+ interface AcquireScanLeaseRequest {
1392
+ credentialId: string;
1393
+ /** Clamped server-side to [60, 3600]; default 2100. */
1394
+ ttlSeconds?: number;
1395
+ scopeHint?: Record<string, unknown>;
1396
+ }
1397
+ interface AcquireScanLeaseResponse {
1398
+ success: true;
1399
+ lease: CloudScanLease;
1400
+ }
1401
+ interface ListScanHistoryQuery {
1402
+ credentialId?: string;
1403
+ /** Clamped server-side to [1, 100]; default 20. */
1404
+ limit?: number;
1405
+ }
1406
+ interface ListScanHistoryResponse {
1407
+ success: boolean;
1408
+ scans: CloudScanHistory[];
1409
+ }
1410
+ interface PeekScanLeaseResponse {
1411
+ success: boolean;
1412
+ /** null when no lease exists for (repoId, credentialId). */
1413
+ lease: CloudScanLease | null;
1414
+ }
1415
+
1416
+ declare class ResourcesClient {
1417
+ private readonly http;
1418
+ constructor(http: BaseClient);
1419
+ getTree(repoId: string, query?: ResourceTreeQuery): Promise<ResourceTreeResponse>;
1420
+ /**
1421
+ * BFS-walks the dependency graph starting from `seedResourceIds` (or
1422
+ * `seedNameTokens`) and returns the matching nodes + edges. Use this
1423
+ * to render an inbound/outbound dependency view for a selected
1424
+ * resource. The server caps the result at maxNodes (default 80,
1425
+ * hard cap 200) and sets `truncated` when the cap was hit.
1426
+ */
1427
+ getSubgraph(repoId: string, request: SubgraphRequest): Promise<SubgraphResponse>;
1428
+ /**
1429
+ * Returns recent scan history for a repo, optionally filtered by
1430
+ * credential. Backed by CloudScanHistory rows written when the
1431
+ * agent's discovery orchestrator releases a lease (or when the
1432
+ * backend's cleanup job sweeps an expired one). Use this to render
1433
+ * "last refreshed N min ago" badges and per-scope add/remove counts
1434
+ * next to the resource tree.
1435
+ */
1436
+ listScans(repoId: string, query?: ListScanHistoryQuery): Promise<ListScanHistoryResponse>;
1437
+ /**
1438
+ * Peeks the active scan lease (if any) for the given credential. Used
1439
+ * by the dashboard to display a "scan in progress" badge without
1440
+ * attempting to acquire the lease. Returns `lease: null` when no
1441
+ * scan is running. Expired leases are returned with their stale
1442
+ * timestamps — callers should compare `expiresAt` to `Date.now()`
1443
+ * before treating them as active.
1444
+ */
1445
+ peekScanLease(repoId: string, credentialId: string): Promise<PeekScanLeaseResponse>;
1446
+ /**
1447
+ * Attempts to claim a scan lease. Returns the acquired lease on
1448
+ * success. The server responds 409 with a `ScanInProgressError`-
1449
+ * shaped body when another scan is already in flight — callers
1450
+ * should catch the HttpError, parse the body, and surface a polite
1451
+ * "another scan is running" notice rather than retry automatically.
1452
+ *
1453
+ * NOTE: routine use is the agent's job. The dashboard typically only
1454
+ * calls peekScanLease + listScans; this method is exposed for power-
1455
+ * user tooling and automated test harnesses.
1456
+ */
1457
+ acquireScanLease(repoId: string, request: AcquireScanLeaseRequest): Promise<AcquireScanLeaseResponse>;
1458
+ }
1459
+
1460
+ interface SystemEvent {
1461
+ id: number;
1462
+ timestamp: string;
1463
+ contextId: string;
1464
+ context: string;
1465
+ event: string;
1466
+ orgId: string;
1467
+ userId: string;
1468
+ userName: string;
1469
+ userEmail: string;
1470
+ projectId: string | null;
1471
+ jsonData: string | null;
1472
+ showUnread: boolean;
1473
+ }
1474
+ interface SystemEventQuery {
1475
+ from_timestamp?: number;
1476
+ to_timestamp?: number;
1477
+ contextId?: string;
1478
+ context?: string;
1479
+ event?: string;
1480
+ userId?: string;
1481
+ projectId?: string;
1482
+ /** @deprecated use `projectId` */
1483
+ workspaceId?: string;
1484
+ showUnread?: boolean;
1485
+ skip?: number;
1486
+ take?: number;
1487
+ }
1488
+ interface SystemEventQueryResponse {
1489
+ events: SystemEvent[];
1490
+ total: number;
1491
+ skip: number;
1492
+ take: number;
1493
+ }
1494
+ interface SystemEventReadResponse {
1495
+ success: true;
1496
+ }
1497
+
1498
+ declare class SystemEventsClient {
1499
+ private readonly http;
1500
+ constructor(http: BaseClient);
1501
+ query(body: SystemEventQuery): Promise<SystemEventQueryResponse>;
1502
+ markRead(eventIdOrIds: number | number[]): Promise<SystemEventReadResponse>;
1503
+ markUnread(eventIdOrIds: number | number[]): Promise<SystemEventReadResponse>;
1504
+ }
1505
+
1506
+ interface SubscriptionPeriod {
1507
+ id: string;
1508
+ name: string;
1509
+ amount: number;
1510
+ currency: string;
1511
+ interval: string;
1512
+ intervalCount?: number;
1513
+ /** Per-period grant in USD-cents. 0 means no grant attached. */
1514
+ creditsGrantedCents: number;
1515
+ }
1516
+ interface SubscriptionCapability {
1517
+ key: string;
1518
+ label?: string;
1519
+ limit?: number | null;
1520
+ }
1521
+ interface Subscription {
1522
+ id: string;
1523
+ name: string;
1524
+ description?: string;
1525
+ periods: SubscriptionPeriod[];
1526
+ capabilities: SubscriptionCapability[];
1527
+ /** Plan-level 24h rolling debit cap in USD-cents. null = no cap. */
1528
+ dailyCreditCapCents?: number | null;
1529
+ }
1530
+ interface OrgSubscription {
1531
+ id: string;
1532
+ subscriptionId: string;
1533
+ subscriptionName: string;
1534
+ status: string;
1535
+ currentPeriodStart?: string;
1536
+ currentPeriodEnd?: string;
1537
+ cancelAt?: string | null;
1538
+ capabilities: SubscriptionCapability[];
1539
+ }
1540
+ interface BuySubscriptionRequest {
1541
+ subscriptionPeriodId: string;
1542
+ }
1543
+ interface BuySubscriptionResponse {
1544
+ success: boolean;
1545
+ checkoutUrl?: string;
1546
+ sessionId?: string;
1547
+ isSubscriptionChange?: boolean;
1548
+ previousSubscription?: {
1549
+ id: string;
1550
+ name: string;
1551
+ } | null;
1552
+ isFreeSubscription?: boolean;
1553
+ message?: string;
1554
+ }
1555
+ interface CancelSubscriptionResponse {
1556
+ success: boolean;
1557
+ message?: string;
1558
+ }
1559
+ interface Payment {
1560
+ id: string;
1561
+ status: string;
1562
+ amount: number;
1563
+ currency: string;
1564
+ createdAt: string;
1565
+ description?: string;
1566
+ }
1567
+ interface ListPaymentsResponse {
1568
+ success: boolean;
1569
+ data: Payment[];
1570
+ }
1571
+ /**
1572
+ * Org credit balance — two-bucket forfeit model (billing-v1).
1573
+ *
1574
+ * - permanentCreditCents: PAYG (credit-pack) bucket. Never expires.
1575
+ * - subscriptionCreditCents: Current subscription cycle. Forfeit on
1576
+ * renewal; expires at subscriptionCreditExpiresAt.
1577
+ * - subscriptionCreditExpiresAt: ISO-8601; null when no subscription is active.
1578
+ * - totalActiveCents: Pre-computed sum = permanent +
1579
+ * (subscription if not expired). Use this
1580
+ * to drive the daily-cap progress bar
1581
+ * and "out of credits" check.
1582
+ *
1583
+ * Format `(value / 100).toFixed(2)` for display. Drain order is
1584
+ * subscription bucket first, then permanent — visualise as a single
1585
+ * pool with a small "expires soon" tag for the subscription slice.
1586
+ *
1587
+ * Legacy `realtimeBalance` / `pendingConsumption` / `breakdown` /
1588
+ * `dateBalance` fields were dropped: the chat-loop debits in real-time
1589
+ * so there is no notion of "pending".
1590
+ */
1591
+ interface CreditBalance {
1592
+ permanentCreditCents: number;
1593
+ subscriptionCreditCents: number;
1594
+ subscriptionCreditExpiresAt: string | null;
1595
+ totalActiveCents: number;
1596
+ }
1597
+ /** Source of a credit ledger row. Matches the kind enum from migration 0017. */
1598
+ type CreditTransactionKind = 'grant_initial' | 'grant_renewal' | 'grant_pack' | 'debit_llm' | 'debit_sandbox' | 'admin_adjust';
1599
+ /** Display category for the transactions list. */
1600
+ type CreditTransactionType = 'consumption' | 'purchase' | 'grant';
1601
+ interface CreditTransaction {
1602
+ id: string;
1603
+ /** Signed amount in USD-cents. Negative = debit. */
1604
+ creditAmountCents: number;
1605
+ kind: CreditTransactionKind;
1606
+ type: CreditTransactionType;
1607
+ description?: string;
1608
+ createdAt: string;
1609
+ repoId?: string;
1610
+ executionReceiptId?: string;
1611
+ sandboxSessionDebitId?: string;
1612
+ subscriptionName?: string;
1613
+ packName?: string;
1614
+ }
1615
+ interface ListCreditsTransactionsQuery {
1616
+ from?: string;
1617
+ to?: string;
1618
+ type?: string;
1619
+ page?: number;
1620
+ limit?: number;
1621
+ }
1622
+ interface ListCreditsTransactionsResponse {
1623
+ success: boolean;
1624
+ data: CreditTransaction[];
1625
+ pagination?: {
1626
+ total: number;
1627
+ page: number;
1628
+ limit: number;
1629
+ };
1630
+ }
1631
+ /** One month's bucket of credit activity. All money values in USD-cents. */
1632
+ interface MonthlyCreditStats {
1633
+ month: string;
1634
+ consumptionCents: number;
1635
+ purchasesCents: number;
1636
+ grantsCents: number;
1637
+ balanceCents: number;
1638
+ }
1639
+ /**
1640
+ * Refusal reasons from POST /v1/agent/chat/sessions/:id/messages when
1641
+ * the billing preflight rejects a turn (HTTP 402). Frontend maps these
1642
+ * to typed toasts. Mirrors billing.Refuse* in cloud-agent.
1643
+ */
1644
+ type ChatBillingRefuseCode = 'out_of_credits' | 'daily_cap_reached' | 'no_subscription';
1645
+ interface ChatBillingRefuseError {
1646
+ message: string;
1647
+ code: ChatBillingRefuseCode;
1648
+ permanentCreditCents: number;
1649
+ subscriptionCreditCents: number;
1650
+ subscriptionCreditExpiresAt: string | null;
1651
+ totalActiveCents: number;
1652
+ dailyCapCents: number;
1653
+ debitedLast24hCents: number;
1654
+ }
1655
+
1656
+ declare class SubscriptionsClient {
1657
+ private readonly http;
1658
+ constructor(http: BaseClient);
1659
+ listCatalog(): Promise<Subscription[]>;
1660
+ getMine(): Promise<OrgSubscription | null>;
1661
+ buy(body: BuySubscriptionRequest): Promise<BuySubscriptionResponse>;
1662
+ cancel(): Promise<CancelSubscriptionResponse>;
1663
+ listPayments(): Promise<Payment[]>;
1664
+ /** Stripe-hosted billing portal URL. */
1665
+ portal(): Promise<{
1666
+ url: string;
1667
+ }>;
1668
+ }
1669
+
1670
+ declare class CreditsClient {
1671
+ private readonly http;
1672
+ constructor(http: BaseClient);
1673
+ getBalance(): Promise<CreditBalance>;
1674
+ listTransactions(query?: ListCreditsTransactionsQuery): Promise<ListCreditsTransactionsResponse>;
1675
+ /** Backend currently returns 501. Surfaced for forward-compat. */
1676
+ getMonthlyStats(): Promise<MonthlyCreditStats[]>;
1677
+ }
1678
+
1679
+ interface UsageWindow {
1680
+ from: string;
1681
+ to: string;
1682
+ prompt: number;
1683
+ completion: number;
1684
+ cached_prompt: number;
1685
+ total: number;
1686
+ cost_usd_micros: number;
1687
+ calls: number;
1688
+ }
1689
+ interface UsageBucket {
1690
+ day: string;
1691
+ prompt: number;
1692
+ completion: number;
1693
+ cached_prompt: number;
1694
+ total: number;
1695
+ cost_usd_micros: number;
1696
+ calls: number;
1697
+ }
1698
+ interface UsageTotals {
1699
+ prompt: number;
1700
+ completion: number;
1701
+ cached_prompt: number;
1702
+ total: number;
1703
+ cost_usd_micros: number;
1704
+ calls: number;
1705
+ }
1706
+ interface UsageSummaryQuery {
1707
+ flow_kind?: 'chat' | 'template' | 'scheduled';
1708
+ model?: string;
1709
+ }
1710
+ interface UsageReportQuery extends UsageSummaryQuery {
1711
+ from?: string;
1712
+ to?: string;
1713
+ bucket?: 'hour' | 'day';
1714
+ }
1715
+ interface UsageByModelQuery extends UsageSummaryQuery {
1716
+ from?: string;
1717
+ to?: string;
1718
+ }
1719
+ interface UsageSummaryResponse {
1720
+ windows: Record<'24h' | '7d' | '30d', UsageWindow>;
1721
+ }
1722
+ interface UsageReportResponse {
1723
+ from: string;
1724
+ to: string;
1725
+ bucket: 'hour' | 'day';
1726
+ rows: UsageBucket[];
1727
+ totals: UsageTotals;
1728
+ }
1729
+ interface UsageByModelRow {
1730
+ model: string;
1731
+ prompt: number;
1732
+ completion: number;
1733
+ cached_prompt: number;
1734
+ total: number;
1735
+ cost_usd_micros: number;
1736
+ calls: number;
1737
+ }
1738
+ interface UsageByModelResponse {
1739
+ from: string;
1740
+ to: string;
1741
+ rows: UsageByModelRow[];
1742
+ }
1743
+ interface GetUsageSummaryQuery {
1744
+ org_id: string;
1745
+ from?: string;
1746
+ to?: string;
1747
+ template_id?: string;
1748
+ }
1749
+ interface UsageSummary {
1750
+ window: {
1751
+ from: string;
1752
+ to: string;
1753
+ };
1754
+ totals: {
1755
+ flows: number;
1756
+ successful: number;
1757
+ failed: number;
1758
+ cost_usd: number;
1759
+ tokens_in: number;
1760
+ tokens_out: number;
1761
+ };
1762
+ }
1763
+ interface GetUsageSummaryResponse {
1764
+ summary: UsageSummary;
1765
+ }
1766
+
1767
+ declare class UsageClient {
1768
+ private readonly http;
1769
+ constructor(http: BaseClient);
1770
+ getSummary(query: GetUsageSummaryQuery): Promise<GetUsageSummaryResponse>;
1771
+ org(query?: UsageSummaryQuery): Promise<UsageSummaryResponse>;
1772
+ project(projectId: string, query?: UsageSummaryQuery): Promise<UsageSummaryResponse>;
1773
+ sandbox(sandboxId: string, query?: UsageSummaryQuery): Promise<UsageSummaryResponse>;
1774
+ chat(chatId: string, query?: UsageSummaryQuery): Promise<UsageSummaryResponse>;
1775
+ orgReport(query?: UsageReportQuery): Promise<UsageReportResponse>;
1776
+ projectReport(projectId: string, query?: UsageReportQuery): Promise<UsageReportResponse>;
1777
+ sandboxReport(sandboxId: string, query?: UsageReportQuery): Promise<UsageReportResponse>;
1778
+ chatReport(chatId: string, query?: UsageReportQuery): Promise<UsageReportResponse>;
1779
+ orgByModel(query?: UsageByModelQuery): Promise<UsageByModelResponse>;
1780
+ projectByModel(projectId: string, query?: UsageByModelQuery): Promise<UsageByModelResponse>;
1781
+ sandboxByModel(sandboxId: string, query?: UsageByModelQuery): Promise<UsageByModelResponse>;
1782
+ chatByModel(chatId: string, query?: UsageByModelQuery): Promise<UsageByModelResponse>;
1783
+ }
1784
+
1785
+ type BudgetScope = 'org' | 'workspace' | 'repo' | 'chat';
1786
+ interface OrgBudget {
1787
+ id: string;
1788
+ org_id: string;
1789
+ daily_limit: number;
1790
+ monthly_limit: number;
1791
+ tokens_today: number;
1792
+ tokens_month: number;
1793
+ daily_cost_limit_usd_micros: number;
1794
+ monthly_cost_limit_usd_micros: number;
1795
+ cost_today_usd_micros: number;
1796
+ cost_month_usd_micros: number;
1797
+ chat_session_cost_limit_usd_micros: number;
1798
+ reset_day_at: string;
1799
+ reset_month_at: string;
1800
+ updated_at: string;
1801
+ /** M3 Stage 3: action categories allowed at this scope. `read` is
1802
+ * implicit and never appears here. Lower scopes (workspace, repo,
1803
+ * schedule) intersect with this set. */
1804
+ granted_categories: string[];
1805
+ /** M3 Stage 4: inheritable schedule auto-disable threshold. Null
1806
+ * means "inherit from parent"; engine default is 5 when every
1807
+ * level in the chain is null. */
1808
+ max_consecutive_failures?: number;
1809
+ }
1810
+ interface ScopedBudget {
1811
+ id: string;
1812
+ org_id: string;
1813
+ workspace_id?: string;
1814
+ repo_id?: string;
1815
+ daily_cost_limit_usd_micros: number;
1816
+ monthly_cost_limit_usd_micros: number;
1817
+ chat_session_cost_limit_usd_micros: number;
1818
+ cost_today_usd_micros: number;
1819
+ cost_month_usd_micros: number;
1820
+ reset_day_at: string;
1821
+ reset_month_at: string;
1822
+ updated_at: string;
1823
+ /** M3 Stage 3: see OrgBudget.granted_categories. Subset of parent. */
1824
+ granted_categories: string[];
1825
+ /** M3 Stage 4: see OrgBudget.max_consecutive_failures. */
1826
+ max_consecutive_failures?: number;
1827
+ }
1828
+ interface ChatBudget {
1829
+ id: string;
1830
+ org_id: string;
1831
+ workspace_id: string;
1832
+ repo_id: string;
1833
+ chat_session_id: string;
1834
+ cost_limit_usd_micros: number;
1835
+ cost_total_usd_micros: number;
1836
+ created_by_user_id: string;
1837
+ updated_at: string;
1838
+ }
1839
+ interface EffectiveChatBudget {
1840
+ limit_usd_micros: number;
1841
+ source: BudgetScope;
1842
+ spent_usd_micros: number;
1843
+ }
1844
+ interface UpdateOrgBudgetRequest {
1845
+ daily_cost_limit_usd_micros?: number;
1846
+ monthly_cost_limit_usd_micros?: number;
1847
+ chat_session_cost_limit_usd_micros?: number;
1848
+ /** M3 Stage 3: replace the action-category grant set. Omit to leave
1849
+ * unchanged; empty array relaxes to read-only. */
1850
+ granted_categories?: string[];
1851
+ /** M3 Stage 4: per-scope schedule auto-disable cap. Omit to leave
1852
+ * unchanged. */
1853
+ max_consecutive_failures?: number;
1854
+ }
1855
+ interface UpdateScopedBudgetRequest {
1856
+ daily_cost_limit_usd_micros?: number;
1857
+ monthly_cost_limit_usd_micros?: number;
1858
+ chat_session_cost_limit_usd_micros?: number;
1859
+ /** M3 Stage 3: replace the action-category grant set. Server rejects
1860
+ * (422 grants_outside_parent) when the requested set isn't a subset
1861
+ * of the parent scope's effective grant. */
1862
+ granted_categories?: string[];
1863
+ /** M3 Stage 4: per-scope schedule auto-disable cap. */
1864
+ max_consecutive_failures?: number;
1865
+ }
1866
+ interface UpdateChatBudgetRequest {
1867
+ cost_limit_usd_micros: number;
1868
+ }
1869
+ interface UpdateCostLimitRequest {
1870
+ cost_limit_usd_micros: number;
1871
+ }
1872
+ declare const usdMicros: {
1873
+ toDollars: (micros: number) => number;
1874
+ fromDollars: (dollars: number) => number;
1875
+ };
1876
+
1877
+ declare class BudgetsClient {
1878
+ private readonly http;
1879
+ constructor(http: BaseClient);
1880
+ getOrg(): Promise<{
1881
+ budget: OrgBudget;
1882
+ }>;
1883
+ updateOrg(body: UpdateOrgBudgetRequest): Promise<{
1884
+ budget: OrgBudget;
1885
+ message: string;
1886
+ }>;
1887
+ getProject(projectId: string): Promise<{
1888
+ budget: ScopedBudget;
1889
+ }>;
1890
+ updateProject(projectId: string, body: UpdateScopedBudgetRequest): Promise<{
1891
+ budget: ScopedBudget;
1892
+ message: string;
1893
+ }>;
1894
+ getSandbox(sandboxId: string): Promise<{
1895
+ budget: ScopedBudget;
1896
+ }>;
1897
+ updateSandbox(sandboxId: string, body: UpdateScopedBudgetRequest): Promise<{
1898
+ budget: ScopedBudget;
1899
+ message: string;
1900
+ }>;
1901
+ getChat(chatId: string): Promise<{
1902
+ budget: ChatBudget;
1903
+ }>;
1904
+ updateChat(chatId: string, body: UpdateChatBudgetRequest): Promise<{
1905
+ message: string;
1906
+ }>;
1907
+ getEffectiveChat(chatId: string): Promise<EffectiveChatBudget>;
1908
+ updateTemplateCostLimit(templateId: string, body: UpdateCostLimitRequest): Promise<unknown>;
1909
+ updateScheduleCostLimit(scheduleId: string, body: UpdateCostLimitRequest): Promise<unknown>;
1910
+ }
1911
+
1912
+ type CloudAgentClientOptions = BaseClientOptions;
1913
+ declare class AgentEngineFacade {
1914
+ readonly templates: TemplatesClient;
1915
+ readonly scheduledTasks: ScheduledTasksClient;
1916
+ constructor(templates: TemplatesClient, scheduledTasks: ScheduledTasksClient);
1917
+ }
1918
+ declare class BillingFacade {
1919
+ readonly subscriptions: SubscriptionsClient;
1920
+ readonly credits: CreditsClient;
1921
+ constructor(subscriptions: SubscriptionsClient, credits: CreditsClient);
1922
+ }
1923
+ declare class CloudAgentClient {
1924
+ readonly http: BaseClient;
1925
+ readonly auth: AuthClient;
1926
+ readonly mfa: MfaClient;
1927
+ readonly user: UserClient;
1928
+ readonly organization: OrganizationClient;
1929
+ readonly projects: ProjectsClient;
1930
+ readonly sandboxes: SandboxesClient;
1931
+ readonly credentials: CredentialsClient;
1932
+ readonly chat: ChatClient;
1933
+ readonly agentEngine: AgentEngineFacade;
1934
+ readonly resources: ResourcesClient;
1935
+ readonly systemEvents: SystemEventsClient;
1936
+ readonly billing: BillingFacade;
1937
+ readonly usage: UsageClient;
1938
+ readonly budgets: BudgetsClient;
1939
+ constructor(options: CloudAgentClientOptions);
1940
+ }
1941
+
1942
+ declare class HttpError extends Error {
1943
+ readonly status: number;
1944
+ readonly statusText: string;
1945
+ readonly errorCode: string | null;
1946
+ readonly body: unknown;
1947
+ constructor(status: number, statusText: string, body: unknown);
1948
+ }
1949
+ declare class NotImplementedError extends Error {
1950
+ constructor(method: string);
1951
+ }
1952
+
1953
+ export { type AcceptInviteRequest, AccessType, type AcquireScanLeaseRequest, type AcquireScanLeaseResponse, type ActionCategory, type ActivateRequest, type AddMemberRequest, type AnswerChatQuestionRequest, type AnswerChatQuestionResponse, type AuthUser, BaseClient, type BaseClientOptions, type BudgetScope, BudgetsClient, type BuySubscriptionRequest, type BuySubscriptionResponse, CAP_AI, CAP_COMPUTE, CAP_GENERAL, CAP_STORAGE, CAP_VCS, type CancelChatTurnResponse, type CancelSubscriptionResponse, type ChatAssistantMessagePayload, type ChatBillingRefuseCode, type ChatBillingRefuseError, type ChatBudget, type ChatDonePayload, type ChatEvent, type ChatEventType, type ChatMessage, type ChatMessageKind, type ChatMessageRole, type ChatNarrationPayload, type ChatPhase, type ChatPhasePayload, type ChatPlanDraftPayload, type ChatQuestionPayload, type ChatSchedule, type ChatScheduleEnvelope, type ChatScheduleRunStatus, type ChatScope, type ChatSession, type ChatSessionSource, type ChatSessionTitlePayload, type ChatStepEventPayload, type ChatStepProgressPayload, type ChatStreamHandle, type ChatToolCallConfirmationRequiredPayload, type ChatToolCallFinishedPayload, type ChatToolCallStartedPayload, type ClarificationOption, CloudAgentClient, type CloudAgentClientOptions, type CloudResource, type CloudResourceContainerRef, type CloudResourceEdge, type CloudScanHistory, type CloudScanLease, type ConfirmChatToolCallRequest, type ConfirmChatToolCallResponse, type CreateAgentTemplateRequest, type CreateChatScheduleRequest, type CreateChatSessionRequest, type CreateChatSessionResponse, type CreateCredentialRequest, type CreateGatewayTokenRequest, type CreateGatewayTokenResponse, type CreateOrganizationUserRequest, type CreateProjectRequest, type CreateSandboxRequest, type CreateScheduledTaskRequest, type Credential, type CreditBalance, type CreditTransaction, type CreditTransactionKind, type CreditTransactionType, type DebugPayload, type DebugReceipt, type EffectiveChatBudget, type ExchangeCodeRequest, type FieldSpec, type FieldType, type FineTuneParams, type GatewayToken, type GetChatSessionResponse, type GetUsageSummaryQuery, type GetUsageSummaryResponse, HttpError, type ImpersonationProvider, type ListAgentTemplatesQuery, type ListAgentTemplatesResponse, type ListChatScheduleRunsResponse, type ListChatSchedulesResponse, type ListChatSessionsQuery, type ListChatSessionsResponse, type ListCredentialsQuery, type ListCreditsTransactionsQuery, type ListCreditsTransactionsResponse, type ListPaymentsResponse, type ListSandboxesQuery, type ListScanHistoryQuery, type ListScanHistoryResponse, type ListScheduledTasksQuery, type ListScheduledTasksResponse, type LoginRequest, type MFASetupResponse, type MFASimpleResponse, type MFAStatus, MFAType, type MFAVerifyLoginRequest, type MFAVerifyLoginResponse, type MFAVerifySetupRequest, type MagicLinkActivateRequest, type MagicLinkSendResponse, type ModeType, type MonthlyCreditStats, NotImplementedError, type OpenChatStreamOptions, type OrgBudget, OrgRoles, type OrgSubscription, type Organization, type OrganizationUser, PROVIDER_CATALOG, type Payment, type PeekScanLeaseResponse, type PostChatMessageRequest, type PostChatMessageResponse, type Project, type ProjectMember, type ProviderID, type ProviderSpec, ProviderType, type Query, type ReconcileScope, type ReconcileTuple, type RefreshRequest, type RegisterRequest, type RequestOptions, type ResetPasswordRequest, type ResourceTreeCategory, type ResourceTreeCredential, type ResourceTreeGrouping, type ResourceTreeResource, type ResourceTreeResponse, ResourcesClient, type Sandbox, type SandboxCredential, type ScanInProgressError, type ScheduledTask, type ScopedBudget, type SessionResponse, type SessionTokens, type SimpleAgentResponse, type SimpleKeysResponse, type SimpleOrgResponse, type SimpleResponse$2 as SimpleResponse, type StorageType, type SubgraphDirection, type SubgraphRequest, type SubgraphResponse, type Subscription, type SubscriptionCapability, type SubscriptionPeriod, type SystemEvent, type SystemEventQuery, type SystemEventQueryResponse, type SystemEventReadResponse, type Template, type TokenProvider, type UnauthorizedHandler, type UpdateChatBudgetRequest, type UpdateChatScheduleRequest, type UpdateCostLimitRequest, type UpdateCredentialRequest, type UpdateMemberRoleRequest, type UpdateOrgBudgetRequest, type UpdateOrgUserRequest, type UpdateOrganizationRequest, type UpdateProjectRequest, type UpdateSandboxRequest, type UpdateScopedBudgetRequest, type UpdateUserRequest, type UpdateUserResponse, type UsageBucket, type UsageByModelQuery, type UsageByModelResponse, type UsageByModelRow, type UsageReportQuery, type UsageReportResponse, type UsageSummary, type UsageSummaryQuery, type UsageSummaryResponse, type UsageTotals, type UsageWindow, type UserProfile, type UserSummary, computeDisplayHint, getProvider, getValueAt, isMetadataPath, isSecretPath, listProviders, metadataKey, setValueAt, usdMicros, validate };