@opengeni/contracts 3.0.1 → 3.0.2-canary.1

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.
@@ -0,0 +1,35 @@
1
+ /** Public discovery metadata; listing does not imply runtime compatibility. */
2
+ export { pluginMcpUnavailableReason } from "./mcp-endpoint.js";
3
+ export type PluginDiscoveryItem = {
4
+ id: string;
5
+ name: string;
6
+ displayName: string;
7
+ description: string;
8
+ longDescription: string;
9
+ provider: string;
10
+ category: string | null;
11
+ logoUrl: string | null;
12
+ darkLogoUrl: string | null;
13
+ sourceUrl: string | null;
14
+ author: {
15
+ name?: string;
16
+ } | null;
17
+ version: string | null;
18
+ skills?: {
19
+ name: string;
20
+ sourceUrl: string;
21
+ }[] | null;
22
+ mcpServers?: {
23
+ name: string;
24
+ transport: string;
25
+ requiresConfiguration?: boolean;
26
+ endpoint: string | null;
27
+ }[] | null;
28
+ components: string[] | null;
29
+ installation: string;
30
+ };
31
+ export type PluginDiscoveryPage = {
32
+ items: PluginDiscoveryItem[];
33
+ total: number;
34
+ nextOffset: number | null;
35
+ };
@@ -0,0 +1,7 @@
1
+ import {
2
+ pluginMcpUnavailableReason
3
+ } from "./chunk-WBYTNVIW.js";
4
+ export {
5
+ pluginMcpUnavailableReason
6
+ };
7
+ //# sourceMappingURL=plugin-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -50,13 +50,31 @@ export type WorkspaceArchiveObjectRef = {
50
50
  bytes: number;
51
51
  backend: string;
52
52
  };
53
+ export type WorkspaceArchiveObjectKey = {
54
+ accountId: string;
55
+ workspaceId: string;
56
+ sandboxGroupId: string;
57
+ revision: string;
58
+ uploadId: string | null;
59
+ };
60
+ export declare function parseWorkspaceArchiveObjectKey(value: unknown): WorkspaceArchiveObjectKey | null;
53
61
  export declare function parseWorkspaceArchiveObjectRef(value: unknown): WorkspaceArchiveObjectRef | null;
54
62
  export declare function workspaceArchiveObjectKey(input: {
55
63
  accountId: string;
56
64
  workspaceId: string;
57
65
  sandboxGroupId: string;
58
66
  revision: string;
67
+ /** New upload invocations supply a fresh randomUUID; omission is legacy-only. */
68
+ uploadId?: string;
59
69
  }): string;
70
+ /** Bind a stored locator to its publication/restore scope and verified tar
71
+ * descriptor. A logical revision never substitutes for the exact physical key. */
72
+ export declare function validateWorkspaceArchiveObjectRef(value: unknown, input: {
73
+ accountId: string;
74
+ workspaceId: string;
75
+ sandboxGroupId: string;
76
+ descriptor: WorkspaceArchiveDescriptor;
77
+ }): WorkspaceArchiveObjectRef | null;
60
78
  export declare function workspaceArchivePayloadPresent(sessionState: Record<string, unknown> | null | undefined): boolean;
61
79
  /** Restore may inline object bytes in memory for hydrate. That copy must never
62
80
  * be published onto a lease when a durable object-storage ref exists. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/contracts",
3
- "version": "3.0.1",
3
+ "version": "3.0.2-canary.1",
4
4
  "description": "Shared zod schemas and wire-contract types for the OpenGeni API.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -18,6 +18,10 @@
18
18
  "module": "./dist/index.js",
19
19
  "types": "./dist/index.d.ts",
20
20
  "exports": {
21
+ "./plugin-discovery": {
22
+ "types": "./dist/plugin-discovery.d.ts",
23
+ "import": "./dist/plugin-discovery.js"
24
+ },
21
25
  "./host-mcp-bindings": {
22
26
  "types": "./dist/host-mcp-bindings.d.ts",
23
27
  "import": "./dist/host-mcp-bindings.js"
package/src/index.ts CHANGED
@@ -180,7 +180,9 @@ export {
180
180
  encodeNativeSnapshotRef,
181
181
  omitInlineWorkspaceArchiveWhenObjectRefPresent,
182
182
  parseWorkspaceArchiveDescriptor,
183
+ parseWorkspaceArchiveObjectKey,
183
184
  parseWorkspaceArchiveObjectRef,
185
+ validateWorkspaceArchiveObjectRef,
184
186
  workspaceArchiveObjectKey,
185
187
  workspaceArchivePayloadPresent,
186
188
  type NativeSnapshotDescriptor,
@@ -189,6 +191,7 @@ export {
189
191
  type TarWorkspaceArchiveDescriptor,
190
192
  type WorkspaceArchiveDescriptor,
191
193
  type WorkspaceArchiveObjectRef,
194
+ type WorkspaceArchiveObjectKey,
192
195
  type WorkspaceTreeFingerprint,
193
196
  } from "./sandbox-snapshots";
194
197
 
@@ -11411,6 +11414,7 @@ export const SkillImportFileSummary = z.object({
11411
11414
  export type SkillImportFileSummary = z.infer<typeof SkillImportFileSummary>;
11412
11415
 
11413
11416
  export const SkillImportPreview = z.object({
11417
+ markdown: z.string().max(262144).optional(),
11414
11418
  source: SkillImportSource,
11415
11419
  sourceUrl: z.string().url(),
11416
11420
  repositoryUrl: z.string().url(),
@@ -12144,6 +12148,7 @@ export const PluginInstallationSummary = z
12144
12148
  description: z.string().max(4000),
12145
12149
  category: z.string().min(1).max(100),
12146
12150
  tags: z.array(z.string().min(1).max(100)).max(64),
12151
+ logoUrl: z.string().url().max(2048).nullable().optional(),
12147
12152
  sourceUrl: z.string().url().max(2048).nullable(),
12148
12153
  manifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
12149
12154
  installationVersion: z.number().int().positive(),
@@ -12319,6 +12324,17 @@ export const Session = /* @__PURE__ */ defineSkillContractSchema(() =>
12319
12324
  workspaceId: z.string().uuid(),
12320
12325
  accountId: z.string().uuid(),
12321
12326
  status: SessionStatus,
12327
+ /** Detail-only failure evidence through lastSequence; independent of timeline paging. */
12328
+ failureDiagnostics: z
12329
+ .object({
12330
+ eventId: z.string().uuid(),
12331
+ sequence: z.number().int().nonnegative(),
12332
+ turnId: z.string().uuid().nullable(),
12333
+ occurredAt: z.string(),
12334
+ payload: z.unknown(),
12335
+ })
12336
+ .nullable()
12337
+ .optional(),
12322
12338
  /** Additive list projection. Detail reads may omit it. */
12323
12339
  backgroundCommandActivity: SessionBackgroundCommandActivity.optional(),
12324
12340
  /** Current non-deleted schedules targeting this session, including paused schedules. */
@@ -16156,6 +16172,7 @@ export const MachineRuntimeCapabilities = z.object({
16156
16172
  browserBridge: z.boolean(),
16157
16173
  operationResourcePolicy: z.boolean(),
16158
16174
  operationCpuQuota: z.boolean(),
16175
+ transactionalFsWrite: z.boolean().default(false),
16159
16176
  });
16160
16177
  export type MachineRuntimeCapabilities = z.infer<typeof MachineRuntimeCapabilities>;
16161
16178
 
@@ -17096,3 +17113,7 @@ export * from "./remember";
17096
17113
  export * from "./agent-authored-durable-text";
17097
17114
 
17098
17115
  export * from "./feedback";
17116
+
17117
+ export type { PluginDiscoveryItem, PluginDiscoveryPage } from "./plugin-discovery";
17118
+ export { mcpEndpointIdentity } from "./mcp-endpoint";
17119
+ export { pluginMcpUnavailableReason } from "./mcp-endpoint";
@@ -0,0 +1,30 @@
1
+ /** Exact endpoint identity: normalize URL syntax, preserve paths and query parameters. */
2
+ export function mcpEndpointIdentity(value: string | null | undefined): string | null {
3
+ if (!value) return null;
4
+ try {
5
+ const url = new URL(value);
6
+ if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) return null;
7
+ url.hash = "";
8
+ return url.href;
9
+ } catch {
10
+ return null;
11
+ }
12
+ }
13
+
14
+ export function pluginMcpUnavailableReason(server: {
15
+ endpoint: string | null;
16
+ transport?: string;
17
+ requiresConfiguration?: boolean;
18
+ }): string | null {
19
+ if (server.transport === "stdio" || !server.endpoint) return "Requires a local runtime";
20
+ if (
21
+ server.transport &&
22
+ !["http", "streamable-http", "streamable_http"].includes(server.transport)
23
+ )
24
+ return "Unsupported transport: " + server.transport;
25
+ if (server.requiresConfiguration || server.endpoint.includes("{"))
26
+ return "Requires custom connection configuration";
27
+ const endpoint = mcpEndpointIdentity(server.endpoint);
28
+ if (!endpoint?.startsWith("https://")) return "Requires a valid HTTPS endpoint";
29
+ return null;
30
+ }
@@ -0,0 +1,33 @@
1
+ /** Public discovery metadata; listing does not imply runtime compatibility. */
2
+ export { pluginMcpUnavailableReason } from "./mcp-endpoint";
3
+
4
+ export type PluginDiscoveryItem = {
5
+ id: string;
6
+ name: string;
7
+ displayName: string;
8
+ description: string;
9
+ longDescription: string;
10
+ provider: string;
11
+ category: string | null;
12
+ logoUrl: string | null;
13
+ darkLogoUrl: string | null;
14
+ sourceUrl: string | null;
15
+ author: { name?: string } | null;
16
+ version: string | null;
17
+ skills?: { name: string; sourceUrl: string }[] | null;
18
+ mcpServers?:
19
+ | {
20
+ name: string;
21
+ transport: string;
22
+ requiresConfiguration?: boolean;
23
+ endpoint: string | null;
24
+ }[]
25
+ | null;
26
+ components: string[] | null;
27
+ installation: string;
28
+ };
29
+ export type PluginDiscoveryPage = {
30
+ items: PluginDiscoveryItem[];
31
+ total: number;
32
+ nextOffset: number | null;
33
+ };
@@ -64,8 +64,35 @@ export type WorkspaceArchiveObjectRef = {
64
64
  backend: string;
65
65
  };
66
66
 
67
+ // Keep legacy scope/key spelling readable. New physical upload identities must
68
+ // be a complete RFC UUID (including version and variant), never arbitrary text.
69
+ const UPLOAD_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
67
70
  const OBJECT_KEY =
68
- /^sandbox-archives\/v1\/[0-9a-f-]{36}\/[0-9a-f-]{36}\/[0-9a-f-]{36}\/wa1:[0-9]{13}:[0-9a-f]{64}\.tar$/i;
71
+ /^sandbox-archives\/v1\/([0-9a-f-]{36})\/([0-9a-f-]{36})\/([0-9a-f-]{36})\/(wa1:[0-9]{13}:[0-9a-f]{64})(?:\.([0-9a-f-]+))?\.tar$/i;
72
+
73
+ export type WorkspaceArchiveObjectKey = {
74
+ accountId: string;
75
+ workspaceId: string;
76
+ sandboxGroupId: string;
77
+ revision: string;
78
+ uploadId: string | null;
79
+ };
80
+
81
+ export function parseWorkspaceArchiveObjectKey(value: unknown): WorkspaceArchiveObjectKey | null {
82
+ if (typeof value !== "string") return null;
83
+ const match = OBJECT_KEY.exec(value);
84
+ // JS $ may match before a final newline; a locator must match in full.
85
+ if (!match || match[0] !== value || (match[5] !== undefined && !UPLOAD_ID.test(match[5]))) {
86
+ return null;
87
+ }
88
+ return {
89
+ accountId: match[1]!,
90
+ workspaceId: match[2]!,
91
+ sandboxGroupId: match[3]!,
92
+ revision: match[4]!,
93
+ uploadId: match[5] ?? null,
94
+ };
95
+ }
69
96
 
70
97
  export function parseWorkspaceArchiveObjectRef(value: unknown): WorkspaceArchiveObjectRef | null {
71
98
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -73,7 +100,7 @@ export function parseWorkspaceArchiveObjectRef(value: unknown): WorkspaceArchive
73
100
  if (
74
101
  candidate.schema !== WORKSPACE_ARCHIVE_OBJECT_REF_SCHEMA ||
75
102
  typeof candidate.key !== "string" ||
76
- !OBJECT_KEY.test(candidate.key) ||
103
+ !parseWorkspaceArchiveObjectKey(candidate.key) ||
77
104
  typeof candidate.sha256 !== "string" ||
78
105
  !SHA256.test(candidate.sha256) ||
79
106
  !nonnegativeInteger(candidate.bytes) ||
@@ -98,8 +125,45 @@ export function workspaceArchiveObjectKey(input: {
98
125
  workspaceId: string;
99
126
  sandboxGroupId: string;
100
127
  revision: string;
128
+ /** New upload invocations supply a fresh randomUUID; omission is legacy-only. */
129
+ uploadId?: string;
101
130
  }): string {
102
- return `sandbox-archives/v1/${input.accountId}/${input.workspaceId}/${input.sandboxGroupId}/${input.revision}.tar`;
131
+ if (
132
+ input.uploadId !== undefined &&
133
+ (!UPLOAD_ID.test(input.uploadId) || input.uploadId.length !== 36)
134
+ ) {
135
+ throw new Error("Invalid workspace archive upload UUID");
136
+ }
137
+ return `sandbox-archives/v1/${input.accountId}/${input.workspaceId}/${input.sandboxGroupId}/${input.revision}${input.uploadId === undefined ? "" : `.${input.uploadId}`}.tar`;
138
+ }
139
+
140
+ /** Bind a stored locator to its publication/restore scope and verified tar
141
+ * descriptor. A logical revision never substitutes for the exact physical key. */
142
+ export function validateWorkspaceArchiveObjectRef(
143
+ value: unknown,
144
+ input: {
145
+ accountId: string;
146
+ workspaceId: string;
147
+ sandboxGroupId: string;
148
+ descriptor: WorkspaceArchiveDescriptor;
149
+ },
150
+ ): WorkspaceArchiveObjectRef | null {
151
+ const ref = parseWorkspaceArchiveObjectRef(value);
152
+ const key = ref && parseWorkspaceArchiveObjectKey(ref.key);
153
+ const descriptor = parseWorkspaceArchiveDescriptor(input.descriptor);
154
+ if (
155
+ !ref ||
156
+ !key ||
157
+ descriptor?.version !== 1 ||
158
+ key.accountId.toLowerCase() !== input.accountId.toLowerCase() ||
159
+ key.workspaceId.toLowerCase() !== input.workspaceId.toLowerCase() ||
160
+ key.sandboxGroupId.toLowerCase() !== input.sandboxGroupId.toLowerCase() ||
161
+ key.revision !== descriptor.revision ||
162
+ ref.sha256 !== descriptor.archiveSha256 ||
163
+ ref.bytes !== descriptor.archiveBytes
164
+ )
165
+ return null;
166
+ return ref;
103
167
  }
104
168
 
105
169
  export function workspaceArchivePayloadPresent(
@@ -14,8 +14,12 @@ export function parseSkillFrontmatter(markdown: string): {
14
14
  uniqueKeys: true,
15
15
  prettyErrors: false,
16
16
  });
17
- if (document.errors.length || document.warnings.length)
18
- throw new Error("Skill artifact SKILL.md has invalid YAML frontmatter");
17
+ if (document.errors.length || document.warnings.length) {
18
+ const issue = document.errors[0] ?? document.warnings[0]!;
19
+ throw new Error(
20
+ `This skill's SKILL.md header contains invalid YAML: ${issue.message}. The source file needs correcting.`,
21
+ );
22
+ }
19
23
  const metadata: unknown = document.toJS({ maxAliasCount: 20 });
20
24
  if (!metadata || typeof metadata !== "object" || Array.isArray(metadata))
21
25
  throw new Error("Skill artifact SKILL.md frontmatter must be a mapping");