@opengeni/runtime 0.7.0 → 0.11.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 (49) hide show
  1. package/THIRD_PARTY_NOTICES +32 -0
  2. package/dist/agent-UMUIWWD2.js +8 -0
  3. package/dist/agent-UMUIWWD2.js.map +1 -0
  4. package/dist/chunk-4YJ5Z52Z.js +1789 -0
  5. package/dist/chunk-4YJ5Z52Z.js.map +1 -0
  6. package/dist/chunk-DPULLAJG.js +215 -0
  7. package/dist/chunk-DPULLAJG.js.map +1 -0
  8. package/dist/chunk-K4V4QYCL.js +37683 -0
  9. package/dist/chunk-K4V4QYCL.js.map +1 -0
  10. package/dist/chunk-PZ5AY32C.js +10 -0
  11. package/dist/chunk-PZ5AY32C.js.map +1 -0
  12. package/dist/chunk-YUAFQEFY.js +21522 -0
  13. package/dist/chunk-YUAFQEFY.js.map +1 -0
  14. package/dist/{index-DIiiwQY2.d.ts → index-D6yi-JcU.d.ts} +138 -15
  15. package/dist/index.d.ts +333 -122
  16. package/dist/index.js +8260 -349
  17. package/dist/index.js.map +1 -1
  18. package/dist/localSources-T3HZ6KY4.js +15 -0
  19. package/dist/localSources-T3HZ6KY4.js.map +1 -0
  20. package/dist/sandbox/index.d.ts +1 -1
  21. package/dist/sandbox/index.js +42 -5
  22. package/dist/skill-library.d.ts +74 -0
  23. package/dist/skill-library.js +18 -0
  24. package/dist/skill-library.js.map +1 -0
  25. package/package.json +13 -5
  26. package/src/bundled_hashicorp_terraform_skills/README.md +3 -3
  27. package/src/bundled_hashicorp_terraform_skills/checkov/SKILL.md +1 -1
  28. package/src/context-compaction.ts +421 -24
  29. package/src/history-sanitizer.ts +14 -5
  30. package/src/index.ts +1451 -304
  31. package/src/sandbox/channel-a.ts +535 -97
  32. package/src/sandbox/index.ts +36 -2
  33. package/src/sandbox/routing/routing-session.ts +10 -2
  34. package/src/sandbox/run-credentials.ts +818 -0
  35. package/src/sandbox/select.ts +3 -3
  36. package/src/sandbox/selfhosted/capabilities.ts +1 -1
  37. package/src/sandbox/selfhosted/op-stream.ts +40 -0
  38. package/src/sandbox/selfhosted/op-testing.ts +50 -3
  39. package/src/sandbox/selfhosted/session.ts +17 -4
  40. package/src/sandbox/selfhosted/testing.ts +1 -1
  41. package/src/sandbox/stream-port.ts +1 -1
  42. package/src/sandbox/stream-token.ts +1 -1
  43. package/src/sandbox/terminal-server.ts +6 -2
  44. package/src/sandbox/toolspace-token.ts +147 -0
  45. package/src/sandbox/turn-tool-cancellation.ts +940 -0
  46. package/src/skill-library.ts +323 -0
  47. package/dist/chunk-RYDCVTMW.js +0 -5531
  48. package/dist/chunk-RYDCVTMW.js.map +0 -1
  49. /package/src/{bundled_hashicorp_terraform_skills → bundled_skill_library}/azure-verified-modules/SKILL.md +0 -0
@@ -0,0 +1,323 @@
1
+ import { createHash } from "node:crypto";
2
+ import { lstatSync, readFileSync, readdirSync } from "node:fs";
3
+ import { dirname, isAbsolute, join, relative } from "node:path";
4
+ import { TextDecoder } from "node:util";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ /**
8
+ * Metadata for a platform-curated skill. The metadata is deliberately
9
+ * provider-neutral: it describes guidance provenance and compatibility, not
10
+ * credentials, tools, permissions, or a model route.
11
+ *
12
+ * Entries are immutable in the runtime. A new artifact gets a new version and
13
+ * content hash; callers must not mutate the returned records.
14
+ */
15
+ export type SkillLibraryEntry = Readonly<{
16
+ id: string;
17
+ name: string;
18
+ version: string;
19
+ description: string;
20
+ category: string;
21
+ tags: readonly string[];
22
+ /** SHA-256 over the complete canonical artifact manifest, not just SKILL.md. */
23
+ contentSha256: string;
24
+ sourceCommit: string;
25
+ sourceUrl: string;
26
+ provenance: string;
27
+ license: string;
28
+ documentationUrl: string;
29
+ compatibility: Readonly<{
30
+ runtime: string;
31
+ minimumSkillCapabilityVersion: string;
32
+ }>;
33
+ upgrade: Readonly<{
34
+ policy: "immutable-replacement";
35
+ supersedes: string | null;
36
+ }>;
37
+ relativePath: string;
38
+ }>;
39
+
40
+ export type SkillLibraryFile = Readonly<{
41
+ path: string;
42
+ content: string;
43
+ }>;
44
+
45
+ export type SkillLibraryArtifact = Readonly<{
46
+ files: readonly SkillLibraryFile[];
47
+ /** SHA-256 over the complete canonical artifact manifest, not just SKILL.md. */
48
+ contentSha256: string;
49
+ }>;
50
+
51
+ export type SkillLibrarySkill = Readonly<{
52
+ name: string;
53
+ description: string;
54
+ files: readonly SkillLibraryFile[];
55
+ }>;
56
+
57
+ const skillLibraryEntries: readonly SkillLibraryEntry[] = Object.freeze([
58
+ Object.freeze({
59
+ id: "azure-verified-modules",
60
+ name: "azure-verified-modules",
61
+ version: "1.0.0",
62
+ description:
63
+ "Azure Verified Modules (AVM) requirements and best practices for certified Terraform modules.",
64
+ category: "infrastructure",
65
+ tags: Object.freeze(["skill", "infrastructure", "terraform", "azure", "opt-in"]),
66
+ contentSha256: "bbc029412fd4893c35cf2a4df6e052efa5583d57d3c26e35d62869dcf4625699",
67
+ sourceCommit: "de4323afdfbc30d1387f287b55062fa8d82b62e8",
68
+ sourceUrl:
69
+ "https://github.com/hashicorp/agent-skills/tree/de4323afdfbc30d1387f287b55062fa8d82b62e8/terraform/code-generation/skills/azure-verified-modules",
70
+ provenance: "Vendored from hashicorp/agent-skills; reviewed OpenGeni curated entry.",
71
+ license: "MPL-2.0",
72
+ documentationUrl: "https://azure.github.io/Azure-Verified-Modules/",
73
+ compatibility: Object.freeze({
74
+ runtime: "openai-agents-skills",
75
+ minimumSkillCapabilityVersion: "0.13.3",
76
+ }),
77
+ upgrade: Object.freeze({
78
+ policy: "immutable-replacement",
79
+ supersedes: null,
80
+ }),
81
+ relativePath: "azure-verified-modules",
82
+ }),
83
+ ]);
84
+
85
+ const skillLibraryRootCandidates = (): string[] => {
86
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
87
+ return [
88
+ join(moduleDir, "bundled_skill_library"),
89
+ join(moduleDir, "..", "src", "bundled_skill_library"),
90
+ ];
91
+ };
92
+
93
+ function skillLibraryRoot(): string | null {
94
+ return skillLibraryRootCandidates().find((candidate) => isRealDirectory(candidate)) ?? null;
95
+ }
96
+
97
+ function entryDirectory(entry: SkillLibraryEntry): string | null {
98
+ const root = skillLibraryRoot();
99
+ if (!root) return null;
100
+ const directory = join(root, entry.relativePath);
101
+ const withinRoot = relative(root, directory);
102
+ if (
103
+ isAbsolute(withinRoot) ||
104
+ withinRoot === ".." ||
105
+ withinRoot.startsWith("../") ||
106
+ !isRealDirectory(directory)
107
+ ) {
108
+ return null;
109
+ }
110
+ return directory;
111
+ }
112
+
113
+ /** Return only entries whose reviewed artifact is present in this deployment. */
114
+ export function listSkillLibraryEntries(): readonly SkillLibraryEntry[] {
115
+ return skillLibraryEntries.filter((entry) => reviewedArtifactIsAvailable(entry));
116
+ }
117
+
118
+ /** Return whether an id belongs to the immutable library, even if its artifact is unavailable. */
119
+ export function isSkillLibraryEntryId(id: string): boolean {
120
+ return skillLibraryEntries.some((entry) => entry.id === id);
121
+ }
122
+
123
+ /** Resolve an exact immutable library entry by id and version. */
124
+ export function getSkillLibraryEntry(id: string, version?: string): SkillLibraryEntry | null {
125
+ const entry = skillLibraryEntries.find(
126
+ (candidate) => candidate.id === id && (version === undefined || candidate.version === version),
127
+ );
128
+ return entry && reviewedArtifactIsAvailable(entry) ? entry : null;
129
+ }
130
+
131
+ /**
132
+ * Load a selected curated entry into the SDK's in-memory skill shape.
133
+ * Selection is guidance-only: this function has no access to settings,
134
+ * credentials, MCP declarations, or model-provider configuration.
135
+ */
136
+ export function loadSkillLibrarySkill(
137
+ id: string,
138
+ version?: string,
139
+ ): { entry: SkillLibraryEntry; skill: SkillLibrarySkill } {
140
+ const entry = getSkillLibraryEntry(id, version);
141
+ if (!entry) {
142
+ throw new Error(
143
+ version
144
+ ? `Skill library entry is unavailable: ${id}@${version}`
145
+ : `Skill library entry is unavailable: ${id}`,
146
+ );
147
+ }
148
+ const directory = entryDirectory(entry);
149
+ if (!directory) {
150
+ throw new Error(`Skill library entry is unavailable: ${entry.id}@${entry.version}`);
151
+ }
152
+ const artifact = verifySkillLibraryArtifact(directory, entry.contentSha256, entry);
153
+ const files = artifact.files;
154
+ const skillMarkdown = files.find((file) => file.path === "SKILL.md")?.content;
155
+ if (skillMarkdown === undefined) {
156
+ throw new Error(`Skill library entry is missing SKILL.md: ${entry.id}@${entry.version}`);
157
+ }
158
+ return {
159
+ entry,
160
+ skill: Object.freeze({
161
+ name: entry.name,
162
+ description: entry.description,
163
+ files: Object.freeze(files.map((file) => Object.freeze(file))),
164
+ }),
165
+ };
166
+ }
167
+
168
+ /**
169
+ * Read a curated artifact and calculate its canonical whole-artifact digest.
170
+ *
171
+ * The manifest is JSON encoded as sorted `[normalizedRelativePath, base64Bytes]`
172
+ * tuples. Base64 preserves every byte, including bytes that would not survive
173
+ * a lossy UTF-8 string round-trip. Files are decoded only after the digest
174
+ * input has been captured because the SDK skill surface is text-based.
175
+ */
176
+ export function readSkillLibraryArtifact(root: string): SkillLibraryArtifact {
177
+ const files = materializeSkillLibraryFiles(root);
178
+ const contentSha256 = skillLibraryArtifactSha256(files);
179
+ return Object.freeze({
180
+ files: Object.freeze(
181
+ files.map((file) =>
182
+ Object.freeze({
183
+ path: file.path,
184
+ content: decodeSkillLibraryFile(file.bytes, file.path),
185
+ }),
186
+ ),
187
+ ),
188
+ contentSha256,
189
+ });
190
+ }
191
+
192
+ /** Verify a reviewed artifact against its immutable catalog digest. */
193
+ export function verifySkillLibraryArtifact(
194
+ root: string,
195
+ expectedSha256: string,
196
+ entry?: Pick<SkillLibraryEntry, "id" | "version">,
197
+ ): SkillLibraryArtifact {
198
+ const artifact = readSkillLibraryArtifact(root);
199
+ if (artifact.files.every((file) => file.path !== "SKILL.md")) {
200
+ throw new Error(
201
+ entry
202
+ ? `Skill library entry is missing SKILL.md: ${entry.id}@${entry.version}`
203
+ : "Skill library artifact is missing SKILL.md",
204
+ );
205
+ }
206
+ if (artifact.contentSha256 !== expectedSha256) {
207
+ const label = entry ? ` for ${entry.id}@${entry.version}` : "";
208
+ throw new Error(
209
+ `Skill library artifact hash mismatch${label}: expected ${expectedSha256}, got ${artifact.contentSha256}`,
210
+ );
211
+ }
212
+ return artifact;
213
+ }
214
+
215
+ type MaterializedSkillLibraryFile = Readonly<{
216
+ path: string;
217
+ bytes: Uint8Array;
218
+ }>;
219
+
220
+ const utf8Decoder = new TextDecoder("utf-8", { fatal: true });
221
+
222
+ function materializeSkillLibraryFiles(root: string, current = ""): MaterializedSkillLibraryFile[] {
223
+ const directory = current ? join(root, current) : root;
224
+ if (!isRealDirectory(directory)) {
225
+ throw new Error(`Skill library artifact root is not a real directory: ${directory}`);
226
+ }
227
+ return readdirSync(directory, { withFileTypes: true })
228
+ .sort((a, b) => compareCanonicalPath(a.name, b.name))
229
+ .flatMap((child) => {
230
+ const childName = normalizeSkillLibraryRelativePath(child.name, true);
231
+ const path = current ? `${current}/${childName}` : childName;
232
+ normalizeSkillLibraryRelativePath(path);
233
+ const childPath = join(root, path);
234
+ if (child.isSymbolicLink()) {
235
+ throw new Error(`Skill library artifact contains a symbolic link: ${path}`);
236
+ }
237
+ if (child.isDirectory()) {
238
+ return materializeSkillLibraryFiles(root, path);
239
+ }
240
+ if (!child.isFile() || !isRealFile(childPath)) {
241
+ throw new Error(`Skill library artifact contains a non-regular file: ${path}`);
242
+ }
243
+ return [{ path, bytes: Uint8Array.from(readFileSync(childPath)) }];
244
+ });
245
+ }
246
+
247
+ function reviewedArtifactIsAvailable(entry: SkillLibraryEntry): boolean {
248
+ const directory = entryDirectory(entry);
249
+ if (!directory) return false;
250
+ try {
251
+ verifySkillLibraryArtifact(directory, entry.contentSha256, entry);
252
+ return true;
253
+ } catch {
254
+ return false;
255
+ }
256
+ }
257
+
258
+ function skillLibraryArtifactSha256(files: readonly MaterializedSkillLibraryFile[]): string {
259
+ const manifest = files
260
+ .map((file) => {
261
+ const path = normalizeSkillLibraryRelativePath(file.path);
262
+ return [path, Buffer.from(file.bytes).toString("base64")] as const;
263
+ })
264
+ .sort((left, right) => compareCanonicalPath(left[0], right[0]));
265
+ const paths = new Set<string>();
266
+ for (const [path] of manifest) {
267
+ if (paths.has(path)) {
268
+ throw new Error(`Skill library artifact contains duplicate file path: ${path}`);
269
+ }
270
+ paths.add(path);
271
+ }
272
+ return createHash("sha256").update(JSON.stringify(manifest), "utf8").digest("hex");
273
+ }
274
+
275
+ function decodeSkillLibraryFile(bytes: Uint8Array, path: string): string {
276
+ try {
277
+ return utf8Decoder.decode(bytes);
278
+ } catch {
279
+ throw new Error(`Skill library artifact contains invalid UTF-8: ${path}`);
280
+ }
281
+ }
282
+
283
+ function normalizeSkillLibraryRelativePath(path: string, segment = false): string {
284
+ if (
285
+ path.length === 0 ||
286
+ path.includes("\\") ||
287
+ path.includes("\0") ||
288
+ path.startsWith("/") ||
289
+ /^[A-Za-z]:(?:\/|$)/u.test(path)
290
+ ) {
291
+ throw new Error(`Skill library artifact contains an unsafe path: ${path}`);
292
+ }
293
+ const parts = path.split("/");
294
+ if (parts.some((part) => part.length === 0 || part === "." || part === "..")) {
295
+ throw new Error(`Skill library artifact contains an unsafe path: ${path}`);
296
+ }
297
+ if (segment && parts.length !== 1) {
298
+ throw new Error(`Skill library artifact contains an unsafe path: ${path}`);
299
+ }
300
+ return parts.join("/");
301
+ }
302
+
303
+ function compareCanonicalPath(left: string, right: string): number {
304
+ return left < right ? -1 : left > right ? 1 : 0;
305
+ }
306
+
307
+ function isRealDirectory(path: string): boolean {
308
+ try {
309
+ const stats = lstatSync(path);
310
+ return stats.isDirectory() && !stats.isSymbolicLink();
311
+ } catch {
312
+ return false;
313
+ }
314
+ }
315
+
316
+ function isRealFile(path: string): boolean {
317
+ try {
318
+ const stats = lstatSync(path);
319
+ return stats.isFile() && !stats.isSymbolicLink();
320
+ } catch {
321
+ return false;
322
+ }
323
+ }