@opengeni/runtime 2.4.3 → 2.5.2-canary.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/dist/{agent-UA75SUZ7.js → agent-Q2VNH5FV.js} +2 -2
  2. package/dist/{chunk-ORKCCH5X.js → chunk-25B3EQRW.js} +3 -398
  3. package/dist/{chunk-ORKCCH5X.js.map → chunk-25B3EQRW.js.map} +1 -1
  4. package/dist/{chunk-YRKIQK25.js → chunk-CD22I76N.js} +2 -2
  5. package/dist/{chunk-7K6WOXFS.js → chunk-GB763TSV.js} +17 -1
  6. package/dist/chunk-GB763TSV.js.map +1 -0
  7. package/dist/{chunk-BV2DSPZK.js → chunk-GBHOT4KS.js} +267 -181
  8. package/dist/chunk-GBHOT4KS.js.map +1 -0
  9. package/dist/{chunk-WATBACLT.js → chunk-LEIGL6X2.js} +2309 -1428
  10. package/dist/chunk-LEIGL6X2.js.map +1 -0
  11. package/dist/index.d.ts +12 -5
  12. package/dist/index.js +15 -5
  13. package/dist/{localSources-GDQRRHT3.js → localSources-Z5IJIIRV.js} +3 -3
  14. package/dist/model-input.d.ts +2 -1
  15. package/dist/runtime-skills.d.ts +28 -5
  16. package/dist/sandbox/archive-spool.d.ts +14 -0
  17. package/dist/sandbox/host-archive-spool.d.ts +19 -0
  18. package/dist/sandbox/index.d.ts +5 -1
  19. package/dist/sandbox/index.js +7 -3
  20. package/dist/sandbox/workspace-archive.d.ts +7 -0
  21. package/dist/skill-files.d.ts +4 -0
  22. package/dist/skill-library.d.ts +1 -1
  23. package/dist/skill-library.js +3 -1
  24. package/dist/workspace-tool-gateway.js +5 -5
  25. package/package.json +11 -11
  26. package/src/bundled_management_skills/opengeni-skills/SKILL.md +3 -1
  27. package/src/index.ts +184 -33
  28. package/src/lazy-tool-transport.ts +0 -3
  29. package/src/model-input.ts +1 -1
  30. package/src/run-events.ts +23 -0
  31. package/src/runtime-skills.ts +122 -161
  32. package/src/sandbox/archive-spool.ts +16 -0
  33. package/src/sandbox/host-archive-spool.ts +1040 -0
  34. package/src/sandbox/index.ts +292 -203
  35. package/src/sandbox/routing/routing-session.ts +1 -1
  36. package/src/sandbox/workspace-archive.ts +54 -1
  37. package/src/skill-files.ts +20 -0
  38. package/src/skill-library.ts +1 -0
  39. package/dist/chunk-7K6WOXFS.js.map +0 -1
  40. package/dist/chunk-BV2DSPZK.js.map +0 -1
  41. package/dist/chunk-WATBACLT.js.map +0 -1
  42. /package/dist/{agent-UA75SUZ7.js.map → agent-Q2VNH5FV.js.map} +0 -0
  43. /package/dist/{chunk-YRKIQK25.js.map → chunk-CD22I76N.js.map} +0 -0
  44. /package/dist/{localSources-GDQRRHT3.js.map → localSources-Z5IJIIRV.js.map} +0 -0
@@ -1,29 +1,16 @@
1
- import {
2
- cpSync,
3
- existsSync,
4
- mkdirSync,
5
- readdirSync,
6
- readFileSync,
7
- renameSync,
8
- rmSync,
9
- } from "node:fs";
1
+ import { existsSync, readdirSync } from "node:fs";
10
2
  import { sitePackageVersions } from "./site-package-versions";
11
- import { dirname, isAbsolute, join, relative } from "node:path";
3
+ import { dirname, join } from "node:path";
12
4
  import { fileURLToPath } from "node:url";
13
5
  import { readSkillMetadata } from "@opengeni/contracts";
14
6
 
15
- import { localDirLazySkillSource } from "@openai/agents/sandbox/local";
16
7
  import {
17
- dir,
18
- file,
19
- localDir,
20
- type Dir,
21
- type Entry,
22
- type LocalDirLazySkillSource,
23
- type SkillIndexEntry,
24
- } from "@openai/agents/sandbox";
25
-
26
- import { buildPortableSkillArtifact, readSkillLibraryArtifact } from "./skill-library";
8
+ PORTABLE_SKILL_MAX_FILES,
9
+ buildPortableSkillArtifact,
10
+ readSkillLibraryArtifact,
11
+ } from "./skill-library";
12
+ import { SkillFileError, listSkillPaths, readSkillFiles } from "./skill-files";
13
+ import type { SkillCatalogDescriptor } from "./skill-catalog";
27
14
 
28
15
  export type RuntimeSkillArtifactFile = Readonly<{
29
16
  path: string;
@@ -84,13 +71,28 @@ export type EffectiveSkillSelection = Readonly<{
84
71
  reason: string;
85
72
  }>;
86
73
 
74
+ export type RuntimeSkillReadable = Readonly<{
75
+ id: string;
76
+ name: string;
77
+ description: string;
78
+ files: readonly RuntimeSkillArtifactFile[];
79
+ }>;
80
+
87
81
  export type RuntimeSkillComposition = Readonly<{
88
- lazySource: LocalDirLazySkillSource;
89
82
  selections: readonly EffectiveSkillSelection[];
90
83
  /** Exact always-visible catalog descriptors for explicitly activated Skills. */
91
84
  configuredDescriptors: readonly RuntimeSkillDescriptor[];
92
85
  configuredNames: readonly string[];
93
86
  nativeToolNames: readonly string[];
87
+ /** Model-facing catalog descriptors for configured and bundled Skills. */
88
+ index: readonly RuntimeSkillIndexEntry[];
89
+ artifacts: readonly RuntimeSkillReadable[];
90
+ }>;
91
+
92
+ export type RuntimeSkillIndexEntry = Readonly<{
93
+ id: string;
94
+ name: string;
95
+ description: string;
94
96
  }>;
95
97
 
96
98
  export type RuntimeSkillDescriptor = Readonly<{
@@ -101,6 +103,12 @@ export type RuntimeSkillDescriptor = Readonly<{
101
103
  description: string;
102
104
  }>;
103
105
 
106
+ export type RuntimeSkillReadRequest = Readonly<{
107
+ skill: string;
108
+ paths?: readonly string[];
109
+ listFiles?: boolean;
110
+ }>;
111
+
104
112
  type ValidatedRuntimeSkillActivation = Readonly<{
105
113
  activation: RuntimeSkillActivation;
106
114
  contentSha256: string;
@@ -144,16 +152,11 @@ export function loadNativeToolSkillArtifacts(
144
152
  });
145
153
  }
146
154
 
147
- let stagedBundledArtifactSkillsDir: string | null = null;
148
- let stagedBundledVideoSkillsDir: string | null = null;
149
-
150
155
  /**
151
156
  * Compose the exact Skills surface for one agent.
152
- *
153
157
  * Optional/domain Skills enter only through explicit activations. Native
154
158
  * Skills are admitted only with the exact executable tool surface they
155
- * document. This one result owns both lazy materialization and inspection
156
- * provenance so those projections cannot disagree.
159
+ * document. The result is an in-memory catalog and file set, not an SDK loader.
157
160
  */
158
161
  export function composeRuntimeSkills(
159
162
  activations: readonly RuntimeSkillActivation[],
@@ -167,39 +170,52 @@ export function composeRuntimeSkills(
167
170
  activations.map(validateRuntimeSkillActivation),
168
171
  nativeNameKeys,
169
172
  );
170
- const activatedNameKeys = new Set(
171
- effectiveActivations.map(({ activation }) => activation.artifact.name.toLowerCase()),
172
- );
173
- const children: Record<string, Entry> = {};
174
- for (const source of nativeSources) {
175
- for (const name of source.names) {
176
- children[name] = source.entries?.[name] ?? localDir({ src: join(source.directory, name) });
177
- }
178
- }
179
-
180
- const activationIndex: SkillIndexEntry[] = [];
181
- for (const { activation } of effectiveActivations) {
182
- const { artifact } = activation;
183
- children[artifact.name] = runtimeSkillDirEntry(artifact);
184
- activationIndex.push({
173
+ const nativeArtifacts = loadNativeToolSkillArtifacts(nativeTools);
174
+ const nativeReadables: RuntimeSkillReadable[] = nativeArtifacts.map((artifact) =>
175
+ Object.freeze({
176
+ id: `native-tool:${artifact.name}`,
185
177
  name: artifact.name,
186
178
  description: runtimeSkillDescription(artifact),
187
- path: artifact.name,
188
- });
189
- }
179
+ files: artifact.files,
180
+ }),
181
+ );
182
+ const configuredDescriptors = Object.freeze(
183
+ effectiveActivations.map(({ activation }) =>
184
+ Object.freeze({
185
+ id: activation.id,
186
+ name: activation.artifact.name,
187
+ source: activation.source,
188
+ reason: activation.reason,
189
+ description: runtimeSkillDescription(activation.artifact),
190
+ }),
191
+ ),
192
+ );
193
+ const configuredReadables: RuntimeSkillReadable[] = effectiveActivations.map(({ activation }) =>
194
+ Object.freeze({
195
+ id: activation.id,
196
+ name: activation.artifact.name,
197
+ description: runtimeSkillDescription(activation.artifact),
198
+ files: activation.artifact.files,
199
+ }),
200
+ );
201
+ const index = Object.freeze([
202
+ ...nativeReadables.map((artifact) =>
203
+ Object.freeze({
204
+ id: artifact.id,
205
+ name: artifact.name,
206
+ description: artifact.description,
207
+ }),
208
+ ),
209
+ ...configuredDescriptors.map((descriptor) =>
210
+ Object.freeze({
211
+ id: descriptor.id,
212
+ name: descriptor.name,
213
+ description: descriptor.description,
214
+ }),
215
+ ),
216
+ ]);
190
217
 
191
218
  return Object.freeze({
192
- lazySource: {
193
- source: dir({ children }),
194
- getIndex: (manifest, skillsPath) => [
195
- ...nativeSources.flatMap((source) =>
196
- (source.lazySource.getIndex?.(manifest, skillsPath) ?? []).filter(
197
- (entry) => !activatedNameKeys.has((entry.path ?? entry.name).toLowerCase()),
198
- ),
199
- ),
200
- ...activationIndex,
201
- ],
202
- },
203
219
  selections: Object.freeze([
204
220
  ...nativeSources.flatMap((source) =>
205
221
  source.names.map((name) =>
@@ -215,24 +231,58 @@ export function composeRuntimeSkills(
215
231
  ),
216
232
  ...effectiveActivations.map((activation) => selectionForActivation(activation)),
217
233
  ]),
218
- configuredDescriptors: Object.freeze(
219
- effectiveActivations.map(({ activation }) =>
220
- Object.freeze({
221
- id: activation.id,
222
- name: activation.artifact.name,
223
- source: activation.source,
224
- reason: activation.reason,
225
- description: runtimeSkillDescription(activation.artifact),
226
- }),
227
- ),
228
- ),
234
+ configuredDescriptors,
229
235
  configuredNames: Object.freeze(
230
236
  effectiveActivations.map(({ activation }) => activation.artifact.name),
231
237
  ),
232
238
  nativeToolNames: Object.freeze([...nativeSources.flatMap((source) => source.names)]),
239
+ index,
240
+ artifacts: Object.freeze([...nativeReadables, ...configuredReadables]),
233
241
  });
234
242
  }
235
243
 
244
+ export function skillCatalogFromComposition(
245
+ composition: RuntimeSkillComposition,
246
+ ): readonly SkillCatalogDescriptor[] {
247
+ return composition.index;
248
+ }
249
+
250
+ export function readRuntimeSkill(
251
+ composition: RuntimeSkillComposition,
252
+ request: RuntimeSkillReadRequest,
253
+ ): { skillId: string; files?: ReturnType<typeof readSkillFiles>["files"]; paths?: string[] } {
254
+ const skill = request.skill.trim();
255
+ if (!skill)
256
+ throw new SkillFileError("invalid_request", "skill_read requires a Skill identifier.");
257
+ if (request.listFiles === true && request.paths !== undefined) {
258
+ throw new SkillFileError(
259
+ "invalid_request",
260
+ "skill_read listFiles:true cannot be combined with paths.",
261
+ );
262
+ }
263
+ const exact = composition.artifacts.find((artifact) => artifact.id === skill);
264
+ const matches = exact
265
+ ? [exact]
266
+ : composition.artifacts.filter((artifact) => artifact.name === skill);
267
+ if (matches.length === 0) {
268
+ throw new SkillFileError("missing_file", `Skill not found: ${skill}`);
269
+ }
270
+ if (matches.length > 1) {
271
+ throw new SkillFileError(
272
+ "invalid_request",
273
+ `Skill name is ambiguous: ${skill}. Use the catalog id.`,
274
+ );
275
+ }
276
+ const artifact = matches[0]!;
277
+ if (request.listFiles === true) {
278
+ return { skillId: artifact.id, ...listSkillPaths(artifact.files, PORTABLE_SKILL_MAX_FILES) };
279
+ }
280
+ return {
281
+ skillId: artifact.id,
282
+ files: readSkillFiles(artifact.files, request.paths).files,
283
+ };
284
+ }
285
+
236
286
  function resolveEffectiveActivations(
237
287
  activations: readonly ValidatedRuntimeSkillActivation[],
238
288
  nativeNameKeys: ReadonlySet<string>,
@@ -331,47 +381,25 @@ function selectionForActivation({
331
381
  }
332
382
 
333
383
  function nativeToolSkillSources(nativeTools: NativeToolSkillSet): Array<{
334
- directory: string;
335
- entries?: Record<string, Entry>;
336
- lazySource: LocalDirLazySkillSource;
337
384
  names: string[];
338
385
  reason: string;
339
386
  }> {
340
- const sources: Array<{
341
- directory: string;
342
- entries?: Record<string, Entry>;
343
- lazySource: LocalDirLazySkillSource;
344
- names: string[];
345
- reason: string;
346
- }> = [];
387
+ const sources: Array<{ names: string[]; reason: string }> = [];
347
388
  if (nativeTools.editableArtifacts) {
348
- const directory = bundledArtifactSkillsDir();
349
389
  sources.push({
350
- directory,
351
- lazySource: localDirLazySkillSource({ src: directory }),
352
- names: skillDirNames(directory),
390
+ names: skillDirNames(packagedSkillDirectory("bundled_artifact_skills")),
353
391
  reason: "native editable-artifact tool surface",
354
392
  });
355
393
  }
356
394
  if (nativeTools.sites) {
357
- const directory = packagedSkillDirectory("bundled_site_skills");
358
- const site = bundledSkillEntry(join(directory, "opengeni-sites"), {
359
- "package-versions.json": file({ content: JSON.stringify(sitePackageVersions(), null, 2) }),
360
- });
361
395
  sources.push({
362
- directory,
363
- entries: { "opengeni-sites": site },
364
- lazySource: localDirLazySkillSource({ src: directory, baseDir: directory }),
365
- names: skillDirNames(directory),
396
+ names: skillDirNames(packagedSkillDirectory("bundled_site_skills")),
366
397
  reason: "bundled Site authoring skill",
367
398
  });
368
399
  }
369
400
  if (nativeTools.videoGeneration) {
370
- const directory = bundledVideoSkillsDir();
371
401
  sources.push({
372
- directory,
373
- lazySource: localDirLazySkillSource({ src: directory }),
374
- names: skillDirNames(directory),
402
+ names: skillDirNames(packagedSkillDirectory("bundled_video_skills")),
375
403
  reason: "native video-generation tool surface",
376
404
  });
377
405
  }
@@ -389,62 +417,6 @@ function packagedSkillDirectory(directoryName: string): string {
389
417
  );
390
418
  }
391
419
 
392
- function bundledArtifactSkillsDir(): string {
393
- const packaged = packagedSkillDirectory("bundled_artifact_skills");
394
- if (isPathWithin(process.cwd(), packaged)) return packaged;
395
- if (!stagedBundledArtifactSkillsDir) {
396
- stagedBundledArtifactSkillsDir = stageSkillDirectory(
397
- packaged,
398
- join(process.cwd(), ".opengeni", "bundled_artifact_skills"),
399
- );
400
- }
401
- return stagedBundledArtifactSkillsDir;
402
- }
403
-
404
- /** Compose generated metadata in the manifest, never in the installed application. */
405
- function bundledSkillEntry(directory: string, overrides: Record<string, Entry> = {}): Dir {
406
- const children: Record<string, Entry> = {};
407
- for (const entry of readdirSync(directory, { withFileTypes: true })) {
408
- const path = join(directory, entry.name);
409
- children[entry.name] = entry.isDirectory()
410
- ? bundledSkillEntry(path)
411
- : file({ content: readFileSync(path, "utf8") });
412
- }
413
- return dir({ children: { ...children, ...overrides } });
414
- }
415
-
416
- function bundledVideoSkillsDir(): string {
417
- const packaged = packagedSkillDirectory("bundled_video_skills");
418
- if (isPathWithin(process.cwd(), packaged)) return packaged;
419
- if (!stagedBundledVideoSkillsDir) {
420
- stagedBundledVideoSkillsDir = stageSkillDirectory(
421
- packaged,
422
- join(process.cwd(), ".opengeni", "bundled_video_skills"),
423
- );
424
- }
425
- return stagedBundledVideoSkillsDir;
426
- }
427
-
428
- function stageSkillDirectory(packaged: string, target: string): string {
429
- const temporary = `${target}.tmp-${process.pid}`;
430
- rmSync(temporary, { recursive: true, force: true });
431
- mkdirSync(dirname(temporary), { recursive: true });
432
- cpSync(packaged, temporary, { recursive: true });
433
- rmSync(target, { recursive: true, force: true });
434
- try {
435
- renameSync(temporary, target);
436
- } catch (error) {
437
- rmSync(temporary, { recursive: true, force: true });
438
- if (!existsSync(target)) throw error;
439
- }
440
- return target;
441
- }
442
-
443
- function isPathWithin(root: string, candidate: string): boolean {
444
- const relativePath = relative(root, candidate);
445
- return relativePath === "" || (!relativePath.startsWith("..") && !isAbsolute(relativePath));
446
- }
447
-
448
420
  function skillDirNames(root: string): string[] {
449
421
  return readdirSync(root, { withFileTypes: true })
450
422
  .filter((entry) => entry.isDirectory() && existsSync(join(root, entry.name, "SKILL.md")))
@@ -457,10 +429,6 @@ type RuntimeSkillDirNode = {
457
429
  files: Map<string, string>;
458
430
  };
459
431
 
460
- function runtimeSkillDirEntry(skill: RuntimeSkillArtifact): Dir {
461
- return runtimeSkillDirFromNode(runtimeSkillDirNode(skill));
462
- }
463
-
464
432
  function runtimeSkillDirNode(skill: RuntimeSkillArtifact): RuntimeSkillDirNode {
465
433
  const root: RuntimeSkillDirNode = { dirs: new Map(), files: new Map() };
466
434
  for (const skillFile of skill.files) {
@@ -489,13 +457,6 @@ function runtimeSkillDirNode(skill: RuntimeSkillArtifact): RuntimeSkillDirNode {
489
457
  return root;
490
458
  }
491
459
 
492
- function runtimeSkillDirFromNode(node: RuntimeSkillDirNode): Dir {
493
- const children: Record<string, Entry> = {};
494
- for (const [name, child] of node.dirs) children[name] = runtimeSkillDirFromNode(child);
495
- for (const [name, content] of node.files) children[name] = file({ content });
496
- return dir({ children });
497
- }
498
-
499
460
  function assertSafeRuntimeSkillName(name: string): void {
500
461
  if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u.test(name)) {
501
462
  throw new Error(`Invalid Skill name: ${name}`);
@@ -0,0 +1,16 @@
1
+ import type { TarWorkspaceArchiveDescriptor } from "@opengeni/contracts";
2
+
3
+ /** Process-owned, reopenable archive bytes. Never persisted as a local path. */
4
+ export type WorkspaceArchiveSpool = {
5
+ path: string;
6
+ byteSize: number;
7
+ sha256: string;
8
+ open: () => AsyncIterable<Uint8Array>;
9
+ dispose: () => Promise<void>;
10
+ };
11
+
12
+ export type VerifiedHostWorkspaceArchive = {
13
+ kind: "host_spool";
14
+ spool: WorkspaceArchiveSpool;
15
+ descriptor: TarWorkspaceArchiveDescriptor;
16
+ };