@opengeni/runtime 2.5.3-canary.0 → 2.5.3-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.
@@ -23,14 +23,17 @@ import {
23
23
  withRunCredentialsClient,
24
24
  withRunCredentialsSession,
25
25
  wrapCapabilityToolsForTurnCancellation
26
- } from "./chunk-VVEGJPDR.js";
26
+ } from "./chunk-46BFUGFL.js";
27
27
  import {
28
28
  MemorySession,
29
29
  connectMcpServers
30
30
  } from "./chunk-FHGLYLBL.js";
31
31
  import {
32
32
  SKILL_MAX_FILES,
33
+ SKILL_READ_MAX_OUTPUT_BYTES,
34
+ SKILL_READ_MAX_PATHS,
33
35
  SkillFileError,
36
+ assertSkillRelativePath,
34
37
  buildPortableSkillArtifact,
35
38
  listSkillPaths,
36
39
  readSkillFiles,
@@ -7323,6 +7326,8 @@ var ALWAYS_VISIBLE_BASE_TOOL_NAMES = /* @__PURE__ */ new Set([
7323
7326
  "apply_patch",
7324
7327
  // The server-backed reader needs neither sandbox setup nor tool search.
7325
7328
  "skill_read",
7329
+ // Repository descriptors route to the live sandbox reader.
7330
+ "repository_skill_read",
7326
7331
  "request_human_input",
7327
7332
  "list_models"
7328
7333
  ]);
@@ -9019,7 +9024,7 @@ Skills are reusable instructions supplied dynamically for the current session. W
9019
9024
 
9020
9025
  Use \`session_events\` for conversation history: its default returns user and completed assistant messages, not execution noise. Cursors only paginate. Request \`results\` for final outcomes, \`tools\` for tool receipts, or \`debug\` for explicit diagnostics; request large tool bodies only when needed. Use the returned continuation cursor rather than rereading whole pages. Audit reads do not acknowledge command completion.
9021
9026
 
9022
- For a yielded command, use \`command_read\` to read available output and status, or \`command_wait\` to wait briefly using the same command interface. Keep the command ID and output cursor. A terminal read suppresses any still-pending completion notification; a running read does not. Earlier tool results and delivered messages never change. Use \`command_input\` only to send input where supported, not to poll output. An unsupported input capability does not imply output is unavailable. Give foreground commands a realistic requested wait; an internal polling slice is not a reason to return a background handle.
9027
+ For a yielded command, use \`command_read\` to read available output and status, or \`command_wait\` to wait briefly using the same command interface. Keep the command ID and output cursor. A terminal read suppresses any still-pending completion notification; a running read does not. Earlier tool results and delivered messages never change. Use \`command_input\` only to send input where supported, not to poll output. An unsupported input capability does not imply output is unavailable. Give foreground commands a realistic requested wait; default to 10 seconds (yield_time_ms: 10000). An internal polling slice is not a reason to return a background handle.
9023
9028
 
9024
9029
  If the user asks to create, inspect, continue, pause, resume, steer, rename, or otherwise manage a session, use the corresponding session tool. Pause affects the selected workstream and its descendants: pausing an ancestor also stops you, so you cannot then Resume yourself. Coordinate disjoint edits through messages instead of ancestor Pause.
9025
9030
 
@@ -11874,6 +11879,7 @@ function configureOpenAI(settings) {
11874
11879
 
11875
11880
  // src/workspace-skills.ts
11876
11881
  import { createHash as createHash4 } from "crypto";
11882
+ import { parseSkillFrontmatter } from "@opengeni/contracts";
11877
11883
  import { SandboxFilesystemNotFoundError } from "modal";
11878
11884
  var SKILL_FILE = "SKILL.md";
11879
11885
  var MAX_DISCOVERED_SKILLS = 256;
@@ -11892,21 +11898,84 @@ var WorkspaceSkillsCapability = class extends Capability {
11892
11898
  }
11893
11899
  type = "workspace-skills";
11894
11900
  discovery;
11895
- async instructions() {
11901
+ bind(session) {
11902
+ if (this._session !== session) delete this.discovery;
11903
+ return super.bind(session);
11904
+ }
11905
+ discover() {
11896
11906
  const session = requireWorkspaceSkillSession(this._session);
11897
- this.discovery ??= discoverWorkspaceSkills(
11907
+ return this.discovery ??= discoverWorkspaceSkills(
11898
11908
  session,
11899
11909
  this.searchPaths,
11900
11910
  this.reservedNames,
11901
11911
  this._runAs,
11902
11912
  this.shadowedNames
11903
11913
  );
11904
- const skills = await this.discovery;
11914
+ }
11915
+ tools() {
11916
+ return [
11917
+ tool({
11918
+ name: "repository_skill_read",
11919
+ description: "Read current repository Skill files from the bound workspace. Use the exact repository: identifier from the Repository skills index. Omit paths for SKILL.md; explicit relative paths read only those files. Set listFiles:true without paths for a bounded file inventory. This reads live files through the sandbox, including Connected Machines.",
11920
+ parameters: external_exports.object({
11921
+ skill: external_exports.string().min(1),
11922
+ paths: external_exports.array(external_exports.string().min(1).max(1024)).min(1).max(SKILL_READ_MAX_PATHS).optional(),
11923
+ listFiles: external_exports.boolean().optional()
11924
+ }),
11925
+ execute: async (request) => {
11926
+ if (request.listFiles && request.paths !== void 0)
11927
+ throw new SkillFileError(
11928
+ "invalid_request",
11929
+ "listFiles:true cannot be combined with paths."
11930
+ );
11931
+ const skill = (await this.discover()).find(
11932
+ (entry) => repositorySkillId(entry) === request.skill
11933
+ );
11934
+ if (!skill)
11935
+ throw new SkillFileError(
11936
+ "missing_file",
11937
+ "Repository Skill is not in this index. Use its exact repository: identifier."
11938
+ );
11939
+ const session = requireWorkspaceSkillSession(this._session);
11940
+ const root = skill.path.slice(0, -SKILL_FILE.length - 1);
11941
+ const result = request.listFiles ? listSkillPaths(
11942
+ await repositorySkillInventory(session, root, this._runAs),
11943
+ MAX_SKILL_ENTRIES
11944
+ ) : readSkillFiles(
11945
+ await repositorySkillFiles(
11946
+ session,
11947
+ root,
11948
+ request.paths ?? [SKILL_FILE],
11949
+ this._runAs
11950
+ ),
11951
+ request.paths
11952
+ );
11953
+ const output = JSON.stringify({
11954
+ skillId: request.skill,
11955
+ source: "repository",
11956
+ root,
11957
+ ...result
11958
+ });
11959
+ if (new TextEncoder().encode(output).byteLength > SKILL_READ_MAX_OUTPUT_BYTES) {
11960
+ throw new SkillFileError(
11961
+ "output_too_large",
11962
+ "Repository Skill response exceeds the read output limit. Request fewer paths."
11963
+ );
11964
+ }
11965
+ return output;
11966
+ }
11967
+ })
11968
+ ];
11969
+ }
11970
+ async instructions() {
11971
+ const skills = await this.discover();
11905
11972
  if (skills.length === 0) return null;
11906
- const available = skills.map((skill) => `- ${skill.name}: ${skill.description} (file: ${skill.path})`).join("\n");
11973
+ const available = skills.map(
11974
+ (skill) => `- ${JSON.stringify({ id: repositorySkillId(skill), name: skill.name, description: skill.description, reader: "repository_skill_read", path: skill.path })}`
11975
+ ).join("\n");
11907
11976
  return `## Repository skills
11908
11977
 
11909
- Repository skills are instructions already present in the live workspace. They do not need to be loaded or copied.
11978
+ Repository skills are instructions already present in the live workspace. Read them with repository_skill_read using the exact repository: id below. The reader returns current live files; ordinary filesystem tools execute referenced scripts and read binary assets. Configured Skills use their separate skill_read index.
11910
11979
 
11911
11980
  ### Available repository skills
11912
11981
  ${available}
@@ -11971,6 +12040,14 @@ async function discoverWorkspaceSkillsUnmeasured(session, searchPaths, reservedN
11971
12040
  const skillMarkdownPath = joinWorkspacePath(entry.path, SKILL_FILE);
11972
12041
  let markdown;
11973
12042
  try {
12043
+ const skillEntries = await session.listDir({
12044
+ path: entry.path,
12045
+ ...runAs ? { runAs } : {}
12046
+ });
12047
+ if (!skillEntries.some(
12048
+ (candidate2) => candidate2.name === SKILL_FILE && candidate2.type === "file"
12049
+ ))
12050
+ continue;
11974
12051
  const content = await session.readFile({
11975
12052
  path: skillMarkdownPath,
11976
12053
  ...runAs ? { runAs } : {}
@@ -11988,7 +12065,7 @@ async function discoverWorkspaceSkillsUnmeasured(session, searchPaths, reservedN
11988
12065
  const key = name.toLowerCase();
11989
12066
  if (shadowedNames.has(key)) continue;
11990
12067
  const description = frontmatter.description?.trim() || "No description provided.";
11991
- if (description.length > 2048 || /[\r\n]/.test(description)) {
12068
+ if (description.length > 2048) {
11992
12069
  throw new Error(`Repository skill "${name}" has an invalid description`);
11993
12070
  }
11994
12071
  if (reservedNames.has(key)) {
@@ -12059,26 +12136,59 @@ async function fingerprintWorkspaceDirectory(session, root, runAs) {
12059
12136
  await visit(root, "");
12060
12137
  return hash.digest("hex");
12061
12138
  }
12062
- function parseSkillFrontmatter(markdown) {
12063
- const lines = markdown.split(/\r?\n/);
12064
- if (lines[0]?.trim() !== "---") return {};
12065
- const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
12066
- if (end === -1) return {};
12067
- const values = {};
12068
- for (const line of lines.slice(1, end)) {
12069
- const separator = line.indexOf(":");
12070
- if (separator === -1) continue;
12071
- const key = line.slice(0, separator).trim();
12072
- if (key !== "name" && key !== "description") continue;
12073
- values[key] = unquote(line.slice(separator + 1).trim());
12074
- }
12075
- return values;
12076
- }
12077
- function unquote(value) {
12078
- if (value.length >= 2 && value[0] === value[value.length - 1] && (value[0] === '"' || value[0] === "'")) {
12079
- return value.slice(1, -1);
12139
+ function repositorySkillId(skill) {
12140
+ return `repository:${skill.path}`;
12141
+ }
12142
+ async function repositorySkillFiles(session, root, paths, runAs) {
12143
+ readSkillFiles(
12144
+ paths.map((path) => ({ path, content: "" })),
12145
+ paths
12146
+ );
12147
+ const files = [];
12148
+ for (const path of paths) {
12149
+ let directory = root;
12150
+ const segments = path.split("/");
12151
+ for (const [index, name] of segments.entries()) {
12152
+ const entries = await session.listDir({ path: directory, ...runAs ? { runAs } : {} });
12153
+ const entry = entries.find((candidate) => candidate.name === name);
12154
+ const expected = index === segments.length - 1 ? "file" : "dir";
12155
+ if (entry?.type !== expected)
12156
+ throw new SkillFileError("missing_file", `Repository Skill file is unavailable: ${path}`);
12157
+ directory = joinWorkspacePath(directory, name);
12158
+ }
12159
+ const content = await session.readFile({ path: directory, ...runAs ? { runAs } : {} });
12160
+ files.push({
12161
+ path,
12162
+ content: typeof content === "string" ? content : new TextDecoder("utf-8", { fatal: true }).decode(content)
12163
+ });
12164
+ readSkillFiles(
12165
+ files,
12166
+ files.map((file2) => file2.path)
12167
+ );
12168
+ }
12169
+ return files;
12170
+ }
12171
+ async function repositorySkillInventory(session, root, runAs) {
12172
+ const files = [];
12173
+ let count = 0;
12174
+ async function visit(relative) {
12175
+ const entries = await session.listDir({
12176
+ path: relative ? joinWorkspacePath(root, relative) : root,
12177
+ ...runAs ? { runAs } : {}
12178
+ });
12179
+ for (const entry of entries) {
12180
+ if (++count > MAX_SKILL_ENTRIES)
12181
+ throw new SkillFileError("output_too_large", "Repository Skill inventory is too large.");
12182
+ assertSkillRelativePath(entry.name);
12183
+ if (entry.name.includes("/"))
12184
+ throw new SkillFileError("invalid_path", "Invalid repository directory entry.");
12185
+ const path = relative ? `${relative}/${entry.name}` : entry.name;
12186
+ if (entry.type === "dir") await visit(path);
12187
+ else if (entry.type === "file") files.push({ path, content: "" });
12188
+ }
12080
12189
  }
12081
- return value;
12190
+ await visit("");
12191
+ return files;
12082
12192
  }
12083
12193
  function joinWorkspacePath(parent, child) {
12084
12194
  return `${parent.replace(/\/+$/, "")}/${child}`;
@@ -12096,7 +12206,7 @@ import { existsSync, readdirSync } from "fs";
12096
12206
  // ../sdk/package.json
12097
12207
  var package_default = {
12098
12208
  name: "@opengeni/sdk",
12099
- version: "5.0.5-canary.0",
12209
+ version: "5.0.5-canary.1",
12100
12210
  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.",
12101
12211
  license: "Apache-2.0",
12102
12212
  repository: {
@@ -12236,7 +12346,7 @@ var package_default = {
12236
12346
  // ../react/package.json
12237
12347
  var package_default2 = {
12238
12348
  name: "@opengeni/react",
12239
- version: "5.0.5-canary.0",
12349
+ version: "5.0.5-canary.1",
12240
12350
  description: "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views \u2014 token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
12241
12351
  license: "Apache-2.0",
12242
12352
  repository: {
@@ -12380,6 +12490,7 @@ var package_default2 = {
12380
12490
  "react-resizable-panels": "^4.11.2",
12381
12491
  "remark-gfm": "^4.0.1",
12382
12492
  "tailwind-merge": "^3.5.0",
12493
+ "thinking-orbs": "^0.3.1",
12383
12494
  virtua: "^0.49.2"
12384
12495
  },
12385
12496
  devDependencies: {
@@ -12488,7 +12599,7 @@ var package_default2 = {
12488
12599
  // ../codemode/package.json
12489
12600
  var package_default3 = {
12490
12601
  name: "@opengeni/codemode",
12491
- version: "0.5.6-canary.0",
12602
+ version: "0.5.6-canary.1",
12492
12603
  description: "Attempt-frozen programmatic tool catalog and execution authority for OpenGeni.",
12493
12604
  license: "Apache-2.0",
12494
12605
  repository: {
@@ -12537,7 +12648,7 @@ var package_default3 = {
12537
12648
  // ../ogtool/package.json
12538
12649
  var package_default4 = {
12539
12650
  name: "@opengeni/ogtool",
12540
- version: "0.3.38-canary.0",
12651
+ version: "0.3.38-canary.1",
12541
12652
  description: "Codemode CLI and typed client entrypoint for an OpenGeni execution attempt.",
12542
12653
  license: "Apache-2.0",
12543
12654
  repository: {
@@ -12616,7 +12727,7 @@ var emptyNativeToolSkillSet = Object.freeze({
12616
12727
  videoGeneration: false
12617
12728
  });
12618
12729
  function loadNativeToolSkillArtifacts(nativeTools) {
12619
- const directories = [];
12730
+ const directories = ["bundled_default_skills"];
12620
12731
  if (nativeTools.projects) directories.push("bundled_project_skills");
12621
12732
  if (nativeTools.editableArtifacts) directories.push("bundled_artifact_skills");
12622
12733
  if (nativeTools.sites) directories.push("bundled_site_skills");
@@ -12833,7 +12944,12 @@ function selectionForActivation({
12833
12944
  }
12834
12945
  }
12835
12946
  function nativeToolSkillSources(nativeTools) {
12836
- const sources = [];
12947
+ const sources = [
12948
+ {
12949
+ names: skillDirNames(packagedSkillDirectory("bundled_default_skills")),
12950
+ reason: "included by default"
12951
+ }
12952
+ ];
12837
12953
  if (nativeTools.editableArtifacts) {
12838
12954
  sources.push({
12839
12955
  names: skillDirNames(packagedSkillDirectory("bundled_artifact_skills")),
@@ -23377,4 +23493,4 @@ export {
23377
23493
  runAzureCliLoginHook,
23378
23494
  renderSessionGoalContext2 as renderSessionGoalContext
23379
23495
  };
23380
- //# sourceMappingURL=chunk-SD6MDONS.js.map
23496
+ //# sourceMappingURL=chunk-VUEWS4GI.js.map