@opengeni/sdk 0.26.1 → 0.28.2
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/README.md +28 -0
- package/dist/index.d.ts +44 -9
- package/dist/index.js +129 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +8 -8
- package/src/index.ts +5 -1
- package/src/mcp-output.ts +161 -0
- package/src/types.ts +83 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.2",
|
|
4
4
|
"description": "Framework-agnostic TypeScript SDK for the OpenGeni API: typed client, session lifecycle, SSE event streaming with reconnect + replay-by-sequence, and proxy re-streaming helpers.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
package/src/client.ts
CHANGED
|
@@ -46,7 +46,8 @@ import type {
|
|
|
46
46
|
CreateCapabilityCatalogItemRequest,
|
|
47
47
|
CreateCheckoutRequest,
|
|
48
48
|
CreateCheckoutResponse,
|
|
49
|
-
|
|
49
|
+
OpenGeniSlackBotInstallRequest,
|
|
50
|
+
OpenGeniSlackBotInstallStart,
|
|
50
51
|
CreateConnectionRequest,
|
|
51
52
|
CreateDocumentBaseRequest,
|
|
52
53
|
CreateFileUploadRequest,
|
|
@@ -2589,17 +2590,16 @@ export class OpenGeniClient {
|
|
|
2589
2590
|
return response.connection;
|
|
2590
2591
|
}
|
|
2591
2592
|
|
|
2592
|
-
/**
|
|
2593
|
-
async
|
|
2593
|
+
/** Start the public Slack installation flow for the workspace-shared OpenGeni bot. */
|
|
2594
|
+
async startOpenGeniSlackBotInstall(
|
|
2594
2595
|
workspaceId: string,
|
|
2595
|
-
request:
|
|
2596
|
-
): Promise<
|
|
2597
|
-
|
|
2596
|
+
request: OpenGeniSlackBotInstallRequest = {},
|
|
2597
|
+
): Promise<OpenGeniSlackBotInstallStart> {
|
|
2598
|
+
return await this.requestJson<OpenGeniSlackBotInstallStart>(
|
|
2598
2599
|
"POST",
|
|
2599
|
-
`/v1/workspaces/${workspaceId}/connections/slack-bot`,
|
|
2600
|
+
`/v1/workspaces/${workspaceId}/connections/slack-bot/install`,
|
|
2600
2601
|
request,
|
|
2601
2602
|
);
|
|
2602
|
-
return response.connection;
|
|
2603
2603
|
}
|
|
2604
2604
|
|
|
2605
2605
|
async updateConnection(
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ export {
|
|
|
24
24
|
export type { ProxySessionEventStreamOptions, SseReStreamOptions } from "./proxy";
|
|
25
25
|
export { parseSseStream } from "./sse";
|
|
26
26
|
export type { SseMessage } from "./sse";
|
|
27
|
+
export { normalizeMcpOutput } from "./mcp-output";
|
|
28
|
+
export type { NormalizedMcpOutput } from "./mcp-output";
|
|
27
29
|
// Desktop (noVNC) transport contract — pure, zero-dep (the RFB import lives in
|
|
28
30
|
// @opengeni/react). URL assembler + connection state machine + rotation fence.
|
|
29
31
|
export { desktopSocketUrl, nextDesktopState, applyUrlRotation } from "./desktop";
|
|
@@ -191,7 +193,8 @@ export type {
|
|
|
191
193
|
CreateApiKeyRequest,
|
|
192
194
|
CreateApiKeyResponse,
|
|
193
195
|
CreateCapabilityCatalogItemRequest,
|
|
194
|
-
|
|
196
|
+
OpenGeniSlackBotInstallRequest,
|
|
197
|
+
OpenGeniSlackBotInstallStart,
|
|
195
198
|
CreateConnectionRequest,
|
|
196
199
|
CreateCheckoutRequest,
|
|
197
200
|
CreateCheckoutResponse,
|
|
@@ -321,6 +324,7 @@ export type {
|
|
|
321
324
|
SessionCommandReceipt,
|
|
322
325
|
SteerSessionQueueItemRequest,
|
|
323
326
|
WorkspaceInferenceControlResponse,
|
|
327
|
+
SessionPendingInputPreview,
|
|
324
328
|
SessionSystemUpdate,
|
|
325
329
|
SessionSystemUpdateKind,
|
|
326
330
|
SessionSystemUpdateState,
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A transport-tolerant MCP tool result.
|
|
3
|
+
*
|
|
4
|
+
* `value` is the canonical machine-readable payload after recognized MCP/JSON
|
|
5
|
+
* envelopes are removed. `text` is the best presentation string without
|
|
6
|
+
* discarding structured data. `raw` always retains the original evidence.
|
|
7
|
+
*/
|
|
8
|
+
export type NormalizedMcpOutput = Readonly<{
|
|
9
|
+
raw: unknown;
|
|
10
|
+
value: unknown;
|
|
11
|
+
text: string;
|
|
12
|
+
isError: boolean;
|
|
13
|
+
}>;
|
|
14
|
+
|
|
15
|
+
const MAX_MCP_OUTPUT_DEPTH = 8;
|
|
16
|
+
const RESULT_ENVELOPE_KEYS = new Set(["result", "isError", "jsonrpc", "id", "_meta"]);
|
|
17
|
+
|
|
18
|
+
/** Normalize common direct, JSON, and standard MCP result envelopes without throwing. */
|
|
19
|
+
export function normalizeMcpOutput(output: unknown): NormalizedMcpOutput {
|
|
20
|
+
const normalized = normalizeValue(output, 0, new Set<object>());
|
|
21
|
+
return {
|
|
22
|
+
raw: output,
|
|
23
|
+
value: normalized.value,
|
|
24
|
+
text: normalized.text,
|
|
25
|
+
isError: normalized.isError,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type NormalizedValue = Omit<NormalizedMcpOutput, "raw">;
|
|
30
|
+
|
|
31
|
+
function normalizeValue(value: unknown, depth: number, ancestors: Set<object>): NormalizedValue {
|
|
32
|
+
if (value === null || value === undefined) {
|
|
33
|
+
return { value, text: "", isError: false };
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === "string") {
|
|
36
|
+
return normalizeText(value, depth, ancestors);
|
|
37
|
+
}
|
|
38
|
+
if (typeof value !== "object") {
|
|
39
|
+
return { value, text: String(value), isError: false };
|
|
40
|
+
}
|
|
41
|
+
if (depth >= MAX_MCP_OUTPUT_DEPTH || ancestors.has(value)) {
|
|
42
|
+
return { value, text: safeStringify(value), isError: false };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
ancestors.add(value);
|
|
46
|
+
try {
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
return { value, text: safeStringify(value), isError: false };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const record = value as Record<string, unknown>;
|
|
52
|
+
const envelopeError = record.isError === true;
|
|
53
|
+
|
|
54
|
+
if (record.type === "text" && typeof record.text === "string") {
|
|
55
|
+
const normalized = normalizeText(record.text, depth + 1, ancestors);
|
|
56
|
+
return {
|
|
57
|
+
value: normalized.value,
|
|
58
|
+
text: record.text,
|
|
59
|
+
isError: envelopeError || normalized.isError,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if ("structuredContent" in record) {
|
|
64
|
+
const normalized = normalizeValue(record.structuredContent, depth + 1, ancestors);
|
|
65
|
+
return {
|
|
66
|
+
value: normalized.value,
|
|
67
|
+
text: firstMcpText(record.content) ?? normalized.text,
|
|
68
|
+
isError: envelopeError || normalized.isError,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (isMcpContent(record.content)) {
|
|
73
|
+
const text = firstMcpText(record.content);
|
|
74
|
+
if (text !== null) {
|
|
75
|
+
const normalized = normalizeText(text, depth + 1, ancestors);
|
|
76
|
+
return {
|
|
77
|
+
value: normalized.value,
|
|
78
|
+
text,
|
|
79
|
+
isError: envelopeError || normalized.isError,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
value,
|
|
84
|
+
text: safeStringify(value),
|
|
85
|
+
isError: envelopeError,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isResultEnvelope(record)) {
|
|
90
|
+
const normalized = normalizeValue(record.result, depth + 1, ancestors);
|
|
91
|
+
return {
|
|
92
|
+
value: normalized.value,
|
|
93
|
+
text: normalized.text,
|
|
94
|
+
isError: envelopeError || normalized.isError,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
value,
|
|
100
|
+
text: safeStringify(value),
|
|
101
|
+
isError: envelopeError,
|
|
102
|
+
};
|
|
103
|
+
} finally {
|
|
104
|
+
ancestors.delete(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function normalizeText(text: string, depth: number, ancestors: Set<object>): NormalizedValue {
|
|
109
|
+
try {
|
|
110
|
+
const parsed: unknown = JSON.parse(text);
|
|
111
|
+
const normalized = normalizeValue(parsed, depth + 1, ancestors);
|
|
112
|
+
return {
|
|
113
|
+
value: normalized.value,
|
|
114
|
+
text,
|
|
115
|
+
isError: normalized.isError,
|
|
116
|
+
};
|
|
117
|
+
} catch {
|
|
118
|
+
return { value: text, text, isError: false };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function isMcpContent(value: unknown): value is readonly Record<string, unknown>[] {
|
|
123
|
+
return (
|
|
124
|
+
Array.isArray(value) &&
|
|
125
|
+
value.some(
|
|
126
|
+
(part) =>
|
|
127
|
+
part !== null &&
|
|
128
|
+
typeof part === "object" &&
|
|
129
|
+
typeof (part as { type?: unknown }).type === "string",
|
|
130
|
+
)
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function firstMcpText(value: unknown): string | null {
|
|
135
|
+
if (!Array.isArray(value)) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
for (const part of value) {
|
|
139
|
+
if (
|
|
140
|
+
part !== null &&
|
|
141
|
+
typeof part === "object" &&
|
|
142
|
+
(part as { type?: unknown }).type === "text" &&
|
|
143
|
+
typeof (part as { text?: unknown }).text === "string"
|
|
144
|
+
) {
|
|
145
|
+
return (part as { text: string }).text;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function isResultEnvelope(record: Record<string, unknown>): boolean {
|
|
152
|
+
return "result" in record && Object.keys(record).every((key) => RESULT_ENVELOPE_KEYS.has(key));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function safeStringify(value: unknown): string {
|
|
156
|
+
try {
|
|
157
|
+
return JSON.stringify(value) ?? "";
|
|
158
|
+
} catch {
|
|
159
|
+
return String(value);
|
|
160
|
+
}
|
|
161
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -408,13 +408,16 @@ export type CreateConnectionRequest = {
|
|
|
408
408
|
metadata?: Record<string, unknown> | undefined;
|
|
409
409
|
};
|
|
410
410
|
|
|
411
|
-
export type
|
|
412
|
-
/** Write-only Slack bot token. It is never returned by the API. */
|
|
413
|
-
token: string;
|
|
411
|
+
export type OpenGeniSlackBotInstallRequest = {
|
|
414
412
|
/** Existing OpenGeni Slack bot connection to reinstall in place. */
|
|
415
413
|
connectionId?: string | undefined;
|
|
416
414
|
};
|
|
417
415
|
|
|
416
|
+
export type OpenGeniSlackBotInstallStart = {
|
|
417
|
+
authorizationUrl: string;
|
|
418
|
+
expiresAt: string;
|
|
419
|
+
};
|
|
420
|
+
|
|
418
421
|
export type UpdateConnectionRequest = {
|
|
419
422
|
providerDomain?: string | undefined;
|
|
420
423
|
subjectId?: string | null | undefined;
|
|
@@ -491,6 +494,7 @@ export type Session = {
|
|
|
491
494
|
// the session carried none. Org-visible metadata, never a timeline event.
|
|
492
495
|
instructions: string | null;
|
|
493
496
|
resources: ResourceRef[];
|
|
497
|
+
skills: SessionSkill[];
|
|
494
498
|
tools: ToolRef[];
|
|
495
499
|
toolPolicy?: SessionToolPolicy | undefined;
|
|
496
500
|
toolPolicyVersion?: number | undefined;
|
|
@@ -513,6 +517,7 @@ export type Session = {
|
|
|
513
517
|
rigId: string | null;
|
|
514
518
|
rigVersionId: string | null;
|
|
515
519
|
firstPartyMcpPermissions: string[] | null;
|
|
520
|
+
firstPartyMcpTools: FirstPartyMcpToolName[] | null;
|
|
516
521
|
mcpServers: SessionMcpServerMetadata[];
|
|
517
522
|
parentSessionId: string | null;
|
|
518
523
|
/** Immutable server-authored nested-agent lineage and policy snapshot. */
|
|
@@ -754,6 +759,9 @@ export const SESSION_EVENT_TYPES = [
|
|
|
754
759
|
"goal.continuation",
|
|
755
760
|
"system.update.pending",
|
|
756
761
|
"system.update.delivered",
|
|
762
|
+
"system.update.superseded",
|
|
763
|
+
"system.update.cancelled",
|
|
764
|
+
"system.update.settled",
|
|
757
765
|
"session.control.paused",
|
|
758
766
|
"session.control.resumed",
|
|
759
767
|
"session.control.steer_requested",
|
|
@@ -1560,6 +1568,8 @@ export type CreateSessionRequest = {
|
|
|
1560
1568
|
// user-visible timeline. Trimmed, non-empty, max 32768 chars.
|
|
1561
1569
|
instructions?: string | undefined;
|
|
1562
1570
|
resources?: ResourceRef[] | undefined;
|
|
1571
|
+
/** Inline skills fixed onto this session; omitted children inherit them. */
|
|
1572
|
+
skills?: SessionSkill[] | undefined;
|
|
1563
1573
|
tools?: ToolRef[] | undefined;
|
|
1564
1574
|
metadata?: Record<string, unknown> | undefined;
|
|
1565
1575
|
model?: string | undefined;
|
|
@@ -1588,6 +1598,7 @@ export type CreateSessionRequest = {
|
|
|
1588
1598
|
expectedNewSessionDraftRevision?: number | undefined;
|
|
1589
1599
|
maxNestedAgentDepth?: number | undefined;
|
|
1590
1600
|
firstPartyMcpPermissions?: string[] | undefined;
|
|
1601
|
+
firstPartyMcpTools?: FirstPartyMcpToolName[] | undefined;
|
|
1591
1602
|
mcpServers?: SessionMcpServerInput[] | undefined;
|
|
1592
1603
|
// Shared-sandbox placement (mirror of `@opengeni/contracts` CreateSessionRequest.sandbox,
|
|
1593
1604
|
// addendum 05 §D.1). Three-way union; OMITTED ⇒ the context-dependent server default
|
|
@@ -1653,6 +1664,58 @@ export type KnownPermission = (typeof KNOWN_PERMISSIONS)[number];
|
|
|
1653
1664
|
*/
|
|
1654
1665
|
export type Permission = KnownPermission | (string & {});
|
|
1655
1666
|
|
|
1667
|
+
export type FirstPartyMcpToolName =
|
|
1668
|
+
| "set_session_title"
|
|
1669
|
+
| "goal_set"
|
|
1670
|
+
| "goal_update"
|
|
1671
|
+
| "goal_complete"
|
|
1672
|
+
| "goal_pause"
|
|
1673
|
+
| "memory_search"
|
|
1674
|
+
| "memory_save"
|
|
1675
|
+
| "memory_correct"
|
|
1676
|
+
| "sandboxes_list"
|
|
1677
|
+
| "sandbox_attach"
|
|
1678
|
+
| "sandbox_swap"
|
|
1679
|
+
| "run_on"
|
|
1680
|
+
| "sandbox_provision"
|
|
1681
|
+
| "rig_list"
|
|
1682
|
+
| "rig_get"
|
|
1683
|
+
| "rig_propose_change"
|
|
1684
|
+
| "rig_verify"
|
|
1685
|
+
| "rig_promote"
|
|
1686
|
+
| "sessions_list"
|
|
1687
|
+
| "session_get"
|
|
1688
|
+
| "session_events"
|
|
1689
|
+
| "session_create"
|
|
1690
|
+
| "session_send_message"
|
|
1691
|
+
| "session_pause"
|
|
1692
|
+
| "session_resume"
|
|
1693
|
+
| "session_steer"
|
|
1694
|
+
| "set_other_session_title"
|
|
1695
|
+
| "variable_set_list"
|
|
1696
|
+
| "environment_list"
|
|
1697
|
+
| "variable_set_set_variable"
|
|
1698
|
+
| "environment_set_variable"
|
|
1699
|
+
| "github_connect_link"
|
|
1700
|
+
| "github_token"
|
|
1701
|
+
| "github_repositories_list"
|
|
1702
|
+
| "social_connections_list"
|
|
1703
|
+
| "social_posts_recent"
|
|
1704
|
+
| "social_daily_analysis_context"
|
|
1705
|
+
| "scheduled_tasks_list"
|
|
1706
|
+
| "scheduled_tasks_get"
|
|
1707
|
+
| "scheduled_tasks_create"
|
|
1708
|
+
| "scheduled_tasks_update"
|
|
1709
|
+
| "scheduled_tasks_pause"
|
|
1710
|
+
| "scheduled_tasks_resume"
|
|
1711
|
+
| "scheduled_tasks_trigger"
|
|
1712
|
+
| "scheduled_tasks_delete"
|
|
1713
|
+
| "scheduled_task_runs_list"
|
|
1714
|
+
| "slack_bot_list_channels"
|
|
1715
|
+
| "slack_bot_channel_history"
|
|
1716
|
+
| "slack_bot_list_users"
|
|
1717
|
+
| "slack_bot_post_message";
|
|
1718
|
+
|
|
1656
1719
|
export type ProductAccessMode = "local" | "configured" | "managed";
|
|
1657
1720
|
|
|
1658
1721
|
export type ModelCapabilitySupportV1 = "supported" | "unsupported" | "unknown";
|
|
@@ -2365,8 +2428,20 @@ export type SessionQueueSnapshot = {
|
|
|
2365
2428
|
/** The latest interrupted attempt has not yet durably proved physical quiescence. */
|
|
2366
2429
|
stoppingPreviousAttempt: boolean;
|
|
2367
2430
|
items: SessionTurn[];
|
|
2431
|
+
/** Canonical pending machine inputs. Events only invalidate this snapshot. */
|
|
2432
|
+
pendingInputs: SessionPendingInputPreview[];
|
|
2433
|
+
/** Exact next bounded input batch that will join an already-waiting prompt. */
|
|
2434
|
+
pendingInputAttachment: {
|
|
2435
|
+
turnId: string;
|
|
2436
|
+
inputIds: string[];
|
|
2437
|
+
} | null;
|
|
2368
2438
|
};
|
|
2369
2439
|
|
|
2440
|
+
export type SessionPendingInputPreview = Pick<
|
|
2441
|
+
SessionSystemUpdate,
|
|
2442
|
+
"id" | "sessionId" | "kind" | "classification" | "sourceId" | "summary" | "createdAt"
|
|
2443
|
+
>;
|
|
2444
|
+
|
|
2370
2445
|
export type SystemUpdateClassification = "success" | "failure" | "action_required" | "info";
|
|
2371
2446
|
|
|
2372
2447
|
export type SessionSystemUpdateKind =
|
|
@@ -2378,7 +2453,6 @@ export type SessionSystemUpdateKind =
|
|
|
2378
2453
|
|
|
2379
2454
|
export type SessionSystemUpdateState =
|
|
2380
2455
|
| "pending"
|
|
2381
|
-
| "deferred"
|
|
2382
2456
|
| "delivered"
|
|
2383
2457
|
| "cancelled"
|
|
2384
2458
|
| "superseded"
|
|
@@ -2396,6 +2470,7 @@ export type SessionSystemUpdate = {
|
|
|
2396
2470
|
lineage: Record<string, unknown>;
|
|
2397
2471
|
state: SessionSystemUpdateState;
|
|
2398
2472
|
deliveredTurnId: string | null;
|
|
2473
|
+
deliveredHistoryItemId: string | null;
|
|
2399
2474
|
deliveredAt: string | null;
|
|
2400
2475
|
createdAt: string;
|
|
2401
2476
|
};
|
|
@@ -3125,6 +3200,8 @@ export type CapabilityPackSkill = {
|
|
|
3125
3200
|
files: CapabilityPackSkillFile[];
|
|
3126
3201
|
};
|
|
3127
3202
|
|
|
3203
|
+
export type SessionSkill = CapabilityPackSkill;
|
|
3204
|
+
|
|
3128
3205
|
export type CapabilityPackVariableSetSpec = {
|
|
3129
3206
|
description: string;
|
|
3130
3207
|
requiredVariables: string[];
|
|
@@ -3313,9 +3390,10 @@ export type CapabilityCatalogItem = {
|
|
|
3313
3390
|
enabledReason: string | null;
|
|
3314
3391
|
/** The connection backing this enabled installation, or null when none is involved. */
|
|
3315
3392
|
connectionRef: {
|
|
3316
|
-
connectionId
|
|
3393
|
+
connectionId?: string | undefined;
|
|
3317
3394
|
providerDomain: string;
|
|
3318
3395
|
kind: string;
|
|
3396
|
+
subjectScope?: "subject" | "workspace" | undefined;
|
|
3319
3397
|
} | null;
|
|
3320
3398
|
metadata: Record<string, unknown>;
|
|
3321
3399
|
createdAt?: string | undefined;
|