@introspection-sdk/introspection-browser 0.5.4 → 0.5.6

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.
package/dist/api/tasks.js CHANGED
@@ -1,5 +1,4 @@
1
- import { cursorPaginate } from "@introspection-sdk/http";
2
- import { parseSse } from "./sse.js";
1
+ import { RunHandle, TaskRunsClient, TasksClient as SharedTasksClient, } from "@introspection-sdk/http";
3
2
  function toTaskBody(params) {
4
3
  const { identity, metadata, ...rest } = params;
5
4
  const body = { ...rest };
@@ -10,137 +9,15 @@ function toTaskBody(params) {
10
9
  body.metadata = mergedMetadata;
11
10
  return body;
12
11
  }
13
- /** Live handle on a task's run: stream its events, collect text, cancel. */
14
- export class RunHandle {
15
- task;
16
- run;
17
- runs;
18
- constructor(task, run, runs) {
19
- this.task = task;
20
- this.run = run;
21
- this.runs = runs;
22
- }
23
- stream() {
24
- return this.runs.stream(this.run.task_id, this.run.id);
25
- }
26
- cancel() {
27
- return this.runs.cancel(this.run.task_id, this.run.id);
28
- }
29
- /** Convenience: concatenate `data` from `text`/`message` SSE frames. */
30
- async text() {
31
- let out = "";
32
- for await (const ev of this.stream()) {
33
- if (ev.event === "text" || ev.event === "message")
34
- out += ev.data;
35
- }
36
- return out;
37
- }
38
- }
39
- export class TaskRunsClient {
40
- http;
41
- constructor(http) {
42
- this.http = http;
43
- }
44
- async create(taskId, body) {
45
- const res = await this.http.request({
46
- method: "POST",
47
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs`,
48
- body,
49
- });
50
- return new RunHandle(null, res.run, this);
51
- }
52
- get(taskId, runId) {
53
- return this.http.request({
54
- method: "GET",
55
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}`,
56
- });
57
- }
58
- cancel(taskId, runId) {
59
- return this.http.request({
60
- method: "POST",
61
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}/cancel`,
62
- });
63
- }
64
- async *stream(taskId, runId) {
65
- const res = await this.http.stream({
66
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}/stream`,
67
- });
68
- yield* parseSse(res);
69
- }
70
- }
71
12
  /**
72
- * Cookie-authenticated `/v1/tasks` client. Mirrors the Node SDK's
73
- * `TasksApi` shape but is bound to a DP session cookie rather than a
74
- * bearer token, and lets the caller select the agent on create.
13
+ * Cookie-authenticated `/v1/tasks` client. The implementation is shared with
14
+ * Node's runner-bound task client; this browser subclass only adds the
15
+ * `identity -> metadata.identity` body mapping used by cookie-session calls.
75
16
  */
76
- export class TasksClient {
77
- http;
78
- runs;
17
+ export class TasksClient extends SharedTasksClient {
79
18
  constructor(http) {
80
- this.http = http;
81
- this.runs = new TaskRunsClient(http);
82
- }
83
- /**
84
- * Tasks matching `params`. `await` it for the first page (preserving
85
- * the wire envelope's counts + `next` cursor), or `for await` it to
86
- * stream every task across pages (fetched lazily — `limit` sets the
87
- * page size, `next` the starting cursor; stop early to stop fetching).
88
- *
89
- * Mirrors the Node SDK's `TasksApi.list`, which is the source of truth
90
- * for the `/v1/tasks` shape.
91
- */
92
- list(params) {
93
- return cursorPaginate((next) => this.http.request({
94
- method: "GET",
95
- path: "/v1/tasks",
96
- query: { ...params, next },
97
- }), params?.next);
98
- }
99
- create(body) {
100
- return this.http.request({
101
- method: "POST",
102
- path: "/v1/tasks",
103
- body: toTaskBody(body),
104
- });
105
- }
106
- get(taskId) {
107
- return this.http.request({
108
- method: "GET",
109
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
110
- });
111
- }
112
- update(taskId, body) {
113
- return this.http.request({
114
- method: "PATCH",
115
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
116
- body,
117
- });
118
- }
119
- delete(taskId) {
120
- return this.http.request({
121
- method: "DELETE",
122
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
123
- expect: "empty",
124
- });
125
- }
126
- archive(taskId) {
127
- return this.http.request({
128
- method: "POST",
129
- path: `/v1/tasks/${encodeURIComponent(taskId)}/archive`,
130
- expect: "empty",
131
- });
132
- }
133
- unarchive(taskId) {
134
- return this.http.request({
135
- method: "POST",
136
- path: `/v1/tasks/${encodeURIComponent(taskId)}/unarchive`,
137
- expect: "empty",
138
- });
139
- }
140
- /** Sugar: create a task + return a handle on its initial run. */
141
- async start(params) {
142
- const res = await this.create(params);
143
- return new RunHandle(res.task, res.run, this.runs);
19
+ super(http, toTaskBody);
144
20
  }
145
21
  }
22
+ export { RunHandle, TaskRunsClient };
146
23
  //# sourceMappingURL=tasks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/api/tasks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/api/tasks.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,cAAc,EACd,WAAW,IAAI,iBAAiB,GAEjC,MAAM,yBAAyB,CAAC;AA0CjC,SAAS,UAAU,CAAC,MAAwB;IAC1C,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IAC/C,MAAM,IAAI,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,QAAQ;QAC7B,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE;QACnC,CAAC,CAAC,QAAQ,CAAC;IACb,IAAI,cAAc,KAAK,SAAS;QAAE,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,iBAGhC;IACC,YAAY,IAAwB;QAClC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1B,CAAC;CACF;AAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@introspection-sdk/introspection-browser",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Introspection observability SDK for the browser",
6
6
  "engines": {
@@ -31,8 +31,8 @@
31
31
  "@opentelemetry/api-logs": "^0.219.0",
32
32
  "@opentelemetry/sdk-logs": "^0.219.0",
33
33
  "@opentelemetry/exporter-logs-otlp-http": "^0.219.0",
34
- "@introspection-sdk/http": "0.5.4",
35
- "@introspection-sdk/types": "0.5.4"
34
+ "@introspection-sdk/types": "0.5.6",
35
+ "@introspection-sdk/http": "0.5.6"
36
36
  },
37
37
  "scripts": {
38
38
  "lint": "eslint . --max-warnings 0",
package/src/api/client.ts CHANGED
@@ -2,17 +2,22 @@
2
2
  * Browser-side Introspection API client.
3
3
  *
4
4
  * Lets a single-page app create and stream Introspection tasks directly
5
- * from the browser, with no API key in JavaScript. The auth boundary:
5
+ * from the browser, with no API key in JavaScript. The browser talks only
6
+ * to the Data Plane — runtime resolution and any other Control Plane work
7
+ * stays on the app's backend, so the CP never needs to serve CORS to
8
+ * customer web origins. The auth boundary:
6
9
  *
7
- * 1. The SPA's own backend ("broker") mints an Introspection access
8
- * token — via RFC 8693 token-exchange of the partner IdP token, a
9
- * PKCE `authorization_code`, or `client_credentials`. The IdP
10
- * secret never leaves the backend. The SPA fetches that token
11
- * through the `getToken` callback.
10
+ * 1. The SPA's own backend ("broker") mints a short-lived Introspection
11
+ * access token — via RFC 8693 token-exchange of the partner IdP
12
+ * token, a PKCE `authorization_code`, or `client_credentials` (the
13
+ * IdP secret never leaves the backend) — and, when a specific runtime
14
+ * is needed, resolves its `runtime_id` server-side. The SPA fetches
15
+ * the token through the `getToken` callback.
12
16
  * 2. `connect()` redeems the token at the DP `POST /v1/oauth/exchange`
13
17
  * for the HttpOnly `intro_dp_session` cookie.
14
18
  * 3. Every subsequent call rides that cookie (`credentials: "include"`)
15
- * — `client.tasks.start(...)`, `.get(...)`, run streaming, etc.
19
+ * — `client.tasks.start({ runtime_id })`, `.get(...)`, run streaming,
20
+ * etc.
16
21
  *
17
22
  * When the session cookie expires, an in-flight request gets a 401, and
18
23
  * the client transparently re-runs `getToken` + the DP exchange once
@@ -20,13 +25,26 @@
20
25
  */
21
26
 
22
27
  import { BrowserHttpClient, stripTrailingSlash, toApiError } from "./http.js";
28
+ import {
29
+ ConversationsClient,
30
+ FilesClient,
31
+ SharesClient,
32
+ } from "@introspection-sdk/http";
23
33
  import { TasksClient } from "./tasks.js";
24
- import { FilesClient } from "./files.js";
25
- import { ConversationsClient } from "./conversations.js";
26
- import { SharesClient } from "./shares.js";
34
+
35
+ type CookieClients = {
36
+ tasks: TasksClient;
37
+ files: FilesClient;
38
+ conversations: ConversationsClient;
39
+ shares: SharesClient;
40
+ };
27
41
 
28
42
  export interface IntrospectionApiClientOptions {
29
- /** Data Plane REST base URL (e.g. `https://dp.us.introspection.dev`). */
43
+ /**
44
+ * Data Plane REST base URL for the cookie-session APIs (`connect()` and
45
+ * `client.tasks` / `client.files` / `client.conversations` /
46
+ * `client.shares`). Required — the browser only talks to the DP.
47
+ */
30
48
  dpUrl: string;
31
49
  /**
32
50
  * Returns a fresh Introspection access token from the app's broker
@@ -43,16 +61,8 @@ export interface IntrospectionApiClientOptions {
43
61
  }
44
62
 
45
63
  export class IntrospectionApiClient {
46
- /** `/v1/tasks` operations bound to the DP session cookie. */
47
- readonly tasks: TasksClient;
48
- /** `/v1/files` operations bound to the DP session cookie. */
49
- readonly files: FilesClient;
50
- /** Read-only `/v1/conversations` projection bound to the session cookie. */
51
- readonly conversations: ConversationsClient;
52
- /** `/v1/shares` read-sharing grants bound to the session cookie. */
53
- readonly shares: SharesClient;
54
-
55
64
  private readonly fetchImpl: typeof fetch;
65
+ private readonly cookieClients: CookieClients;
56
66
 
57
67
  constructor(private readonly opts: IntrospectionApiClientOptions) {
58
68
  this.fetchImpl = opts.fetch ?? globalThis.fetch;
@@ -61,16 +71,41 @@ export class IntrospectionApiClient {
61
71
  "global fetch is unavailable; pass `fetch` or run in a modern browser",
62
72
  );
63
73
  }
74
+ if (!opts.dpUrl) {
75
+ throw new Error("IntrospectionApiClient requires a dpUrl");
76
+ }
64
77
  const http = new BrowserHttpClient({
65
78
  apiUrl: opts.dpUrl,
66
79
  additionalHeaders: opts.additionalHeaders,
67
80
  fetch: opts.fetch,
68
81
  onUnauthorized: () => this.reexchange(),
69
82
  });
70
- this.tasks = new TasksClient(http);
71
- this.files = new FilesClient(http);
72
- this.conversations = new ConversationsClient(http);
73
- this.shares = new SharesClient(http);
83
+ this.cookieClients = {
84
+ tasks: new TasksClient(http),
85
+ files: new FilesClient(http),
86
+ conversations: new ConversationsClient(http),
87
+ shares: new SharesClient(http),
88
+ };
89
+ }
90
+
91
+ /** `/v1/tasks` operations bound to the DP session cookie. */
92
+ get tasks(): TasksClient {
93
+ return this.cookieClients.tasks;
94
+ }
95
+
96
+ /** `/v1/files` operations bound to the DP session cookie. */
97
+ get files(): FilesClient {
98
+ return this.cookieClients.files;
99
+ }
100
+
101
+ /** Read-only `/v1/conversations` projection bound to the session cookie. */
102
+ get conversations(): ConversationsClient {
103
+ return this.cookieClients.conversations;
104
+ }
105
+
106
+ /** `/v1/shares` read-sharing grants bound to the session cookie. */
107
+ get shares(): SharesClient {
108
+ return this.cookieClients.shares;
74
109
  }
75
110
 
76
111
  /**
package/src/api/index.ts CHANGED
@@ -6,22 +6,30 @@
6
6
  * Separate from the package's default telemetry export so apps only pull
7
7
  * in what they use.
8
8
  *
9
+ * The browser talks only to the Data Plane. Resolving a runtime by name
10
+ * (a Control Plane call) stays on your backend, which hands the browser a
11
+ * short-lived access token plus the resolved `runtime_id`.
12
+ *
9
13
  * @example
10
14
  * ```typescript
11
15
  * import { IntrospectionApiClient } from "@introspection-sdk/introspection-browser/api";
12
16
  *
17
+ * // Your backend returns { token, runtimeId, dpUrl } — it mints the access
18
+ * // token, resolves the runtime id, and surfaces the DP URL (e.g. from the
19
+ * // Node SDK's serviceAccountToken response), so the browser never calls the CP.
20
+ * const { token, runtimeId, dpUrl } = await fetch(
21
+ * "/api/introspection/session",
22
+ * ).then((r) => r.json());
23
+ *
13
24
  * const client = new IntrospectionApiClient({
14
- * dpUrl: "https://dp.us.introspection.dev",
15
- * // your backend mints the Introspection access token (the session's
16
- * // project is derived from its claims — no projectId option needed)
17
- * getToken: () => fetch("/api/introspection/token").then((r) => r.text()),
25
+ * dpUrl,
26
+ * getToken: () => token,
18
27
  * });
19
28
  *
20
- * await client.connect(); // → intro_dp_session cookie
29
+ * await client.connect(); // -> intro_dp_session cookie
21
30
  * const run = await client.tasks.start({
22
31
  * prompt: "Summarize my latest order",
23
- * agent_name: "support-agent",
24
- * identity: { user_id: "u_42" },
32
+ * runtime_id: runtimeId,
25
33
  * });
26
34
  * for await (const ev of run.stream()) console.log(ev.event, ev.data);
27
35
  * ```
@@ -39,15 +47,13 @@ export {
39
47
  type StartTaskParams,
40
48
  } from "./tasks.js";
41
49
  export {
42
- FilesClient,
50
+ ConversationItemsClient,
51
+ ConversationsClient,
43
52
  FileVersionsClient,
53
+ FilesClient,
54
+ SharesClient,
44
55
  type FileUploadBody,
45
- } from "./files.js";
46
- export {
47
- ConversationsClient,
48
- ConversationItemsClient,
49
- } from "./conversations.js";
50
- export { SharesClient } from "./shares.js";
56
+ } from "@introspection-sdk/http";
51
57
  export { BrowserHttpClient, type BrowserHttpConfig } from "./http.js";
52
58
  export { parseSse } from "./sse.js";
53
59
  export {
@@ -93,4 +99,5 @@ export {
93
99
  InsufficientScopeError,
94
100
  NotFoundError,
95
101
  NetworkError,
102
+ RunnerExpiredError,
96
103
  } from "@introspection-sdk/types";
package/src/api/tasks.ts CHANGED
@@ -1,19 +1,10 @@
1
- import type {
2
- Paginated,
3
- RunIdentityInput,
4
- SseEvent,
5
- Task,
6
- TaskCancelResponse,
7
- TaskCreateResponse,
8
- TaskListParams,
9
- TaskRun,
10
- TaskRunCreateParams,
11
- TaskRunResponse,
12
- TaskUpdateParams,
13
- } from "@introspection-sdk/types";
14
- import { Paginator, cursorPaginate } from "@introspection-sdk/http";
15
- import { BrowserHttpClient } from "./http.js";
16
- import { parseSse } from "./sse.js";
1
+ import type { RunIdentityInput } from "@introspection-sdk/types";
2
+ import {
3
+ RunHandle,
4
+ TaskRunsClient,
5
+ TasksClient as SharedTasksClient,
6
+ type ResourceHttpClient,
7
+ } from "@introspection-sdk/http";
17
8
 
18
9
  /**
19
10
  * Body for creating a task directly against the DP from the browser.
@@ -65,149 +56,18 @@ function toTaskBody(params: CreateTaskParams): Record<string, unknown> {
65
56
  return body;
66
57
  }
67
58
 
68
- /** Live handle on a task's run: stream its events, collect text, cancel. */
69
- export class RunHandle {
70
- constructor(
71
- public readonly task: Task | null,
72
- public readonly run: TaskRun,
73
- private readonly runs: TaskRunsClient,
74
- ) {}
75
-
76
- stream(): AsyncIterable<SseEvent> {
77
- return this.runs.stream(this.run.task_id, this.run.id);
78
- }
79
-
80
- cancel(): Promise<TaskCancelResponse> {
81
- return this.runs.cancel(this.run.task_id, this.run.id);
82
- }
83
-
84
- /** Convenience: concatenate `data` from `text`/`message` SSE frames. */
85
- async text(): Promise<string> {
86
- let out = "";
87
- for await (const ev of this.stream()) {
88
- if (ev.event === "text" || ev.event === "message") out += ev.data;
89
- }
90
- return out;
91
- }
92
- }
93
-
94
- export class TaskRunsClient {
95
- constructor(private readonly http: BrowserHttpClient) {}
96
-
97
- async create(taskId: string, body: TaskRunCreateParams): Promise<RunHandle> {
98
- const res = await this.http.request<TaskRunResponse>({
99
- method: "POST",
100
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs`,
101
- body,
102
- });
103
- return new RunHandle(null, res.run, this);
104
- }
105
-
106
- get(taskId: string, runId: string): Promise<TaskRun> {
107
- return this.http.request<TaskRun>({
108
- method: "GET",
109
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}`,
110
- });
111
- }
112
-
113
- cancel(taskId: string, runId: string): Promise<TaskCancelResponse> {
114
- return this.http.request<TaskCancelResponse>({
115
- method: "POST",
116
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}/cancel`,
117
- });
118
- }
119
-
120
- async *stream(taskId: string, runId: string): AsyncIterable<SseEvent> {
121
- const res = await this.http.stream({
122
- path: `/v1/tasks/${encodeURIComponent(taskId)}/runs/${encodeURIComponent(runId)}/stream`,
123
- });
124
- yield* parseSse(res);
125
- }
126
- }
127
-
128
59
  /**
129
- * Cookie-authenticated `/v1/tasks` client. Mirrors the Node SDK's
130
- * `TasksApi` shape but is bound to a DP session cookie rather than a
131
- * bearer token, and lets the caller select the agent on create.
60
+ * Cookie-authenticated `/v1/tasks` client. The implementation is shared with
61
+ * Node's runner-bound task client; this browser subclass only adds the
62
+ * `identity -> metadata.identity` body mapping used by cookie-session calls.
132
63
  */
133
- export class TasksClient {
134
- readonly runs: TaskRunsClient;
135
-
136
- constructor(private readonly http: BrowserHttpClient) {
137
- this.runs = new TaskRunsClient(http);
138
- }
139
-
140
- /**
141
- * Tasks matching `params`. `await` it for the first page (preserving
142
- * the wire envelope's counts + `next` cursor), or `for await` it to
143
- * stream every task across pages (fetched lazily — `limit` sets the
144
- * page size, `next` the starting cursor; stop early to stop fetching).
145
- *
146
- * Mirrors the Node SDK's `TasksApi.list`, which is the source of truth
147
- * for the `/v1/tasks` shape.
148
- */
149
- list(params?: TaskListParams): Paginator<Task> {
150
- return cursorPaginate(
151
- (next) =>
152
- this.http.request<Paginated<Task>>({
153
- method: "GET",
154
- path: "/v1/tasks",
155
- query: { ...params, next } as Record<string, unknown>,
156
- }),
157
- params?.next,
158
- );
159
- }
160
-
161
- create(body: CreateTaskParams): Promise<TaskCreateResponse> {
162
- return this.http.request<TaskCreateResponse>({
163
- method: "POST",
164
- path: "/v1/tasks",
165
- body: toTaskBody(body),
166
- });
167
- }
168
-
169
- get(taskId: string): Promise<Task> {
170
- return this.http.request<Task>({
171
- method: "GET",
172
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
173
- });
174
- }
175
-
176
- update(taskId: string, body: TaskUpdateParams): Promise<Task> {
177
- return this.http.request<Task>({
178
- method: "PATCH",
179
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
180
- body,
181
- });
182
- }
183
-
184
- delete(taskId: string): Promise<void> {
185
- return this.http.request<void>({
186
- method: "DELETE",
187
- path: `/v1/tasks/${encodeURIComponent(taskId)}`,
188
- expect: "empty",
189
- });
190
- }
191
-
192
- archive(taskId: string): Promise<void> {
193
- return this.http.request<void>({
194
- method: "POST",
195
- path: `/v1/tasks/${encodeURIComponent(taskId)}/archive`,
196
- expect: "empty",
197
- });
198
- }
199
-
200
- unarchive(taskId: string): Promise<void> {
201
- return this.http.request<void>({
202
- method: "POST",
203
- path: `/v1/tasks/${encodeURIComponent(taskId)}/unarchive`,
204
- expect: "empty",
205
- });
206
- }
207
-
208
- /** Sugar: create a task + return a handle on its initial run. */
209
- async start(params: StartTaskParams): Promise<RunHandle> {
210
- const res = await this.create(params);
211
- return new RunHandle(res.task, res.run, this.runs);
64
+ export class TasksClient extends SharedTasksClient<
65
+ CreateTaskParams,
66
+ StartTaskParams
67
+ > {
68
+ constructor(http: ResourceHttpClient) {
69
+ super(http, toTaskBody);
212
70
  }
213
71
  }
72
+
73
+ export { RunHandle, TaskRunsClient };
@@ -1,84 +0,0 @@
1
- /**
2
- * Cookie-authenticated, read-only Conversations client for the browser
3
- * (`/v1/conversations`).
4
- *
5
- * Mirrors the Node SDK's runner-bound `ConversationsApi`, but rides the
6
- * DP `intro_dp_session` cookie via {@link BrowserHttpClient} instead of a
7
- * bearer token — so a single-page app reads conversation history with the
8
- * same identity session it uses for tasks and files. Conversations are a
9
- * projection over the immutable telemetry store: list summaries, walk a
10
- * conversation's items, or `retrieve()` the resolved state of one turn.
11
- */
12
- import type { ConversationItem, ConversationItemInclude, ConversationItemList, ConversationItemListParams, ConversationListParams, ConversationResponse, ConversationSummary } from "@introspection-sdk/types";
13
- import { Paginator } from "@introspection-sdk/http";
14
- import { BrowserHttpClient } from "./http.js";
15
- /**
16
- * Items of a conversation (`/v1/conversations/{id}/items`). Read-only.
17
- *
18
- * Paging is OpenAI-style underneath: the envelope has NO `next` token —
19
- * `list()` drives `after` = the previous page's `last_id` while
20
- * `has_more` is true.
21
- */
22
- export declare class ConversationItemsClient {
23
- private readonly http;
24
- constructor(http: BrowserHttpClient);
25
- /**
26
- * List items of a conversation. `await` the result for the first page
27
- * (an OpenAI-style {@link ConversationItemList} envelope), or
28
- * `for await` it to stream every item across pages (fetched lazily —
29
- * `limit` sets the page size, `after` the starting cursor; stop early to
30
- * stop fetching). Pass `order: "asc"` to walk the transcript from the
31
- * start.
32
- *
33
- * Items carry the turn-local delta in `input_messages` — only the
34
- * messages new to that turn. Use `get()` for the full input history.
35
- */
36
- list(conversationId: string, params?: ConversationItemListParams): Paginator<ConversationItem, ConversationItemList>;
37
- /**
38
- * Fetch a single conversation item. Unlike the list route, the
39
- * detail's `input_messages` is the FULL input history for that span.
40
- */
41
- get(conversationId: string, itemId: string, params?: {
42
- include?: ConversationItemInclude[];
43
- }): Promise<ConversationItem>;
44
- }
45
- /**
46
- * Read-only Conversations client (`/v1/conversations`).
47
- *
48
- * Both `list()` and `items.list()` are auto-paging, but they drive
49
- * different wire protocols underneath: `list()` walks the standard
50
- * Introspection cursor envelope's opaque `next` token, while
51
- * `items.list()` walks an OpenAI-style envelope via `after` = the
52
- * previous page's `last_id` while `has_more` is true.
53
- */
54
- export declare class ConversationsClient {
55
- private readonly http;
56
- /** Items of a conversation — `conversations.items.list(...)` etc. */
57
- readonly items: ConversationItemsClient;
58
- constructor(http: BrowserHttpClient);
59
- /**
60
- * List conversation summaries matching `params`. `await` the result for
61
- * the first page, or `for await` it to stream every summary across
62
- * pages (fetched lazily — `limit` sets the page size, `next` the
63
- * starting cursor; stop early to stop fetching).
64
- */
65
- list(params?: ConversationListParams): Paginator<ConversationSummary>;
66
- /**
67
- * Responses-API-style retrieve: load the state of a conversation as of
68
- * one item — the full input history, output, system instructions, and
69
- * tool definitions of that turn.
70
- *
71
- * When `itemId` is omitted, the latest LLM turn is used: the first
72
- * item (in descending order) whose `node_type` is `"assistant"` or
73
- * whose `operation_name` is `"chat"`, falling back to the first item
74
- * with a non-null `output_message`. Returns `null` when the
75
- * conversation has no items.
76
- *
77
- * For the full per-turn transcript instead, iterate
78
- * `items.list(conversationId, { order: "asc" })`.
79
- */
80
- retrieve(conversationId: string, itemId?: string): Promise<ConversationResponse | null>;
81
- /** Scan items in descending order for the most recent LLM turn. */
82
- private findLatestTurnId;
83
- }
84
- //# sourceMappingURL=conversations.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/api/conversations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EAIpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAkB,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAS9C;;;;;;GAMG;AACH,qBAAa,uBAAuB;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,iBAAiB;IAEpD;;;;;;;;;;OAUG;IACH,IAAI,CACF,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,0BAA0B,GAClC,SAAS,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;IAiBpD;;;OAGG;IACH,GAAG,CACD,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAA;KAAE,GAC/C,OAAO,CAAC,gBAAgB,CAAC;CAO7B;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAIlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAC;gBAEX,IAAI,EAAE,iBAAiB;IAIpD;;;;;OAKG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC,mBAAmB,CAAC;IAYrE;;;;;;;;;;;;;OAaG;IACG,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA6BvC,mEAAmE;YACrD,gBAAgB;CAc/B"}