@oberik/sdk 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -124,12 +124,36 @@ export interface TokenResponse {
124
124
  token_type: string;
125
125
  expires_in: number;
126
126
  tenant_id: string;
127
+ /** Who the token is for. Omitting `user_ref` inherits the caller's subject — it does
128
+ * not mint a token without one, which used to fail much later at an unrelated call
129
+ * site with `Token missing subject claim 'sub'`. */
130
+ subject: string;
131
+ /** What was actually granted, after intersecting with the caller's own. Absent when
132
+ * the request named none (the token is then as broad as the caller). */
133
+ capabilities?: string[] | null;
134
+ scope?: string | null;
127
135
  }
128
136
  export interface ToolInfo {
129
137
  name: string;
130
- source: "builtin" | "mcp" | string;
138
+ source: "builtin" | "mcp" | "webhook" | string;
131
139
  description: string;
132
140
  }
141
+ /** What happened when this project's MCP server was asked for its tools.
142
+ *
143
+ * Without this, a server that registered cleanly and contributed nothing is
144
+ * indistinguishable from one still connecting, one whose handshake failed, and one
145
+ * that genuinely has no tools — all four are an absence of rows in the listing. */
146
+ export interface McpServerStatus {
147
+ name: string;
148
+ /** Did it answer? */
149
+ ok: boolean;
150
+ /** How many tools it contributed. `ok` with `0` means it answered and offered none. */
151
+ tools: number;
152
+ /** Answered from the short-lived cache rather than dialled again this call. */
153
+ cached?: boolean;
154
+ /** Why not, when `ok` is false — including a URL refused as private or unroutable. */
155
+ error?: string;
156
+ }
133
157
  export type DocumentStatus = "awaiting_upload" | "pending" | "processing" | "ready" | "failed" | string;
134
158
  export interface DocumentOut {
135
159
  id: string;
@@ -524,9 +548,17 @@ export interface QuestionAnswerItem {
524
548
  /** The question's `id` (or `header`). Omit for a single question, or when the
525
549
  * answers are in the order they were asked. */
526
550
  question_id?: string;
527
- /** Option labels the user picked. Anything not offered is reported to the agent
528
- * as text the user typed, not as a selection. */
529
- selected?: string[];
551
+ /** What the user picked: an option's `label`, or the `QuestionOption` itself.
552
+ *
553
+ * Both, because the options you are handed are objects and `selected: [q.options[0]]`
554
+ * is the natural thing to write — and it was a 422 (`Input should be a valid string`)
555
+ * telling you nothing about `.label`. The server unwraps an object to its label, so
556
+ * an `onQuestion` handler that returns the option it was given now works, which is
557
+ * what "pass an `onQuestion` handler and the pause is answered for you" claimed.
558
+ *
559
+ * Anything not among the offered options is reported to the agent as text the user
560
+ * typed, not as a selection. */
561
+ selected?: (string | QuestionOption)[];
530
562
  /** The "type something else" answer. May accompany selections. */
531
563
  text?: string | null;
532
564
  }
@@ -676,8 +708,14 @@ export interface ComputerHost {
676
708
  workdir: string;
677
709
  /** Applied when a command names no timeout of its own. */
678
710
  exec_default_timeout_s: number;
679
- /** Hard ceiling: past this a command is killed. */
711
+ /** Hard ceiling for the AGENT's `computer_bash`, which streams and so can use all of
712
+ * it. Not what `computers.exec` can get — see below. */
680
713
  exec_max_timeout_s: number;
714
+ /** Ceiling for a direct `computers.exec`, which blocks an HTTP response and so is
715
+ * bounded by the edge long before `exec_max_timeout_s`. Asking for more than this is
716
+ * clamped to it, rather than left to become a proxy's HTML error page. For work that
717
+ * needs longer, let the agent run it, or start it with `&` and poll. */
718
+ sync_exec_max_timeout_s: number;
681
719
  max_sessions_per_tenant: number;
682
720
  }
683
721
  export type ComputerSessionStatus = "creating" | "running" | "paused" | "stopped" | "failed" | string;
@@ -778,7 +816,6 @@ export interface ChatRequest {
778
816
  /** Attach a specific existing sandbox to this turn (reconnect to a prior session).
779
817
  * Omitted = the sandbox bound to this chat session, else a fresh one. */
780
818
  computer_session_id?: string | null;
781
- /** Let the agent run read-only SQL against connected query-mode data sources. */
782
819
  /** Let the agent drive a real browser — click, type, scroll, wait, capture — rather
783
820
  * than fetching one page at a time. Needs the `browser` capability and the browser
784
821
  * service; `web_search`/`browse_url` work without it. */
@@ -808,7 +845,27 @@ export interface PendingToolCall {
808
845
  name: string;
809
846
  args: Record<string, unknown>;
810
847
  }
848
+ /** One sentence, and the passages it came from.
849
+ *
850
+ * `citations` is still the whole retrieval set — a client may want to show what was
851
+ * searched — but this is what answers "where did THAT come from". Before it existed the
852
+ * docs promised a citation "for every claim" and delivered the retrieval set in score
853
+ * order, so a question whose answer lived in one chunk came back with three "sources" and
854
+ * a UI built as instructed showed the reader citations that did not support the sentence. */
855
+ export interface Claim {
856
+ text: string;
857
+ /** Offsets into `content`. Null when the claim could not be located after markers were
858
+ * stripped — better absent than pointing at the wrong span. */
859
+ start: number | null;
860
+ end: number | null;
861
+ /** `Citation.marker` values, in the order the model wrote them. */
862
+ citations: number[];
863
+ }
811
864
  export interface Citation {
865
+ /** The number the model was shown for this passage, and what a `Claim` refers to. */
866
+ marker?: number | null;
867
+ /** Whether a sentence was actually attributed to it. */
868
+ used?: boolean;
812
869
  document_id: string;
813
870
  chunk_index: number;
814
871
  filename: string | null;
@@ -850,6 +907,17 @@ export interface ChatResponse {
850
907
  /** Set only when history had to be trimmed or summarized to fit the window. */
851
908
  context?: ContextReport | null;
852
909
  citations: Citation[];
910
+ /** Sentences attributed to a passage, in order. Empty when the model emitted no markers,
911
+ * which `attribution` reports rather than hiding. */
912
+ claims: Claim[];
913
+ /** `per-claim` · `retrieval-only` · `none`. Draw footnotes from `claims` on the first;
914
+ * on the second you have the retrieval set and no attribution, which is a different
915
+ * thing to show. */
916
+ attribution: "per-claim" | "retrieval-only" | "none";
917
+ /** Set when the agent put a page in front of the user. Declared here as well as on
918
+ * `ChatDone`: a `chat.send()` caller could not learn a hand-off had happened at all,
919
+ * while the docs say the blocking path carries `handoff.blocking`. */
920
+ handoff?: Handoff | null;
853
921
  sources: Source[];
854
922
  /** Non-text outputs of the turn: generated media, and files the agent exported
855
923
  * from its sandbox. `url` is signed fresh per response — don't persist it. */
@@ -863,8 +931,17 @@ export interface ChatResponse {
863
931
  /** A reasoning model's thinking for this turn, else "". Live only — it is not stored
864
932
  * and is never sent back to the model, so it won't appear in session history. */
865
933
  reasoning?: string;
866
- /** Non-normal stop reason, else null. "max_tool_iterations" when a token's
867
- * tool-loop ceiling was hit. Language-neutral — localize it yourself. */
934
+ /**
935
+ * Non-normal stop reason, else null. Language-neutral — localize it yourself.
936
+ *
937
+ * `max_tool_iterations` a token's tool-loop ceiling was hit; `content` is the answer
938
+ * produced so far
939
+ * `guardrail` an input guardrail refused the message
940
+ * `no_model` the PROJECT has no model configured, so nothing could run.
941
+ * Not the end-user's problem and not something they can fix —
942
+ * route it to whoever set the project up. `GET /readiness` on
943
+ * the control plane lists what is missing.
944
+ */
868
945
  finish_reason?: string | null;
869
946
  }
870
947
  export interface SessionOut {
@@ -920,6 +997,65 @@ export interface TaskOut {
920
997
  last_error: string | null;
921
998
  created_at: string;
922
999
  }
1000
+ /** A project's guardrail policy, complete — an untouched field reads as its default
1001
+ * rather than as missing. */
1002
+ export interface GuardrailPolicy {
1003
+ enabled: boolean;
1004
+ input: {
1005
+ injection: boolean;
1006
+ blockedTopics: string[];
1007
+ pii: PiiMode;
1008
+ };
1009
+ output: {
1010
+ groundedness: boolean;
1011
+ moderation: boolean;
1012
+ pii: PiiMode;
1013
+ };
1014
+ /** Which model judges. Null = the turn's own model. */
1015
+ guardModel: string | null;
1016
+ /** `block` refuses the turn; `flag` allows it and annotates `guard_flags`. */
1017
+ onViolation: "block" | "flag";
1018
+ }
1019
+ /** Off is the default and deliberately so: on a product where an end-user shares their own
1020
+ * information on purpose, the model has to see it. `detect` records that it was there;
1021
+ * `redact` keeps it from the provider and costs the agent the ability to use it. */
1022
+ export type PiiMode = "off" | "detect" | "redact";
1023
+ /** Flat, because that is what a form sends. Anything omitted is left unchanged. */
1024
+ export interface GuardrailUpdate {
1025
+ enabled?: boolean;
1026
+ injection?: boolean;
1027
+ blockedTopics?: string[];
1028
+ inputPii?: PiiMode;
1029
+ groundedness?: boolean;
1030
+ moderation?: boolean;
1031
+ outputPii?: PiiMode;
1032
+ guardModel?: string;
1033
+ onViolation?: "block" | "flag";
1034
+ }
1035
+ /** What still has to happen before a project can answer a question. */
1036
+ export interface ProjectReadiness {
1037
+ ready: boolean;
1038
+ /** The first blocking step, so one line of UI has something to render. */
1039
+ next: ReadinessStep | null;
1040
+ steps: ReadinessStep[];
1041
+ }
1042
+ export interface ReadinessStep {
1043
+ id: string;
1044
+ done: boolean;
1045
+ /** What stops working while this is undone — "every request", "every document upload". */
1046
+ blocks: string;
1047
+ what: string;
1048
+ /** The one call, or the one screen, that fixes it. */
1049
+ how: string;
1050
+ }
1051
+ export interface ConnectInfo {
1052
+ projectId: string;
1053
+ tenantId: string | null;
1054
+ controlPlaneUrl: string;
1055
+ dataPlaneUrl: string;
1056
+ /** Copy-pasteable: the server half and the app half, using both clients correctly. */
1057
+ snippet: string;
1058
+ }
923
1059
  /** What a project key may do. An admin key satisfies a mint requirement, never the
924
1060
  * reverse. */
925
1061
  export type ProjectKeyScope = "admin" | "mint";
@@ -964,6 +1100,23 @@ export interface TokenCapabilities {
964
1100
  max_context_tokens: number | null;
965
1101
  };
966
1102
  }
1103
+ /** A URL that starts a turn when something happens in another system. */
1104
+ export interface Trigger {
1105
+ id: string;
1106
+ name: string;
1107
+ prompt: string;
1108
+ enabled: boolean;
1109
+ /** Events that started a run. A sender's retry of the same event is not counted twice. */
1110
+ fired_count: number;
1111
+ last_fired_at: string | null;
1112
+ last_error: string | null;
1113
+ /** Absolute, and give it to the other system. Not shown-once: their configuration holds
1114
+ * it, so we cannot forget it on their behalf. */
1115
+ url: string;
1116
+ /** Only on create and rotate. Sign the body with it and the URL stops being a bearer
1117
+ * token: `X-Signature: sha256=<hmac>`. */
1118
+ secret?: string | null;
1119
+ }
967
1120
  /** One memory or wiki page. */
968
1121
  export interface KnowledgeItem {
969
1122
  id: string;
@@ -1156,6 +1309,8 @@ export type StreamEvent = {
1156
1309
  guard_flags: string[];
1157
1310
  context?: ContextReport | null;
1158
1311
  citations: Citation[];
1312
+ claims: Claim[];
1313
+ attribution: "per-claim" | "retrieval-only" | "none";
1159
1314
  sources: Source[];
1160
1315
  attachments: Attachment[];
1161
1316
  reasoning?: string;
@@ -1300,6 +1455,13 @@ export interface ChatDone {
1300
1455
  /** Set only when history had to be trimmed or summarized to fit the window. */
1301
1456
  context?: ContextReport | null;
1302
1457
  citations: Citation[];
1458
+ /** Sentences attributed to a passage, in order. Empty when the model emitted no markers,
1459
+ * which `attribution` reports rather than hiding. */
1460
+ claims: Claim[];
1461
+ /** `per-claim` · `retrieval-only` · `none`. Draw footnotes from `claims` on the first;
1462
+ * on the second you have the retrieval set and no attribution, which is a different
1463
+ * thing to show. */
1464
+ attribution: "per-claim" | "retrieval-only" | "none";
1303
1465
  sources: Source[];
1304
1466
  attachments: Attachment[];
1305
1467
  /** The full thinking trace of a reasoning model, else "" (streamed as `reasoning`). */
@@ -1367,6 +1529,9 @@ export interface DownloadOptions {
1367
1529
  }
1368
1530
  export declare class AgentApiError extends Error {
1369
1531
  status: number;
1532
+ /** The server's `detail`, in whatever shape it sent — except an HTML error page from
1533
+ * an intermediary, which is replaced by the same summary as `message`. Keeping four
1534
+ * kilobytes of someone else's markup here helped nobody and buried the status. */
1370
1535
  detail: unknown;
1371
1536
  constructor(status: number, detail: unknown);
1372
1537
  }
@@ -1491,13 +1656,29 @@ export declare class AgentFramework {
1491
1656
  } & Record<string, string>>;
1492
1657
  };
1493
1658
  tools: {
1659
+ /** Every tool this token would actually be handed on its next request.
1660
+ *
1661
+ * `mcp_servers` is present when the project has any, and answers the question the
1662
+ * listing alone cannot: "still connecting", "handshake failed" and "this server has
1663
+ * no tools" all look identical as an absence of rows. Each entry says whether the
1664
+ * server answered, how many tools it contributed, and why not. */
1494
1665
  list: () => Promise<{
1495
1666
  tools: ToolInfo[];
1667
+ mcp_servers?: McpServerStatus[];
1496
1668
  }>;
1497
1669
  };
1498
1670
  chat: {
1499
1671
  /** One round-trip. Returns `requires_action` + `tool_calls` for you to handle
1500
- * manually — use `chat.run` to auto-dispatch client tools instead. */
1672
+ * manually — use `chat.run` to auto-dispatch client tools instead.
1673
+ *
1674
+ * Client *tools* stay manual here; that is the whole difference from `run`. UI
1675
+ * components do not, because there is no manual handling of one: the registry
1676
+ * passed to `createClient({ ui: [...] })` IS the handling, and `chat.stream`
1677
+ * already both declares it and draws from it. A blocking client that registered a
1678
+ * chart renderer got an empty `ui` and no error — the declarations were never sent,
1679
+ * so the agent was not offered the component at all; and when they were repeated by
1680
+ * hand as `ui_tools`, the renderer still never ran. The one wiring `tools.md`
1681
+ * documents produced nothing on the one call it documents it with. */
1501
1682
  send: (body: ChatRequest) => Promise<ChatResponse>;
1502
1683
  /** Blocking chat that AUTO-EXECUTES registered client tools: it sends the
1503
1684
  * message, and whenever the agent asks for client tools it runs their
@@ -1533,7 +1714,16 @@ export declare class AgentFramework {
1533
1714
  handoffDone: (sessionId: string) => Promise<ChatResponse>;
1534
1715
  answer: (sessionId: string, ...answers: QuestionAnswer[]) => Promise<ChatResponse>;
1535
1716
  sessions: {
1536
- list: (userRef?: string) => Promise<SessionOut[]>;
1717
+ /** Conversations this token may see, newest first.
1718
+ *
1719
+ * Paged: `limit` defaults to 100 and is capped at 500. This used to return every
1720
+ * session in one unbounded response — fine for one end-user, and an admin token
1721
+ * on a busy project gets the whole tenant's history to render a sidebar showing
1722
+ * twenty. Page with `offset`. */
1723
+ list: (userRef?: string, opts?: {
1724
+ limit?: number;
1725
+ offset?: number;
1726
+ }) => Promise<SessionOut[]>;
1537
1727
  /** The agent's plan for this conversation — what a UI renders on a page load,
1538
1728
  * or between turns. A turn that touched the list also returns it directly. */
1539
1729
  todos: (sessionId: string) => Promise<TodoItem[]>;
@@ -1728,6 +1918,36 @@ export declare class AgentFramework {
1728
1918
  get: (id: string) => Promise<TaskOut>;
1729
1919
  cancel: (id: string) => Promise<TaskOut>;
1730
1920
  };
1921
+ /**
1922
+ * Turns that start because something happened somewhere else.
1923
+ *
1924
+ * A trigger is a URL you give another system — a ticket tracker, a CI job, a Zapier step
1925
+ * — and the path is the credential, so it runs as a fixed subject chosen at creation.
1926
+ * These were the only routes in the API reference with no SDK method: every integration
1927
+ * hand-wrote `fetch` for them.
1928
+ *
1929
+ * The URL comes back absolute and is not a secret we can show once: the whole point is
1930
+ * that someone else's configuration holds it. `secret` IS shown once — with it, the
1931
+ * sender signs the body and the URL stops being a bearer token.
1932
+ */
1933
+ triggers: {
1934
+ list: () => Promise<Trigger[]>;
1935
+ /** `prompt` may interpolate the event: `"A ticket arrived: {{ body.title }}"`. */
1936
+ create: (opts: {
1937
+ prompt: string;
1938
+ name?: string;
1939
+ systemPrompt?: string;
1940
+ /** Run every event in one conversation. Off by default: two unrelated events sharing
1941
+ * a transcript confuse both. */
1942
+ sessionId?: string;
1943
+ /** Require a signed body, and return the key to sign it with. */
1944
+ signed?: boolean;
1945
+ }) => Promise<Trigger>;
1946
+ delete: (triggerId: string) => Promise<void>;
1947
+ /** A new URL, with the old one alive for 24 hours — so telling the other system its new
1948
+ * address is not an outage. */
1949
+ rotate: (triggerId: string) => Promise<Trigger>;
1950
+ };
1731
1951
  /**
1732
1952
  * What the agent wrote down — remembered facts and wiki pages.
1733
1953
  *
@@ -1921,6 +2141,18 @@ export declare class OberikProject {
1921
2141
  };
1922
2142
  /** Documents owned by the project rather than by any one end-user: the corpus you
1923
2143
  * curate and your users only read. */
2144
+ /**
2145
+ * The corpus you curate.
2146
+ *
2147
+ * Uploads here are stored `tenant`-visible — readable by every end-user of the project —
2148
+ * which is what "a corpus you curate, that users only read" means. That is the default
2149
+ * and the only option, deliberately: a project key is not a person, so there is no
2150
+ * per-user subtree for it to write into. Per-user documents go through the data-plane
2151
+ * client with an end-user token, where the subject IS the owner.
2152
+ *
2153
+ * The docs used to show `visibility: "tenant"` being passed here, which was neither
2154
+ * accepted nor needed — a recipe that worked by luck rather than by expression.
2155
+ */
1924
2156
  documents: {
1925
2157
  list: () => Promise<unknown[]>;
1926
2158
  upload: (file: Blob | File, opts?: {
@@ -1929,6 +2161,126 @@ export declare class OberikProject {
1929
2161
  }) => Promise<unknown>;
1930
2162
  delete: (documentId: string) => Promise<void>;
1931
2163
  };
2164
+ /**
2165
+ * The models this project runs on, and the retrieval it uses.
2166
+ *
2167
+ * These had no methods at all: `project-api.md` documents them in a table and every
2168
+ * integration hand-rolled `fetch` for half its setup. `providers.add` is the one that
2169
+ * matters most — it is the step a new project cannot answer a question without, and it
2170
+ * finishes the rest of the setup itself (see `derived` in the response).
2171
+ *
2172
+ * `providers.catalog` is deliberately absent: it is not project-scoped, so it does not
2173
+ * belong on a client whose every path hangs off one project.
2174
+ */
2175
+ providers: {
2176
+ list: () => Promise<unknown[]>;
2177
+ /** Name a chat model AND an embedding model: the first lets the agent answer, the
2178
+ * second lets it index. The response's `derived` says what was set for you. */
2179
+ add: (opts: {
2180
+ provider: string;
2181
+ models: string[];
2182
+ values: Record<string, string>;
2183
+ label?: string;
2184
+ }) => Promise<{
2185
+ id: string;
2186
+ derived?: Record<string, unknown>;
2187
+ }>;
2188
+ edit: (credId: string, opts: {
2189
+ models?: string[];
2190
+ label?: string;
2191
+ values?: Record<string, string>;
2192
+ }) => Promise<unknown>;
2193
+ /** Re-read the provider's catalog: a model registered before its price was published
2194
+ * bills nothing, so the usage cap never trips. */
2195
+ refresh: (credId: string) => Promise<unknown>;
2196
+ remove: (credId: string) => Promise<void>;
2197
+ };
2198
+ /** The model used when a request does not name one. */
2199
+ defaultModel: {
2200
+ set: (model: string) => Promise<unknown>;
2201
+ };
2202
+ /** Embedding and rerank overrides. Set for you when you register an embedding model, so
2203
+ * this is for changing it rather than for getting started. */
2204
+ retrieval: {
2205
+ set: (opts: {
2206
+ embeddingModel?: string;
2207
+ embeddingDim?: number;
2208
+ rerankModel?: string;
2209
+ }) => Promise<unknown>;
2210
+ /** How many floats a model returns, measured by embedding one word. No provider
2211
+ * publishes it, and a wrong one fails at the first ingest rather than here. */
2212
+ probe: (model: string) => Promise<{
2213
+ dim: number | null;
2214
+ error?: string;
2215
+ }>;
2216
+ };
2217
+ /** How documents are read: the built-in parser, or a vision model you choose. */
2218
+ documentProcessor: {
2219
+ set: (opts: {
2220
+ type: string;
2221
+ model?: string;
2222
+ }) => Promise<unknown>;
2223
+ };
2224
+ /** What happens when a conversation outgrows the model's window. */
2225
+ context: {
2226
+ get: () => Promise<unknown>;
2227
+ set: (opts: Record<string, unknown>) => Promise<unknown>;
2228
+ };
2229
+ /** Spend and rate caps on this project's LLM key. Enforced by the biller, so they hold
2230
+ * even when the usage views cannot be read. */
2231
+ limits: {
2232
+ get: () => Promise<unknown>;
2233
+ set: (opts: {
2234
+ maxBudget?: number | null;
2235
+ budgetDuration?: string;
2236
+ tpmLimit?: number | null;
2237
+ rpmLimit?: number | null;
2238
+ }) => Promise<unknown>;
2239
+ };
2240
+ /** Which models a delegate may run on, and how many may run at once. Without this the
2241
+ * subagents capability stays unavailable however it is granted. */
2242
+ subagents: {
2243
+ set: (opts: {
2244
+ models: string[];
2245
+ maxConcurrent?: number;
2246
+ }) => Promise<unknown>;
2247
+ };
2248
+ /** Procedures you publish as Agent Plugins, and what your end-users have added. */
2249
+ skills: {
2250
+ list: () => Promise<unknown[]>;
2251
+ upload: (zip: Blob | File, filename?: string) => Promise<unknown>;
2252
+ delete: (pluginId: string) => Promise<void>;
2253
+ };
2254
+ /** MCP servers whose tools join this project's catalog. */
2255
+ mcp: {
2256
+ list: () => Promise<unknown[]>;
2257
+ add: (opts: {
2258
+ name: string;
2259
+ url: string;
2260
+ transport?: "streamable_http" | "sse";
2261
+ headers?: Record<string, string>;
2262
+ }) => Promise<unknown>;
2263
+ remove: (mcpId: string) => Promise<void>;
2264
+ };
2265
+ /** Conversations, and what was said in them. */
2266
+ sessions: {
2267
+ list: () => Promise<unknown[]>;
2268
+ messages: (sessionId: string) => Promise<unknown[]>;
2269
+ };
2270
+ /** Scheduled work this project's end-users have created. */
2271
+ tasks: {
2272
+ list: () => Promise<unknown[]>;
2273
+ };
2274
+ /** What the agent has written down: remembered facts and wiki pages. */
2275
+ wiki: {
2276
+ list: () => Promise<unknown[]>;
2277
+ delete: (itemId: string) => Promise<void>;
2278
+ };
2279
+ /** Live sandboxes, and what to do about one. */
2280
+ sandboxes: {
2281
+ list: () => Promise<unknown[]>;
2282
+ action: (sessionId: string, action: "pause" | "resume" | "delete") => Promise<unknown>;
2283
+ };
1932
2284
  /** Prepended to every request for this project, above anything a caller sends. */
1933
2285
  systemPrompt: {
1934
2286
  set: (systemPrompt: string) => Promise<unknown>;
@@ -1953,6 +2305,33 @@ export declare class OberikProject {
1953
2305
  delete: (toolId: string) => Promise<void>;
1954
2306
  };
1955
2307
  /** Server-side keys. A created one is returned once and never again. */
2308
+ /**
2309
+ * Checks on what goes into the model and what comes back.
2310
+ *
2311
+ * The enforcement has existed for a long time and there was no way to configure it — no
2312
+ * route, no dashboard section, no column — so a documentation page described switches
2313
+ * that could not be reached. `set` takes a partial: what you do not mention is left as it
2314
+ * is.
2315
+ */
2316
+ guardrails: {
2317
+ get: () => Promise<GuardrailPolicy>;
2318
+ set: (policy: GuardrailUpdate) => Promise<GuardrailPolicy>;
2319
+ };
2320
+ /**
2321
+ * Whether this project can actually answer a question yet.
2322
+ *
2323
+ * A new project has no models, so it can neither answer nor index anything — and the
2324
+ * flag that used to be the closest thing to this (`hasLlm`) meant "a LiteLLM key was
2325
+ * provisioned", which is true from the moment a project exists. Every unfinished step
2326
+ * names what it blocks and the one call that fixes it.
2327
+ *
2328
+ * Worth calling in a deploy check: a project that is not ready fails every request with
2329
+ * the provider's own error, which reads as your bug rather than as missing setup.
2330
+ */
2331
+ readiness: () => Promise<ProjectReadiness>;
2332
+ /** The starting snippet and this project's endpoints — the same one the dashboard and the
2333
+ * SSH gateway show, so there is one of it rather than three. */
2334
+ connect: () => Promise<ConnectInfo>;
1956
2335
  /**
1957
2336
  * Further project keys.
1958
2337
  *