@opengeni/sdk 0.27.0 → 0.29.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.
- package/README.md +44 -5
- package/dist/index.d.ts +44 -14
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +5 -0
- package/src/mcp-output.ts +161 -0
- package/src/types.ts +84 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
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/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";
|
|
@@ -235,8 +237,10 @@ export type {
|
|
|
235
237
|
FileResourceRef,
|
|
236
238
|
FileStatus,
|
|
237
239
|
FileUploadData,
|
|
240
|
+
FirstPartyMcpToolName,
|
|
238
241
|
GetPackResponse,
|
|
239
242
|
GitHubAppInfo,
|
|
243
|
+
GitHubAppSetupMode,
|
|
240
244
|
GitHubBindingStatus,
|
|
241
245
|
GitHubInstallationBinding,
|
|
242
246
|
GitHubInstallationLifecycle,
|
|
@@ -322,6 +326,7 @@ export type {
|
|
|
322
326
|
SessionCommandReceipt,
|
|
323
327
|
SteerSessionQueueItemRequest,
|
|
324
328
|
WorkspaceInferenceControlResponse,
|
|
329
|
+
SessionPendingInputPreview,
|
|
325
330
|
SessionSystemUpdate,
|
|
326
331
|
SessionSystemUpdateKind,
|
|
327
332
|
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
|
@@ -272,7 +272,7 @@ export type ToolRef = {
|
|
|
272
272
|
};
|
|
273
273
|
|
|
274
274
|
export type SessionToolPolicy = {
|
|
275
|
-
mode: "workspace_default" | "explicit" | "inherited"
|
|
275
|
+
mode: "workspace_default" | "explicit" | "inherited";
|
|
276
276
|
inheritedFromSessionId: string | null;
|
|
277
277
|
};
|
|
278
278
|
|
|
@@ -282,9 +282,9 @@ export type UpdateSessionToolPolicyRequest =
|
|
|
282
282
|
expectedVersion: number;
|
|
283
283
|
}
|
|
284
284
|
| {
|
|
285
|
-
|
|
286
|
-
mode?: "explicit" | undefined;
|
|
285
|
+
mode: "explicit";
|
|
287
286
|
tools: ToolRef[];
|
|
287
|
+
firstPartyMcpTools: FirstPartyMcpToolName[];
|
|
288
288
|
expectedVersion: number;
|
|
289
289
|
};
|
|
290
290
|
|
|
@@ -496,8 +496,8 @@ export type Session = {
|
|
|
496
496
|
resources: ResourceRef[];
|
|
497
497
|
skills: SessionSkill[];
|
|
498
498
|
tools: ToolRef[];
|
|
499
|
-
toolPolicy
|
|
500
|
-
toolPolicyVersion
|
|
499
|
+
toolPolicy: SessionToolPolicy;
|
|
500
|
+
toolPolicyVersion: number;
|
|
501
501
|
effectiveToolPolicy?: SessionEffectiveToolPolicy | undefined;
|
|
502
502
|
metadata: Record<string, unknown>;
|
|
503
503
|
/** Frozen creator fact; later turns carry their own independent initiator. */
|
|
@@ -517,6 +517,7 @@ export type Session = {
|
|
|
517
517
|
rigId: string | null;
|
|
518
518
|
rigVersionId: string | null;
|
|
519
519
|
firstPartyMcpPermissions: string[] | null;
|
|
520
|
+
firstPartyMcpTools: FirstPartyMcpToolName[];
|
|
520
521
|
mcpServers: SessionMcpServerMetadata[];
|
|
521
522
|
parentSessionId: string | null;
|
|
522
523
|
/** Immutable server-authored nested-agent lineage and policy snapshot. */
|
|
@@ -758,6 +759,9 @@ export const SESSION_EVENT_TYPES = [
|
|
|
758
759
|
"goal.continuation",
|
|
759
760
|
"system.update.pending",
|
|
760
761
|
"system.update.delivered",
|
|
762
|
+
"system.update.superseded",
|
|
763
|
+
"system.update.cancelled",
|
|
764
|
+
"system.update.settled",
|
|
761
765
|
"session.control.paused",
|
|
762
766
|
"session.control.resumed",
|
|
763
767
|
"session.control.steer_requested",
|
|
@@ -1594,6 +1598,7 @@ export type CreateSessionRequest = {
|
|
|
1594
1598
|
expectedNewSessionDraftRevision?: number | undefined;
|
|
1595
1599
|
maxNestedAgentDepth?: number | undefined;
|
|
1596
1600
|
firstPartyMcpPermissions?: string[] | undefined;
|
|
1601
|
+
firstPartyMcpTools?: FirstPartyMcpToolName[] | undefined;
|
|
1597
1602
|
mcpServers?: SessionMcpServerInput[] | undefined;
|
|
1598
1603
|
// Shared-sandbox placement (mirror of `@opengeni/contracts` CreateSessionRequest.sandbox,
|
|
1599
1604
|
// addendum 05 §D.1). Three-way union; OMITTED ⇒ the context-dependent server default
|
|
@@ -1659,6 +1664,58 @@ export type KnownPermission = (typeof KNOWN_PERMISSIONS)[number];
|
|
|
1659
1664
|
*/
|
|
1660
1665
|
export type Permission = KnownPermission | (string & {});
|
|
1661
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
|
+
|
|
1662
1719
|
export type ProductAccessMode = "local" | "configured" | "managed";
|
|
1663
1720
|
|
|
1664
1721
|
export type ModelCapabilitySupportV1 = "supported" | "unsupported" | "unknown";
|
|
@@ -2332,9 +2389,6 @@ export type ComposerDraft = {
|
|
|
2332
2389
|
revision: number;
|
|
2333
2390
|
text: string;
|
|
2334
2391
|
resources: ResourceRef[];
|
|
2335
|
-
tools: ToolRef[];
|
|
2336
|
-
/** False inherits the session policy; true preserves an explicit array. */
|
|
2337
|
-
toolsProvided: boolean;
|
|
2338
2392
|
model: string;
|
|
2339
2393
|
reasoningEffort: ReasoningEffort;
|
|
2340
2394
|
sourceTurnId: string | null;
|
|
@@ -2350,6 +2404,7 @@ export type NewSessionDraftOptions = {
|
|
|
2350
2404
|
rigId?: string | undefined;
|
|
2351
2405
|
goal?: GoalSpec | undefined;
|
|
2352
2406
|
firstPartyMcpPermissions?: Permission[] | undefined;
|
|
2407
|
+
firstPartyMcpTools?: FirstPartyMcpToolName[] | undefined;
|
|
2353
2408
|
};
|
|
2354
2409
|
|
|
2355
2410
|
export type NewSessionDraft = {
|
|
@@ -2371,8 +2426,20 @@ export type SessionQueueSnapshot = {
|
|
|
2371
2426
|
/** The latest interrupted attempt has not yet durably proved physical quiescence. */
|
|
2372
2427
|
stoppingPreviousAttempt: boolean;
|
|
2373
2428
|
items: SessionTurn[];
|
|
2429
|
+
/** Canonical pending machine inputs. Events only invalidate this snapshot. */
|
|
2430
|
+
pendingInputs: SessionPendingInputPreview[];
|
|
2431
|
+
/** Exact next bounded input batch that will join an already-waiting prompt. */
|
|
2432
|
+
pendingInputAttachment: {
|
|
2433
|
+
turnId: string;
|
|
2434
|
+
inputIds: string[];
|
|
2435
|
+
} | null;
|
|
2374
2436
|
};
|
|
2375
2437
|
|
|
2438
|
+
export type SessionPendingInputPreview = Pick<
|
|
2439
|
+
SessionSystemUpdate,
|
|
2440
|
+
"id" | "sessionId" | "kind" | "classification" | "sourceId" | "summary" | "createdAt"
|
|
2441
|
+
>;
|
|
2442
|
+
|
|
2376
2443
|
export type SystemUpdateClassification = "success" | "failure" | "action_required" | "info";
|
|
2377
2444
|
|
|
2378
2445
|
export type SessionSystemUpdateKind =
|
|
@@ -2384,7 +2451,6 @@ export type SessionSystemUpdateKind =
|
|
|
2384
2451
|
|
|
2385
2452
|
export type SessionSystemUpdateState =
|
|
2386
2453
|
| "pending"
|
|
2387
|
-
| "deferred"
|
|
2388
2454
|
| "delivered"
|
|
2389
2455
|
| "cancelled"
|
|
2390
2456
|
| "superseded"
|
|
@@ -2402,6 +2468,7 @@ export type SessionSystemUpdate = {
|
|
|
2402
2468
|
lineage: Record<string, unknown>;
|
|
2403
2469
|
state: SessionSystemUpdateState;
|
|
2404
2470
|
deliveredTurnId: string | null;
|
|
2471
|
+
deliveredHistoryItemId: string | null;
|
|
2405
2472
|
deliveredAt: string | null;
|
|
2406
2473
|
createdAt: string;
|
|
2407
2474
|
};
|
|
@@ -3409,6 +3476,8 @@ export type GitHubRepositoryScope = "all" | "selected";
|
|
|
3409
3476
|
|
|
3410
3477
|
export type GitHubBindingStatus = "disabled" | "unbound" | "bound";
|
|
3411
3478
|
|
|
3479
|
+
export type GitHubAppSetupMode = "platform" | "operator";
|
|
3480
|
+
|
|
3412
3481
|
export type GitHubInstallationLifecycle = "active" | "suspended" | "deleted" | "unverified";
|
|
3413
3482
|
|
|
3414
3483
|
export type GitHubInstallationBinding = {
|
|
@@ -3419,6 +3488,8 @@ export type GitHubInstallationBinding = {
|
|
|
3419
3488
|
lifecycle: GitHubInstallationLifecycle;
|
|
3420
3489
|
repositoryScope: GitHubRepositoryScope;
|
|
3421
3490
|
repositoryCount: number;
|
|
3491
|
+
/** OpenGeni-owned entry point for changing the installation's repository allowlist. */
|
|
3492
|
+
configureUrl: string | null;
|
|
3422
3493
|
createdAt: string;
|
|
3423
3494
|
updatedAt: string;
|
|
3424
3495
|
};
|
|
@@ -3427,12 +3498,14 @@ export type GitHubAppInfo = {
|
|
|
3427
3498
|
configured: boolean;
|
|
3428
3499
|
/** Truthful workspace binding state; server App credentials alone are not a binding. */
|
|
3429
3500
|
status: GitHubBindingStatus;
|
|
3501
|
+
/** Platform deployments expose installation only; operator deployments may create an App. */
|
|
3502
|
+
setupMode: GitHubAppSetupMode;
|
|
3430
3503
|
appId: string | null;
|
|
3431
3504
|
clientId: string | null;
|
|
3432
3505
|
appSlug: string | null;
|
|
3433
|
-
/** Fresh
|
|
3506
|
+
/** Fresh OAuth-first existing-installation discovery and install entry point. */
|
|
3434
3507
|
installUrl: string | null;
|
|
3435
|
-
/** Compatibility alias for installUrl
|
|
3508
|
+
/** Compatibility alias for installUrl. */
|
|
3436
3509
|
linkUrl: string | null;
|
|
3437
3510
|
/** Installation bindings owned independently by this workspace. */
|
|
3438
3511
|
installations: GitHubInstallationBinding[];
|
|
@@ -3547,7 +3620,6 @@ export type UserMessageEventInput = {
|
|
|
3547
3620
|
text: string;
|
|
3548
3621
|
turnInstructions?: string | undefined;
|
|
3549
3622
|
resources?: ResourceRef[] | undefined;
|
|
3550
|
-
tools?: ToolRef[] | undefined;
|
|
3551
3623
|
model?: string | undefined;
|
|
3552
3624
|
reasoningEffort?: ReasoningEffort | undefined;
|
|
3553
3625
|
mcpCredentialUpdates?: SessionMcpCredentialUpdateInput[] | undefined;
|