@opengeni/sdk 3.2.2 → 3.3.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.
Files changed (44) hide show
  1. package/README.md +21 -0
  2. package/dist/artifacts.js +4 -4
  3. package/dist/browser.js +2 -2
  4. package/dist/chat/index.js +15 -349
  5. package/dist/chat/index.js.map +1 -1
  6. package/dist/{chunk-JKG75TTU.js → chunk-BWAJPU5S.js} +12 -2
  7. package/dist/chunk-BWAJPU5S.js.map +1 -0
  8. package/dist/{chunk-PBVUAXSU.js → chunk-F4OXWFCU.js} +217 -7
  9. package/dist/chunk-F4OXWFCU.js.map +1 -0
  10. package/dist/{chunk-N2I422X4.js → chunk-HP7NVCAX.js} +3 -11
  11. package/dist/chunk-HP7NVCAX.js.map +1 -0
  12. package/dist/{chunk-JP62FZSI.js → chunk-MJWC6GTA.js} +2 -2
  13. package/dist/chunk-OV3POE62.js +359 -0
  14. package/dist/chunk-OV3POE62.js.map +1 -0
  15. package/dist/{chunk-PDU6EU2M.js → chunk-S5XTUA7L.js} +2 -2
  16. package/dist/{chunk-VPVMLM7Q.js → chunk-X5ITQVXE.js} +1 -1
  17. package/dist/chunk-X5ITQVXE.js.map +1 -0
  18. package/dist/client.d.ts +3 -0
  19. package/dist/core.js +3 -3
  20. package/dist/document-authority.js +3 -3
  21. package/dist/index.js +11 -9
  22. package/dist/index.js.map +1 -1
  23. package/dist/insights-usage.d.ts +1 -1
  24. package/dist/insights-usage.js +1 -1
  25. package/dist/site-ai.d.ts +35 -0
  26. package/dist/site-bridge-host.js +4 -3
  27. package/dist/site-bridge-host.js.map +1 -1
  28. package/dist/site-browser-runtime.gen.d.ts +1 -1
  29. package/dist/site-document.js +1 -1
  30. package/dist/site-document.js.map +1 -1
  31. package/dist/site.d.ts +4 -0
  32. package/dist/site.js +4 -3
  33. package/package.json +3 -3
  34. package/src/client.ts +19 -0
  35. package/src/insights-usage.ts +3 -0
  36. package/src/site-ai.ts +284 -0
  37. package/src/site-browser-runtime.gen.ts +1 -1
  38. package/src/site.ts +16 -5
  39. package/dist/chunk-JKG75TTU.js.map +0 -1
  40. package/dist/chunk-N2I422X4.js.map +0 -1
  41. package/dist/chunk-PBVUAXSU.js.map +0 -1
  42. package/dist/chunk-VPVMLM7Q.js.map +0 -1
  43. /package/dist/{chunk-JP62FZSI.js.map → chunk-MJWC6GTA.js.map} +0 -0
  44. /package/dist/{chunk-PDU6EU2M.js.map → chunk-S5XTUA7L.js.map} +0 -0
package/README.md CHANGED
@@ -1115,6 +1115,27 @@ never enter the iframe; `@opengeni/sdk/site` uses a single parent-owned
1115
1115
  `MessagePort` that exposes only the retained tool allowlist intersected with the
1116
1116
  current viewer's live workspace catalog.
1117
1117
 
1118
+ Site AI can return directly into an app without any conversation UI:
1119
+
1120
+ ```ts
1121
+ import { createOpenGeniSiteClient } from "@opengeni/sdk/site";
1122
+ const site = createOpenGeniSiteClient();
1123
+ const result = await site.ai.run({ initialMessage: appPrompt, idempotencyKey: actionId });
1124
+ if (result.status === "completed") renderResult(result.text);
1125
+ ```
1126
+
1127
+ The app defines the prompt, context and output presentation. This helper uses
1128
+ native sessions and events with the same permissions, approvals, model access
1129
+ and billing; it is not a second executor. New Site work is private per viewer
1130
+ and excluded from ordinary workspace discovery. `pending` and `cancelled` are
1131
+ not successful results; model failure rejects. Retain the `onSession` handle
1132
+ to observe again using `site.ai.result(id, { turnId })`, without creating work.
1133
+ An `after` cursor returns only subsequent output; omit it for full replay.
1134
+ Aborting observation does not cancel native execution. See
1135
+ [`site-conversations.md`](../../docs/site-conversations.md) and
1136
+ [`site-session-embed`](../../examples/site-session-embed) for optional chat and
1137
+ headless inline examples. Do not store private handles in shared Site Data.
1138
+
1118
1139
  ```ts
1119
1140
  let cursor: string | undefined;
1120
1141
  do {
package/dist/artifacts.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  OpenGeniClient
3
- } from "./chunk-PDU6EU2M.js";
4
- import "./chunk-JP62FZSI.js";
5
- import "./chunk-JKG75TTU.js";
6
- import "./chunk-VPVMLM7Q.js";
3
+ } from "./chunk-S5XTUA7L.js";
4
+ import "./chunk-MJWC6GTA.js";
5
+ import "./chunk-BWAJPU5S.js";
6
+ import "./chunk-X5ITQVXE.js";
7
7
  import "./chunk-4AHR4KGA.js";
8
8
  import "./chunk-KADZ5PGG.js";
9
9
  import "./chunk-O7KANXC3.js";
package/dist/browser.js CHANGED
@@ -8,8 +8,8 @@ import {
8
8
  } from "./chunk-P7UWKORG.js";
9
9
  import {
10
10
  OpenGeniClient
11
- } from "./chunk-JKG75TTU.js";
12
- import "./chunk-VPVMLM7Q.js";
11
+ } from "./chunk-BWAJPU5S.js";
12
+ import "./chunk-X5ITQVXE.js";
13
13
  import "./chunk-4AHR4KGA.js";
14
14
  import {
15
15
  OPENGENI_API_CONTRACT_HEADER,
@@ -8,17 +8,24 @@ import {
8
8
  uuidV5
9
9
  } from "../chunk-XA7HVIHI.js";
10
10
  import {
11
- EMPTY_FINAL_REPLY_NOTICE,
12
- OpenGeniEmbeddingClient,
13
- turnCompletedWithEmptyFinalReply
14
- } from "../chunk-N2I422X4.js";
15
- import "../chunk-PDU6EU2M.js";
16
- import "../chunk-JP62FZSI.js";
11
+ OpenGeniEmbeddingClient
12
+ } from "../chunk-HP7NVCAX.js";
13
+ import "../chunk-S5XTUA7L.js";
14
+ import "../chunk-MJWC6GTA.js";
17
15
  import {
18
16
  chatDefaults
19
17
  } from "../chunk-UM4ZXXJR.js";
20
- import "../chunk-JKG75TTU.js";
21
- import "../chunk-VPVMLM7Q.js";
18
+ import {
19
+ ChatPendingFold,
20
+ ChatTurnFold,
21
+ OpenGeniChatError,
22
+ approvalPending,
23
+ asRecord,
24
+ humanInputPending,
25
+ stringValue
26
+ } from "../chunk-OV3POE62.js";
27
+ import "../chunk-BWAJPU5S.js";
28
+ import "../chunk-X5ITQVXE.js";
22
29
  import {
23
30
  parseSseStream
24
31
  } from "../chunk-4AHR4KGA.js";
@@ -29,347 +36,6 @@ import {
29
36
  OpenGeniSetupError
30
37
  } from "../chunk-7EWT3PV6.js";
31
38
 
32
- // src/chat/types.ts
33
- var OpenGeniChatError = class extends Error {
34
- code;
35
- event;
36
- constructor(code, message, event = null) {
37
- super(message);
38
- this.name = "OpenGeniChatError";
39
- this.code = code;
40
- this.event = event;
41
- }
42
- };
43
-
44
- // src/chat/fold.ts
45
- var ChatPendingFold = class {
46
- requests = /* @__PURE__ */ new Map();
47
- push(event) {
48
- const payload = asRecord(event.payload);
49
- if (event.type === "session.requiresAction") {
50
- for (const [key, request] of this.requests) {
51
- if (request.pending.kind === "approval") this.requests.delete(key);
52
- }
53
- for (const approval of Array.isArray(payload.approvals) ? payload.approvals : []) {
54
- const pending = approvalPending({ approvals: [approval] });
55
- if (pending) this.put(pending, event.turnId ?? null);
56
- }
57
- } else if (event.type === "session.humanInput.requested") {
58
- const pending = humanInputPending(payload);
59
- if (pending) this.put(pending, event.turnId ?? null);
60
- } else if (event.type === "user.approvalDecision") {
61
- this.requests.delete(`approval:${payload.approvalId}`);
62
- } else if (event.type === "user.humanInputResponse") {
63
- this.requests.delete(`human_input:${payload.requestId}`);
64
- } else if (["turn.completed", "turn.failed", "turn.cancelled"].includes(event.type)) {
65
- for (const [key, request] of this.requests) {
66
- if (request.turnId === null || event.turnId == null || request.turnId === event.turnId) {
67
- this.requests.delete(key);
68
- }
69
- }
70
- }
71
- }
72
- pending(now = Date.now()) {
73
- return [...this.requests.values()].map((request) => request.pending).filter((pending) => {
74
- if (pending.kind !== "human_input") return true;
75
- const expiresAt = asRecord(pending.payload).expiresAt;
76
- return expiresAt == null || typeof expiresAt === "string" && Date.parse(expiresAt) > now;
77
- });
78
- }
79
- put(pending, turnId) {
80
- this.requests.set(`${pending.kind}:${pending.requestId}`, { pending, turnId });
81
- }
82
- };
83
- function noStep() {
84
- return { chunks: [], terminal: null };
85
- }
86
- var ChatTurnFold = class {
87
- constructor(workspaceId, sessionId, expectedTurnId) {
88
- this.workspaceId = workspaceId;
89
- this.sessionId = sessionId;
90
- this.turnId = expectedTurnId;
91
- }
92
- events = [];
93
- turnId;
94
- pending = null;
95
- failure = null;
96
- emptyFinalReply = false;
97
- segments = [];
98
- openTools = /* @__PURE__ */ new Map();
99
- get text() {
100
- return this.segments.filter((segment) => !segment.commentary).map((segment) => segment.text).filter((text) => text.length > 0).join("\n\n");
101
- }
102
- push(event) {
103
- const eventTurnId = typeof event.turnId === "string" ? event.turnId : null;
104
- if (this.turnId && eventTurnId && eventTurnId !== this.turnId) {
105
- return { chunks: [], terminal: null };
106
- }
107
- if (!this.turnId && eventTurnId && isTurnScopedType(event.type)) {
108
- this.turnId = eventTurnId;
109
- }
110
- this.events.push(event);
111
- const payload = asRecord(event.payload);
112
- switch (event.type) {
113
- case "agent.message.delta": {
114
- const text = stringValue(payload.text);
115
- if (!text) return noStep();
116
- const messageId = stringValue(payload.messageId) || null;
117
- if (messageId) return this.messageDelta(messageId, text, isCommentary(payload));
118
- const open = this.segments.at(-1);
119
- if (isCommentary(payload)) {
120
- if (open?.open && open.commentary) {
121
- open.text += text;
122
- } else {
123
- this.closeSegments();
124
- this.segments.push({ text, open: true, commentary: true, messageId: null });
125
- }
126
- return noStep();
127
- }
128
- if (open?.open && !open.commentary) {
129
- open.text += text;
130
- } else {
131
- this.closeSegments();
132
- return { chunks: [this.startSegment(text, true, null)], terminal: null };
133
- }
134
- return { chunks: [{ type: "text", text }], terminal: null };
135
- }
136
- case "agent.message.completed": {
137
- const text = stringValue(payload.text) ?? "";
138
- const messageId = stringValue(payload.messageId) || null;
139
- if (messageId) return this.messageCompleted(messageId, text, isCommentary(payload));
140
- const last = this.segments.at(-1);
141
- if (isCommentary(payload)) {
142
- if (last?.commentary && (last.open || text.startsWith(last.text))) {
143
- last.open = false;
144
- if (text) last.text = text;
145
- return noStep();
146
- }
147
- const streamed = last && !last.commentary && last.open && text.startsWith(last.text);
148
- if (!streamed) {
149
- if (text) {
150
- this.closeSegments();
151
- this.segments.push({ text, open: false, commentary: true, messageId: null });
152
- }
153
- return noStep();
154
- }
155
- }
156
- const target = last?.commentary ? void 0 : last;
157
- if (!target || !target.open && target.text && !text.startsWith(target.text)) {
158
- if (!text) return noStep();
159
- if (payload.phase === void 0 && this.latestAnswer()?.text === text) return noStep();
160
- this.closeSegments();
161
- return { chunks: [this.startSegment(text, false, null)], terminal: null };
162
- }
163
- target.open = false;
164
- return { chunks: this.extendAnswer(target, text), terminal: null };
165
- }
166
- case "agent.toolCall.created": {
167
- this.closeSegments();
168
- const name = stringValue(payload.name) ?? "tool";
169
- const callId = stringValue(payload.id);
170
- if (callId) this.openTools.set(callId, name);
171
- return {
172
- chunks: [
173
- {
174
- type: "tool",
175
- name,
176
- status: "started",
177
- ...callId ? { callId } : {},
178
- ..."arguments" in payload ? { input: payload.arguments } : {}
179
- }
180
- ],
181
- terminal: null
182
- };
183
- }
184
- case "agent.toolCall.output": {
185
- const callId = stringValue(payload.id);
186
- const name = (callId ? this.openTools.get(callId) : void 0) ?? "tool";
187
- if (callId) this.openTools.delete(callId);
188
- return {
189
- chunks: [
190
- {
191
- type: "tool",
192
- name,
193
- status: isErrorOutput(payload) ? "failed" : "completed",
194
- ...callId ? { callId } : {}
195
- }
196
- ],
197
- terminal: null
198
- };
199
- }
200
- case "session.requiresAction": {
201
- const pending = approvalPending(payload);
202
- if (!pending) return { chunks: [], terminal: null };
203
- this.pending = pending;
204
- return {
205
- chunks: [...this.settleSegments(), { type: "pending", pending }],
206
- terminal: "pending"
207
- };
208
- }
209
- case "session.humanInput.requested": {
210
- const pending = humanInputPending(payload);
211
- if (!pending) return { chunks: [], terminal: null };
212
- this.pending = pending;
213
- return {
214
- chunks: [...this.settleSegments(), { type: "pending", pending }],
215
- terminal: "pending"
216
- };
217
- }
218
- case "turn.completed":
219
- this.emptyFinalReply = turnCompletedWithEmptyFinalReply(payload);
220
- return { chunks: this.settleSegments(), terminal: "completed" };
221
- case "turn.failed":
222
- this.failure = event;
223
- return { chunks: this.settleSegments(), terminal: "failed" };
224
- case "turn.cancelled":
225
- return { chunks: this.settleSegments(), terminal: "cancelled" };
226
- default:
227
- return { chunks: [], terminal: null };
228
- }
229
- }
230
- reply(terminal) {
231
- const text = this.text;
232
- return {
233
- text,
234
- sessionId: this.sessionId,
235
- workspaceId: this.workspaceId,
236
- turnId: this.turnId,
237
- status: terminal === "pending" ? "pending" : terminal === "cancelled" ? "cancelled" : "completed",
238
- pending: this.pending,
239
- ...this.emptyFinalReply ? { emptyFinalReply: true, notice: EMPTY_FINAL_REPLY_NOTICE } : {},
240
- events: [...this.events],
241
- toString: () => text
242
- };
243
- }
244
- /** The error to throw for a `turn.failed` settlement. */
245
- failureError() {
246
- const payload = asRecord(this.failure?.payload);
247
- const code = stringValue(payload.code) ?? "turn_failed";
248
- const message = stringValue(payload.error) ?? stringValue(payload.message) ?? "The turn failed.";
249
- return new OpenGeniChatError(code, message, this.failure);
250
- }
251
- messageDelta(messageId, text, commentary) {
252
- const segment = this.segmentOf(messageId);
253
- if (segment?.open) {
254
- segment.text += text;
255
- return segment.commentary ? noStep() : { chunks: [{ type: "text", text }], terminal: null };
256
- }
257
- this.closeSegments();
258
- if (commentary) {
259
- this.segments.push({ text, open: true, commentary: true, messageId });
260
- return noStep();
261
- }
262
- return { chunks: [this.startSegment(text, true, messageId)], terminal: null };
263
- }
264
- messageCompleted(messageId, text, commentary) {
265
- const segment = this.segmentOf(messageId) ?? this.unidentifiedStreamingSegment(text);
266
- if (segment) {
267
- segment.messageId = messageId;
268
- segment.open = false;
269
- if (segment.commentary) {
270
- if (text) segment.text = text;
271
- return noStep();
272
- }
273
- return { chunks: this.extendAnswer(segment, text), terminal: null };
274
- }
275
- if (!text) return noStep();
276
- if (commentary) {
277
- this.segments.push({ text, open: false, commentary: true, messageId });
278
- return noStep();
279
- }
280
- return { chunks: [this.startSegment(text, false, messageId)], terminal: null };
281
- }
282
- segmentOf(messageId) {
283
- return this.findLastSegment((segment) => segment.messageId === messageId);
284
- }
285
- /** Deltas that carried no identity, still streaming the text this completion names. */
286
- unidentifiedStreamingSegment(text) {
287
- const last = this.segments.at(-1);
288
- return last?.open && last.messageId === null && text.startsWith(last.text) ? last : void 0;
289
- }
290
- latestAnswer() {
291
- return this.findLastSegment((segment) => !segment.commentary);
292
- }
293
- findLastSegment(predicate) {
294
- for (let index = this.segments.length - 1; index >= 0; index -= 1) {
295
- const segment = this.segments[index];
296
- if (predicate(segment)) return segment;
297
- }
298
- return void 0;
299
- }
300
- /**
301
- * Complete an answer segment. Only the newest answer can grow: a remainder
302
- * for an earlier one would land after later text for append-only consumers.
303
- */
304
- extendAnswer(segment, text) {
305
- if (text.length <= segment.text.length || !text.startsWith(segment.text)) return [];
306
- if (segment !== this.latestAnswer()) return [];
307
- const remainder = text.slice(segment.text.length);
308
- segment.text = text;
309
- return [{ type: "text", text: remainder }];
310
- }
311
- closeSegments() {
312
- for (const segment of this.segments) segment.open = false;
313
- }
314
- /**
315
- * Close the turn's text. A turn that produced commentary but no answer text
316
- * (for example one that ends waiting for a worker) replies with its latest
317
- * commentary rather than nothing.
318
- */
319
- settleSegments() {
320
- this.closeSegments();
321
- if (this.emptyFinalReply) return [];
322
- if (this.segments.some((segment) => !segment.commentary)) return [];
323
- const latest = [...this.segments].reverse().find((segment) => segment.commentary && segment.text);
324
- if (!latest) return [];
325
- latest.commentary = false;
326
- return [{ type: "text", text: latest.text }];
327
- }
328
- startSegment(text, open, messageId) {
329
- const separator = this.segments.some((segment) => !segment.commentary) ? "\n\n" : "";
330
- this.segments.push({ text, open, commentary: false, messageId });
331
- return { type: "text", text: separator + text };
332
- }
333
- };
334
- function isCommentary(payload) {
335
- return payload.phase === "commentary";
336
- }
337
- function isTurnScopedType(type) {
338
- return type.startsWith("turn.") || type.startsWith("agent.") || type === "user.message";
339
- }
340
- function approvalPending(payload) {
341
- const approvals = Array.isArray(payload.approvals) ? payload.approvals : [];
342
- const first = approvals[0];
343
- if (!first) return null;
344
- const raw = asRecord(first);
345
- const rawItem = asRecord(raw.rawItem);
346
- const requestId = stringValue(rawItem.callId) ?? stringValue(rawItem.id) ?? stringValue(raw.id) ?? stringValue(raw.callId);
347
- if (!requestId) return null;
348
- return {
349
- kind: "approval",
350
- requestId,
351
- name: stringValue(raw.name) ?? stringValue(raw.toolName) ?? stringValue(rawItem.name) ?? null,
352
- payload: first
353
- };
354
- }
355
- function humanInputPending(payload) {
356
- const request = asRecord(payload.request);
357
- const requestId = stringValue(request.id);
358
- if (!requestId || !Array.isArray(request.questions)) return null;
359
- return { kind: "human_input", requestId, name: null, payload: payload.request };
360
- }
361
- function asRecord(value) {
362
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
363
- }
364
- function stringValue(value) {
365
- return typeof value === "string" ? value : void 0;
366
- }
367
- function isErrorOutput(payload) {
368
- if (payload.error === true || payload.failed === true) return true;
369
- const output = payload.output;
370
- return !!output && typeof output === "object" && output.isError === true;
371
- }
372
-
373
39
  // src/chat/opengeni.ts
374
40
  var DEFAULT_OPENGENI_BASE_URL = "https://app.opengeni.ai";
375
41
  var DEFAULT_CHAT_SOURCE = "app";