@opengeni/runtime 0.13.13 → 0.14.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/dist/index.d.ts +15 -3
- package/dist/index.js +281 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +129 -6
- package/src/workspace-skills.ts +235 -0
package/dist/index.d.ts
CHANGED
|
@@ -371,6 +371,11 @@ declare class ComputerUseCapability extends Capability {
|
|
|
371
371
|
private hostedComputerTool;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
type WorkspaceSkillSearchPath = Readonly<{
|
|
375
|
+
path: string;
|
|
376
|
+
source: string;
|
|
377
|
+
}>;
|
|
378
|
+
|
|
374
379
|
/**
|
|
375
380
|
* Read-path sanitizer for replayed conversation history (issue: orphaned
|
|
376
381
|
* tool outputs brick a session).
|
|
@@ -838,7 +843,7 @@ type ToolspaceTokenWriterSession = SandboxSessionLike;
|
|
|
838
843
|
type EffectiveSkillSelection = Readonly<{
|
|
839
844
|
id: string;
|
|
840
845
|
name: string;
|
|
841
|
-
source: "bundled" | "library" | "pack";
|
|
846
|
+
source: "bundled" | "library" | "pack" | "session";
|
|
842
847
|
version: string | null;
|
|
843
848
|
contentSha256: string | null;
|
|
844
849
|
reason: string;
|
|
@@ -892,6 +897,7 @@ type BuildAgentOptions = {
|
|
|
892
897
|
sessionInstructions?: string;
|
|
893
898
|
turnInstructions?: string;
|
|
894
899
|
packSkills?: PackSkill[];
|
|
900
|
+
sessionSkills?: PackSkill[];
|
|
895
901
|
skillLibrarySkills?: PackSkill[];
|
|
896
902
|
skillLibrarySelections?: EffectiveSkillSelection[];
|
|
897
903
|
/**
|
|
@@ -913,7 +919,7 @@ type PackSkillFile = {
|
|
|
913
919
|
};
|
|
914
920
|
type PackSkill = {
|
|
915
921
|
name: string;
|
|
916
|
-
description?: string | null;
|
|
922
|
+
description?: string | null | undefined;
|
|
917
923
|
files: PackSkillFile[];
|
|
918
924
|
};
|
|
919
925
|
/**
|
|
@@ -1066,6 +1072,8 @@ declare function buildOpenGeniAgent(settings: Settings, resources: ResourceRef[]
|
|
|
1066
1072
|
declare function withStructuredViewImageFunctionResults(tools: Tool<unknown>[]): Tool<unknown>[];
|
|
1067
1073
|
declare function buildAgentCapabilities(settings: Settings, packSkills: PackSkill[], options?: {
|
|
1068
1074
|
skillLibrarySkills?: PackSkill[];
|
|
1075
|
+
sessionSkills?: PackSkill[];
|
|
1076
|
+
workspaceSkillPaths?: readonly WorkspaceSkillSearchPath[];
|
|
1069
1077
|
structuredToolTransport?: boolean;
|
|
1070
1078
|
computerToolMode?: ComputerToolMode;
|
|
1071
1079
|
onComputerUseReady?: (session: SandboxSessionLike) => Promise<void>;
|
|
@@ -1087,6 +1095,7 @@ type PrepareToolsOptions = {
|
|
|
1087
1095
|
executionGeneration?: number;
|
|
1088
1096
|
subjectId?: string;
|
|
1089
1097
|
subjectLabel?: string;
|
|
1098
|
+
credentialSubjectId?: string;
|
|
1090
1099
|
firstPartyPermissions?: Permission[];
|
|
1091
1100
|
resolveCredential?: (input: ResolveConnectionCredentialInput) => Promise<ResolveConnectionCredentialResult>;
|
|
1092
1101
|
onAuthNeeded?: (payload: ToolAuthNeededPayload) => Promise<void> | void;
|
|
@@ -1303,6 +1312,9 @@ declare function modelResponseUsageFromResponse(response: unknown): ModelRespons
|
|
|
1303
1312
|
declare function serializeApprovals(interruptions: unknown[]): unknown[];
|
|
1304
1313
|
declare function serializeHumanInputRequests(interruptions: unknown[]): SerializedHumanInputInterruption[];
|
|
1305
1314
|
declare function buildManifest(settings: Settings, resources: ResourceRef[], environment?: Record<string, string>, fileResourceDownloads?: SandboxFileDownload[]): Manifest;
|
|
1315
|
+
declare function repositoryWorkspaceSkillPathsOption(resources: readonly ResourceRef[]): {
|
|
1316
|
+
workspaceSkillPaths?: readonly WorkspaceSkillSearchPath[];
|
|
1317
|
+
};
|
|
1306
1318
|
type SandboxLifecycleHookPhase = "beforeAgentStart";
|
|
1307
1319
|
type SandboxLifecycleCommandRunner = (session: TurnSandboxCommandSession, args: TurnSandboxCommandArgs) => Promise<unknown>;
|
|
1308
1320
|
type SandboxLifecycleHookContext = {
|
|
@@ -1446,4 +1458,4 @@ declare function azureOpenAIDefaultQuery(settings: Pick<Settings, "azureOpenaiAp
|
|
|
1446
1458
|
*/
|
|
1447
1459
|
declare function lazySkillSourceWithPackSkills(packSkills: PackSkill[], skillLibrarySkills?: PackSkill[]): LocalDirLazySkillSource;
|
|
1448
1460
|
|
|
1449
|
-
export { type AgentSegmentInput, type BuildAgentOptions, COMPACTION_PROMPT, COMPACTION_SUMMARY_MARKER, COMPACT_USER_MESSAGE_MAX_TOKENS, CodexSubscriptionUnavailableError, type CompactionDecision, type CompactionItem, CompactionNeededError, CompactionProviderResponseError, ComputerActionError, ComputerReadOnlyError, type ComputerToolMode, ComputerUnavailableError, type ComputerUseArgs, ComputerUseCapability, type ConnectedMcpServerBatches, type ContextRobustnessFilterOptions, DEFAULT_COMPACTION_THRESHOLD_RATIO, type EffectiveSkillSelection, EmptyCompactionSummaryError, GENESIS_TITLE_DIRECTIVE, type GitCredentialBindingSeed, type GitCredentialTokenWriterSession, type GitTokenSeeds, HUMAN_INPUT_TOOL_NAME, type HistoryItem, MAX_COMPACTION_THRESHOLD_RATIO, MAX_MODEL_USAGE_TOKEN_COUNT, MIN_COMPACTION_THRESHOLD_RATIO, type ModelCallUsageInput, type ModelCallUsageNormalization, type ModelCallUsageTelemetry, type ModelResponseUsage, MultiProviderModelProvider, type NormalizedRuntimeEvent, type OpenGeniRuntime, type PackSkill, type PackSkillFile, type PersistentSessionSettings, type PrepareInputOptions, type PrepareToolsOptions, type PreparedAgentInput, type PreparedAgentTools, type PreparedCompactionPromptInput, type ProductionRuntimeOverrides, type ResolveConnectionCredentialInput, type ResolveConnectionCredentialResult, type RigInstructionsContext, type RigSetupDescriptor, type RunAgentStreamOptions, RunCredentialSessionReady, RuntimeMetricsHooks, SUMMARY_BUFFER_TOKENS, SUMMARY_PREFIX, SandboxComputer, type SandboxComputerOptions, type SandboxFileDownload, type SandboxFileDownloadFailure, type SandboxFileDownloadMaterializationResult, type SandboxLifecycleCommandRunner, type SandboxLifecycleHook, type SandboxLifecycleHookContext, type SandboxLifecycleHookPhase, type SerializedHumanInputInterruption, TOOLSPACE_PROGRAMMATIC_DIRECTIVE, type ToolspaceTokenWriterSession, type TurnSandboxCommandArgs, TurnSandboxCommandCancelledError, type TurnSandboxCommandSession, type TurnToolCancellationController, type TurnToolCancellationFence, USER_MESSAGE_TRUNCATION_MARKER, type WorkspaceEnvironmentContext, WorkspaceModelPolicyBlockedError, agentsErrorRunState, appendGenesisTitleDirective, appendGitCredentialBindingInstructions, appendPersistentSessionSettings, appendSessionInstructions, appendToolspaceInstructions, appendTurnInstructions, appendWorkspaceMemory, applyMissingManifestEntries, azureCliLoginCommand, azureOpenAIDefaultQuery, boundModelToolOutputsFilterForSettings, buildAgentCapabilities, buildCompactionPromptInput, buildCompactionReplacementHistory, buildManifest, buildModelInstance, buildOpenAIClientFromSettings, buildOpenGeniAgent, buildProviderClient, buildSummaryItem, callModelInputFilterForSettings, clampCompactionThresholdRatio, compactionProviderFailureDiagnostics, compactionReplacementFingerprint, compactionResponseDiagnostics, compactionThresholdTokens, composeAgentInstructions, computerUse, configureOpenAI, configureRuntimeMetricsHooks, connectMcpServersInBatches, contextRobustnessFilterForSettings, coreInstructions, createProductionAgentRuntime, createTurnToolCancellationController, decideCompaction, effectiveSkillSelectionsForAgent, elideSupersededViewImagePairs, elideSupersededViewImagesFilter, ensureReadableStreamFrom, estimateCompleteModelInput, estimateItemTokens, estimateSerializedValueTokens, estimateTokens, extractResponseOutputText, findCompactionNeededError, gitCredentialBindingHash, gitCredentialBindingTokenRefreshCommand, gitProviderTokenRefreshCommand, hasModelGeneratedItem, isCompactionSummary, isEphemeralInternalContext, isUserMessage, latestCompactionReplacementFingerprint, lazySkillSourceWithPackSkills, manifestEnvironmentDrift, materializeSandboxFileDownloads, maxTurnsExceededRunState, mcpToolErrorOutput, modelCallUsageTelemetry, modelResponseUsageFromResponse, modelResponseUsageFromSdkEvent, modelUsageTokenCountOrNull, neutralizeToolSearchItemsInSerializedRunState, normalizeComputerCallsFilter, normalizeModelCallUsage, normalizeSdkEvent, normalizeToolOutputForEvent, oneShotGenesisTitleInputFilter, pinProvidedSessionManifestEnvironment, prefixedMcpToolName, prepareAgentTools, prepareCompactionPromptInput, prepareRunInput, refreshGitCredentialBindingTokenFiles, refreshGitProviderTokenFiles, refreshToolspaceTokenFile, renderCompactionPromptInputForChat, repositoryCloneCommand, repositoryUsesSandboxClone, resolveTurnModel, rigInstructions, rigSetupScriptCommand, runAgentStream, runAzureCliLoginHook, runBeforeAgentStartHooks, runOwnedSandboxSetup, runRepositoryCloneHook, runRigSetupHook, runToolspaceTokenSeedHook, sandboxCommandExitCode, sandboxCommandOutput, sandboxCommandStillRunning, sandboxFileDownloadFailureNote, sandboxFileDownloadsForAgent, sandboxLifecycleHooksForIds, sandboxRunAs, sanitizeHistoryItemsForModel, serializeApprovals, serializeHumanInputRequests, stripProviderItemIdsFilter, stripReasoningEncryptedContent, stripReasoningIdentityFromSerializedRunState, summarizeForCompaction, toolspaceTokenSeedCommand, withManifestRefreshOnResume, withSandboxFileDownloads, withSandboxLifecycleHooks, withStructuredViewImageFunctionResults, workspaceEnvironmentInstructions };
|
|
1461
|
+
export { type AgentSegmentInput, type BuildAgentOptions, COMPACTION_PROMPT, COMPACTION_SUMMARY_MARKER, COMPACT_USER_MESSAGE_MAX_TOKENS, CodexSubscriptionUnavailableError, type CompactionDecision, type CompactionItem, CompactionNeededError, CompactionProviderResponseError, ComputerActionError, ComputerReadOnlyError, type ComputerToolMode, ComputerUnavailableError, type ComputerUseArgs, ComputerUseCapability, type ConnectedMcpServerBatches, type ContextRobustnessFilterOptions, DEFAULT_COMPACTION_THRESHOLD_RATIO, type EffectiveSkillSelection, EmptyCompactionSummaryError, GENESIS_TITLE_DIRECTIVE, type GitCredentialBindingSeed, type GitCredentialTokenWriterSession, type GitTokenSeeds, HUMAN_INPUT_TOOL_NAME, type HistoryItem, MAX_COMPACTION_THRESHOLD_RATIO, MAX_MODEL_USAGE_TOKEN_COUNT, MIN_COMPACTION_THRESHOLD_RATIO, type ModelCallUsageInput, type ModelCallUsageNormalization, type ModelCallUsageTelemetry, type ModelResponseUsage, MultiProviderModelProvider, type NormalizedRuntimeEvent, type OpenGeniRuntime, type PackSkill, type PackSkillFile, type PersistentSessionSettings, type PrepareInputOptions, type PrepareToolsOptions, type PreparedAgentInput, type PreparedAgentTools, type PreparedCompactionPromptInput, type ProductionRuntimeOverrides, type ResolveConnectionCredentialInput, type ResolveConnectionCredentialResult, type RigInstructionsContext, type RigSetupDescriptor, type RunAgentStreamOptions, RunCredentialSessionReady, RuntimeMetricsHooks, SUMMARY_BUFFER_TOKENS, SUMMARY_PREFIX, SandboxComputer, type SandboxComputerOptions, type SandboxFileDownload, type SandboxFileDownloadFailure, type SandboxFileDownloadMaterializationResult, type SandboxLifecycleCommandRunner, type SandboxLifecycleHook, type SandboxLifecycleHookContext, type SandboxLifecycleHookPhase, type SerializedHumanInputInterruption, TOOLSPACE_PROGRAMMATIC_DIRECTIVE, type ToolspaceTokenWriterSession, type TurnSandboxCommandArgs, TurnSandboxCommandCancelledError, type TurnSandboxCommandSession, type TurnToolCancellationController, type TurnToolCancellationFence, USER_MESSAGE_TRUNCATION_MARKER, type WorkspaceEnvironmentContext, WorkspaceModelPolicyBlockedError, agentsErrorRunState, appendGenesisTitleDirective, appendGitCredentialBindingInstructions, appendPersistentSessionSettings, appendSessionInstructions, appendToolspaceInstructions, appendTurnInstructions, appendWorkspaceMemory, applyMissingManifestEntries, azureCliLoginCommand, azureOpenAIDefaultQuery, boundModelToolOutputsFilterForSettings, buildAgentCapabilities, buildCompactionPromptInput, buildCompactionReplacementHistory, buildManifest, buildModelInstance, buildOpenAIClientFromSettings, buildOpenGeniAgent, buildProviderClient, buildSummaryItem, callModelInputFilterForSettings, clampCompactionThresholdRatio, compactionProviderFailureDiagnostics, compactionReplacementFingerprint, compactionResponseDiagnostics, compactionThresholdTokens, composeAgentInstructions, computerUse, configureOpenAI, configureRuntimeMetricsHooks, connectMcpServersInBatches, contextRobustnessFilterForSettings, coreInstructions, createProductionAgentRuntime, createTurnToolCancellationController, decideCompaction, effectiveSkillSelectionsForAgent, elideSupersededViewImagePairs, elideSupersededViewImagesFilter, ensureReadableStreamFrom, estimateCompleteModelInput, estimateItemTokens, estimateSerializedValueTokens, estimateTokens, extractResponseOutputText, findCompactionNeededError, gitCredentialBindingHash, gitCredentialBindingTokenRefreshCommand, gitProviderTokenRefreshCommand, hasModelGeneratedItem, isCompactionSummary, isEphemeralInternalContext, isUserMessage, latestCompactionReplacementFingerprint, lazySkillSourceWithPackSkills, manifestEnvironmentDrift, materializeSandboxFileDownloads, maxTurnsExceededRunState, mcpToolErrorOutput, modelCallUsageTelemetry, modelResponseUsageFromResponse, modelResponseUsageFromSdkEvent, modelUsageTokenCountOrNull, neutralizeToolSearchItemsInSerializedRunState, normalizeComputerCallsFilter, normalizeModelCallUsage, normalizeSdkEvent, normalizeToolOutputForEvent, oneShotGenesisTitleInputFilter, pinProvidedSessionManifestEnvironment, prefixedMcpToolName, prepareAgentTools, prepareCompactionPromptInput, prepareRunInput, refreshGitCredentialBindingTokenFiles, refreshGitProviderTokenFiles, refreshToolspaceTokenFile, renderCompactionPromptInputForChat, repositoryCloneCommand, repositoryUsesSandboxClone, repositoryWorkspaceSkillPathsOption, resolveTurnModel, rigInstructions, rigSetupScriptCommand, runAgentStream, runAzureCliLoginHook, runBeforeAgentStartHooks, runOwnedSandboxSetup, runRepositoryCloneHook, runRigSetupHook, runToolspaceTokenSeedHook, sandboxCommandExitCode, sandboxCommandOutput, sandboxCommandStillRunning, sandboxFileDownloadFailureNote, sandboxFileDownloadsForAgent, sandboxLifecycleHooksForIds, sandboxRunAs, sanitizeHistoryItemsForModel, serializeApprovals, serializeHumanInputRequests, stripProviderItemIdsFilter, stripReasoningEncryptedContent, stripReasoningIdentityFromSerializedRunState, summarizeForCompaction, toolspaceTokenSeedCommand, withManifestRefreshOnResume, withSandboxFileDownloads, withSandboxLifecycleHooks, withStructuredViewImageFunctionResults, workspaceEnvironmentInstructions };
|
package/dist/index.js
CHANGED
|
@@ -6422,7 +6422,7 @@ import {
|
|
|
6422
6422
|
codexSubscriptionFetch
|
|
6423
6423
|
} from "@opengeni/codex";
|
|
6424
6424
|
import { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync } from "fs";
|
|
6425
|
-
import { createHash as
|
|
6425
|
+
import { createHash as createHash3 } from "crypto";
|
|
6426
6426
|
import { dirname, isAbsolute, join, posix as posixPath, relative } from "path";
|
|
6427
6427
|
import { fileURLToPath } from "url";
|
|
6428
6428
|
|
|
@@ -8480,6 +8480,184 @@ var ComputerUseCapability = class extends Capability {
|
|
|
8480
8480
|
}
|
|
8481
8481
|
};
|
|
8482
8482
|
|
|
8483
|
+
// src/workspace-skills.ts
|
|
8484
|
+
import { createHash as createHash2 } from "crypto";
|
|
8485
|
+
var SKILL_FILE = "SKILL.md";
|
|
8486
|
+
var MAX_DISCOVERED_SKILLS = 256;
|
|
8487
|
+
var MAX_SKILL_ENTRIES = 1024;
|
|
8488
|
+
var MAX_SKILL_BYTES = 32 * 1024 * 1024;
|
|
8489
|
+
var SAFE_SKILL_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
8490
|
+
var WorkspaceSkillsCapability = class extends Capability {
|
|
8491
|
+
constructor(searchPaths, reservedNames = /* @__PURE__ */ new Set()) {
|
|
8492
|
+
super();
|
|
8493
|
+
this.searchPaths = searchPaths;
|
|
8494
|
+
this.reservedNames = reservedNames;
|
|
8495
|
+
}
|
|
8496
|
+
type = "workspace-skills";
|
|
8497
|
+
discovery;
|
|
8498
|
+
async instructions() {
|
|
8499
|
+
const session = requireWorkspaceSkillSession(this._session);
|
|
8500
|
+
this.discovery ??= discoverWorkspaceSkills(
|
|
8501
|
+
session,
|
|
8502
|
+
this.searchPaths,
|
|
8503
|
+
this.reservedNames,
|
|
8504
|
+
this._runAs
|
|
8505
|
+
);
|
|
8506
|
+
const skills2 = await this.discovery;
|
|
8507
|
+
if (skills2.length === 0) return null;
|
|
8508
|
+
const available = skills2.map((skill) => `- ${skill.name}: ${skill.description} (file: ${skill.path})`).join("\n");
|
|
8509
|
+
return `## Repository skills
|
|
8510
|
+
|
|
8511
|
+
Repository skills are instructions already present in the live workspace. They do not need to be loaded or copied.
|
|
8512
|
+
|
|
8513
|
+
### Available repository skills
|
|
8514
|
+
${available}
|
|
8515
|
+
|
|
8516
|
+
### How to use repository skills
|
|
8517
|
+
- If the user names a skill, or the task clearly matches a skill description, read its complete SKILL.md before acting.
|
|
8518
|
+
- Resolve referenced scripts, references, assets, and templates relative to that skill directory.
|
|
8519
|
+
- Use only the minimum relevant skills for the turn, and say briefly which ones you are using.
|
|
8520
|
+
- Do not assume a skill remains applicable on later turns; evaluate the current request again.`;
|
|
8521
|
+
}
|
|
8522
|
+
};
|
|
8523
|
+
function workspaceSkills(searchPaths, reservedNames = []) {
|
|
8524
|
+
return new WorkspaceSkillsCapability(
|
|
8525
|
+
searchPaths,
|
|
8526
|
+
new Set([...reservedNames].map((name) => name.toLowerCase()))
|
|
8527
|
+
);
|
|
8528
|
+
}
|
|
8529
|
+
async function discoverWorkspaceSkills(session, searchPaths, reservedNames = /* @__PURE__ */ new Set(), runAs) {
|
|
8530
|
+
if (!session.listDir || !session.readFile) {
|
|
8531
|
+
throw new Error("Workspace skill discovery requires sandbox listDir() and readFile() support");
|
|
8532
|
+
}
|
|
8533
|
+
const discovered = /* @__PURE__ */ new Map();
|
|
8534
|
+
let candidates = 0;
|
|
8535
|
+
for (const searchPath of searchPaths) {
|
|
8536
|
+
let entries;
|
|
8537
|
+
try {
|
|
8538
|
+
entries = await session.listDir({ path: searchPath.path, ...runAs ? { runAs } : {} });
|
|
8539
|
+
} catch {
|
|
8540
|
+
continue;
|
|
8541
|
+
}
|
|
8542
|
+
for (const entry of [...entries].sort((left, right) => left.name.localeCompare(right.name))) {
|
|
8543
|
+
if (entry.type !== "dir") continue;
|
|
8544
|
+
candidates += 1;
|
|
8545
|
+
if (candidates > MAX_DISCOVERED_SKILLS) {
|
|
8546
|
+
throw new Error(`Repository skill discovery exceeds ${MAX_DISCOVERED_SKILLS} directories`);
|
|
8547
|
+
}
|
|
8548
|
+
const skillMarkdownPath = joinWorkspacePath(entry.path, SKILL_FILE);
|
|
8549
|
+
let markdown;
|
|
8550
|
+
try {
|
|
8551
|
+
const content = await session.readFile({
|
|
8552
|
+
path: skillMarkdownPath,
|
|
8553
|
+
...runAs ? { runAs } : {}
|
|
8554
|
+
});
|
|
8555
|
+
markdown = typeof content === "string" ? content : new TextDecoder().decode(content);
|
|
8556
|
+
} catch {
|
|
8557
|
+
continue;
|
|
8558
|
+
}
|
|
8559
|
+
const frontmatter = parseSkillFrontmatter(markdown);
|
|
8560
|
+
const name = frontmatter.name?.trim() || entry.name;
|
|
8561
|
+
if (name.length > 64 || !SAFE_SKILL_NAME.test(name)) {
|
|
8562
|
+
throw new Error(`Repository skill has an invalid name: ${name.slice(0, 64)}`);
|
|
8563
|
+
}
|
|
8564
|
+
const description = frontmatter.description?.trim() || "No description provided.";
|
|
8565
|
+
if (description.length > 2048 || /[\r\n]/.test(description)) {
|
|
8566
|
+
throw new Error(`Repository skill "${name}" has an invalid description`);
|
|
8567
|
+
}
|
|
8568
|
+
const key = name.toLowerCase();
|
|
8569
|
+
if (reservedNames.has(key)) {
|
|
8570
|
+
throw new Error(`Workspace skill "${name}" conflicts with a configured OpenGeni skill`);
|
|
8571
|
+
}
|
|
8572
|
+
const candidate = {
|
|
8573
|
+
name,
|
|
8574
|
+
description,
|
|
8575
|
+
path: skillMarkdownPath,
|
|
8576
|
+
fingerprint: await fingerprintWorkspaceDirectory(session, entry.path, runAs),
|
|
8577
|
+
source: searchPath.source
|
|
8578
|
+
};
|
|
8579
|
+
const existing = discovered.get(key);
|
|
8580
|
+
if (!existing) {
|
|
8581
|
+
discovered.set(key, candidate);
|
|
8582
|
+
continue;
|
|
8583
|
+
}
|
|
8584
|
+
if (existing.fingerprint !== candidate.fingerprint) {
|
|
8585
|
+
throw new Error(
|
|
8586
|
+
`Workspace skill "${name}" has conflicting definitions in ${existing.source} and ${candidate.source}`
|
|
8587
|
+
);
|
|
8588
|
+
}
|
|
8589
|
+
}
|
|
8590
|
+
}
|
|
8591
|
+
return [...discovered.values()].sort((left, right) => left.name.localeCompare(right.name));
|
|
8592
|
+
}
|
|
8593
|
+
async function fingerprintWorkspaceDirectory(session, root, runAs) {
|
|
8594
|
+
const hash = createHash2("sha256");
|
|
8595
|
+
let entryCount = 0;
|
|
8596
|
+
let byteCount = 0;
|
|
8597
|
+
async function visit(path, relativePath) {
|
|
8598
|
+
const entries = await session.listDir({ path, ...runAs ? { runAs } : {} });
|
|
8599
|
+
for (const entry of [...entries].sort((left, right) => left.name.localeCompare(right.name))) {
|
|
8600
|
+
entryCount += 1;
|
|
8601
|
+
if (entryCount > MAX_SKILL_ENTRIES) {
|
|
8602
|
+
throw new Error(`Workspace skill exceeds ${MAX_SKILL_ENTRIES} filesystem entries`);
|
|
8603
|
+
}
|
|
8604
|
+
const childRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
8605
|
+
hash.update(entry.type);
|
|
8606
|
+
hash.update("\0");
|
|
8607
|
+
hash.update(childRelativePath);
|
|
8608
|
+
hash.update("\0");
|
|
8609
|
+
if (entry.type === "dir") {
|
|
8610
|
+
await visit(entry.path, childRelativePath);
|
|
8611
|
+
continue;
|
|
8612
|
+
}
|
|
8613
|
+
if (entry.type !== "file") continue;
|
|
8614
|
+
const content = await session.readFile({
|
|
8615
|
+
path: entry.path,
|
|
8616
|
+
...runAs ? { runAs } : {}
|
|
8617
|
+
});
|
|
8618
|
+
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
|
|
8619
|
+
byteCount += bytes.byteLength;
|
|
8620
|
+
if (byteCount > MAX_SKILL_BYTES) {
|
|
8621
|
+
throw new Error(`Workspace skill exceeds ${MAX_SKILL_BYTES} bytes`);
|
|
8622
|
+
}
|
|
8623
|
+
hash.update(bytes);
|
|
8624
|
+
hash.update("\0");
|
|
8625
|
+
}
|
|
8626
|
+
}
|
|
8627
|
+
await visit(root, "");
|
|
8628
|
+
return hash.digest("hex");
|
|
8629
|
+
}
|
|
8630
|
+
function parseSkillFrontmatter(markdown) {
|
|
8631
|
+
const lines = markdown.split(/\r?\n/);
|
|
8632
|
+
if (lines[0]?.trim() !== "---") return {};
|
|
8633
|
+
const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
|
|
8634
|
+
if (end === -1) return {};
|
|
8635
|
+
const values = {};
|
|
8636
|
+
for (const line of lines.slice(1, end)) {
|
|
8637
|
+
const separator = line.indexOf(":");
|
|
8638
|
+
if (separator === -1) continue;
|
|
8639
|
+
const key = line.slice(0, separator).trim();
|
|
8640
|
+
if (key !== "name" && key !== "description") continue;
|
|
8641
|
+
values[key] = unquote(line.slice(separator + 1).trim());
|
|
8642
|
+
}
|
|
8643
|
+
return values;
|
|
8644
|
+
}
|
|
8645
|
+
function unquote(value) {
|
|
8646
|
+
if (value.length >= 2 && value[0] === value[value.length - 1] && (value[0] === '"' || value[0] === "'")) {
|
|
8647
|
+
return value.slice(1, -1);
|
|
8648
|
+
}
|
|
8649
|
+
return value;
|
|
8650
|
+
}
|
|
8651
|
+
function joinWorkspacePath(parent, child) {
|
|
8652
|
+
return `${parent.replace(/\/+$/, "")}/${child}`;
|
|
8653
|
+
}
|
|
8654
|
+
function requireWorkspaceSkillSession(session) {
|
|
8655
|
+
if (!session) {
|
|
8656
|
+
throw new Error('capability "workspace-skills" used before bind(session)');
|
|
8657
|
+
}
|
|
8658
|
+
return session;
|
|
8659
|
+
}
|
|
8660
|
+
|
|
8483
8661
|
// src/usage-telemetry.ts
|
|
8484
8662
|
var MAX_MODEL_USAGE_TOKEN_COUNT = 1e9;
|
|
8485
8663
|
function modelUsageTokenCountOrNull(value) {
|
|
@@ -9574,6 +9752,8 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
|
|
|
9574
9752
|
...runAs ? { runAs } : {},
|
|
9575
9753
|
capabilities: buildAgentCapabilities(settings, options.packSkills ?? [], {
|
|
9576
9754
|
...options.skillLibrarySkills?.length ? { skillLibrarySkills: options.skillLibrarySkills } : {},
|
|
9755
|
+
...options.sessionSkills?.length ? { sessionSkills: options.sessionSkills } : {},
|
|
9756
|
+
...repositoryWorkspaceSkillPathsOption(resources),
|
|
9577
9757
|
...options.structuredToolTransport !== void 0 ? { structuredToolTransport: options.structuredToolTransport } : {},
|
|
9578
9758
|
...options.computerToolMode !== void 0 ? { computerToolMode: options.computerToolMode } : {},
|
|
9579
9759
|
...options.onComputerUseReady ? { onComputerUseReady: options.onComputerUseReady } : {},
|
|
@@ -9587,7 +9767,8 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
|
|
|
9587
9767
|
effectiveSkillSelections(
|
|
9588
9768
|
options.skillLibrarySelections ?? [],
|
|
9589
9769
|
options.skillLibrarySkills ?? [],
|
|
9590
|
-
options.packSkills ?? []
|
|
9770
|
+
options.packSkills ?? [],
|
|
9771
|
+
options.sessionSkills ?? []
|
|
9591
9772
|
).map((selection) => Object.freeze(selection))
|
|
9592
9773
|
)
|
|
9593
9774
|
);
|
|
@@ -9739,11 +9920,29 @@ function buildAgentCapabilities(settings, packSkills, options = {}) {
|
|
|
9739
9920
|
filesystemCapability,
|
|
9740
9921
|
shell({ ...toolCancellation ? {} : { configureTools: withExecOpCorrelation } })
|
|
9741
9922
|
];
|
|
9923
|
+
const sessionSkills = sessionSkillsForMaterialization(
|
|
9924
|
+
packSkills,
|
|
9925
|
+
options.skillLibrarySkills ?? [],
|
|
9926
|
+
options.sessionSkills ?? []
|
|
9927
|
+
);
|
|
9742
9928
|
caps.push(
|
|
9743
9929
|
skills({
|
|
9744
|
-
lazyFrom: lazySkillSourceWithPackSkills(
|
|
9930
|
+
lazyFrom: lazySkillSourceWithPackSkills(
|
|
9931
|
+
[...packSkills, ...sessionSkills],
|
|
9932
|
+
options.skillLibrarySkills ?? []
|
|
9933
|
+
)
|
|
9745
9934
|
})
|
|
9746
9935
|
);
|
|
9936
|
+
if (options.workspaceSkillPaths?.length) {
|
|
9937
|
+
caps.push(
|
|
9938
|
+
workspaceSkills(options.workspaceSkillPaths, [
|
|
9939
|
+
...bundledSkillDirNames(bundledSkillsDir()),
|
|
9940
|
+
...(options.skillLibrarySkills ?? []).map((skill) => skill.name),
|
|
9941
|
+
...packSkills.map((skill) => skill.name),
|
|
9942
|
+
...sessionSkills.map((skill) => skill.name)
|
|
9943
|
+
])
|
|
9944
|
+
);
|
|
9945
|
+
}
|
|
9747
9946
|
if (settings.computerUseEnabled && settings.sandboxDesktopEnabled && desktopCapableBackend(settings.sandboxBackend)) {
|
|
9748
9947
|
const explicitMode = options.computerToolMode;
|
|
9749
9948
|
const computerCapability = computerUse({
|
|
@@ -9830,6 +10029,14 @@ async function prepareAgentTools(settings, tools, options = {}) {
|
|
|
9830
10029
|
}, codexConnectorNamespaces };
|
|
9831
10030
|
}
|
|
9832
10031
|
const registry = new Map(settings.mcpServers.map((server) => [server.id, server]));
|
|
10032
|
+
const subjectOwnedTool = tools.find(
|
|
10033
|
+
(tool2) => registry.get(tool2.id)?.connectionRef?.subjectScope === "subject"
|
|
10034
|
+
);
|
|
10035
|
+
if (subjectOwnedTool && !options.credentialSubjectId) {
|
|
10036
|
+
throw new Error(
|
|
10037
|
+
`subject-owned connection for MCP server ${subjectOwnedTool.id} requires a human turn initiator`
|
|
10038
|
+
);
|
|
10039
|
+
}
|
|
9833
10040
|
const aggregateToolBudget = new McpAggregateToolListBudget();
|
|
9834
10041
|
const useBunNativeFetch = options.mcpFetchImpl === void 0 && !!process.versions.bun;
|
|
9835
10042
|
const mcpFetchImpl = options.mcpFetchImpl ?? (useBunNativeFetch ? globalThis.fetch.bind(globalThis) : undiciFetch);
|
|
@@ -10048,7 +10255,7 @@ async function resolveConnectionForRequest(options, serverId, connectionRef, des
|
|
|
10048
10255
|
destinationUrl,
|
|
10049
10256
|
forceRefresh,
|
|
10050
10257
|
...toolName ? { toolName } : {},
|
|
10051
|
-
...options.
|
|
10258
|
+
...options.credentialSubjectId ? { subjectId: options.credentialSubjectId } : {}
|
|
10052
10259
|
};
|
|
10053
10260
|
try {
|
|
10054
10261
|
return await options.resolveCredential(request);
|
|
@@ -11661,6 +11868,24 @@ function buildManifest(settings, resources, environment = collectSandboxEnvironm
|
|
|
11661
11868
|
environment
|
|
11662
11869
|
});
|
|
11663
11870
|
}
|
|
11871
|
+
function repositoryWorkspaceSkillPathsOption(resources) {
|
|
11872
|
+
const repositories = resources.filter(
|
|
11873
|
+
(resource) => resource.kind === "repository"
|
|
11874
|
+
);
|
|
11875
|
+
if (repositories.length === 0) return {};
|
|
11876
|
+
const paths = /* @__PURE__ */ new Map();
|
|
11877
|
+
const add = (path, source) => {
|
|
11878
|
+
if (!paths.has(path)) paths.set(path, { path, source });
|
|
11879
|
+
};
|
|
11880
|
+
add(".agents/skills", "workspace .agents/skills");
|
|
11881
|
+
add(".claude/skills", "workspace .claude/skills");
|
|
11882
|
+
for (const repository of repositories) {
|
|
11883
|
+
const mountPath = resourceMountPath(repository);
|
|
11884
|
+
add(`${mountPath}/.agents/skills`, `${mountPath}/.agents/skills`);
|
|
11885
|
+
add(`${mountPath}/.claude/skills`, `${mountPath}/.claude/skills`);
|
|
11886
|
+
}
|
|
11887
|
+
return { workspaceSkillPaths: [...paths.values()] };
|
|
11888
|
+
}
|
|
11664
11889
|
function sandboxDownloadDirectory(download, mountPath) {
|
|
11665
11890
|
if (download.mountPath !== mountPath) {
|
|
11666
11891
|
throw new Error(
|
|
@@ -11999,7 +12224,7 @@ function gitProviderSeedEnv(provider) {
|
|
|
11999
12224
|
return `OPENGENI_GIT_${provider.toUpperCase()}_TOKEN_SEED`;
|
|
12000
12225
|
}
|
|
12001
12226
|
function gitCredentialBindingHash(credentialBindingId) {
|
|
12002
|
-
return
|
|
12227
|
+
return createHash3("sha256").update(credentialBindingId, "utf8").digest("hex").slice(0, 32);
|
|
12003
12228
|
}
|
|
12004
12229
|
function gitBindingSeedEnv(binding) {
|
|
12005
12230
|
return `OPENGENI_GIT_BINDING_${gitCredentialBindingHash(binding.credentialBindingId).toUpperCase()}_TOKEN_SEED`;
|
|
@@ -13187,7 +13412,7 @@ function lazySkillSourceWithPackSkills(packSkills, skillLibrarySkills = []) {
|
|
|
13187
13412
|
]
|
|
13188
13413
|
};
|
|
13189
13414
|
}
|
|
13190
|
-
function effectiveSkillSelections(librarySelections, librarySkills, packSkills) {
|
|
13415
|
+
function effectiveSkillSelections(librarySelections, librarySkills, packSkills, sessionSkills) {
|
|
13191
13416
|
const defaultSelections = bundledSkillDirNames(bundledSkillsDir()).map((name) => ({
|
|
13192
13417
|
id: `bundled:${name}`,
|
|
13193
13418
|
name,
|
|
@@ -13198,14 +13423,22 @@ function effectiveSkillSelections(librarySelections, librarySkills, packSkills)
|
|
|
13198
13423
|
}));
|
|
13199
13424
|
const libraryNameKeys = new Set(librarySkills.map((skill) => skill.name.toLowerCase()));
|
|
13200
13425
|
const packNameKeys = new Set(packSkills.map((skill) => skill.name.toLowerCase()));
|
|
13426
|
+
const effectiveSessionSkills = sessionSkillsForMaterialization(
|
|
13427
|
+
packSkills,
|
|
13428
|
+
librarySkills,
|
|
13429
|
+
sessionSkills
|
|
13430
|
+
);
|
|
13431
|
+
const sessionNameKeys = new Set(effectiveSessionSkills.map((skill) => skill.name.toLowerCase()));
|
|
13201
13432
|
const selected = librarySelections.filter(
|
|
13202
13433
|
(selection) => libraryNameKeys.has(selection.name.toLowerCase())
|
|
13203
13434
|
);
|
|
13204
13435
|
return [
|
|
13205
13436
|
...defaultSelections.filter(
|
|
13206
|
-
(selection) => !libraryNameKeys.has(selection.name.toLowerCase()) && !packNameKeys.has(selection.name.toLowerCase())
|
|
13437
|
+
(selection) => !libraryNameKeys.has(selection.name.toLowerCase()) && !packNameKeys.has(selection.name.toLowerCase()) && !sessionNameKeys.has(selection.name.toLowerCase())
|
|
13438
|
+
),
|
|
13439
|
+
...selected.filter(
|
|
13440
|
+
(selection) => !packNameKeys.has(selection.name.toLowerCase()) && !sessionNameKeys.has(selection.name.toLowerCase())
|
|
13207
13441
|
),
|
|
13208
|
-
...selected.filter((selection) => !packNameKeys.has(selection.name.toLowerCase())),
|
|
13209
13442
|
...packSkills.map((skill) => ({
|
|
13210
13443
|
id: `pack:${skill.name}`,
|
|
13211
13444
|
name: skill.name,
|
|
@@ -13213,9 +13446,48 @@ function effectiveSkillSelections(librarySelections, librarySkills, packSkills)
|
|
|
13213
13446
|
version: null,
|
|
13214
13447
|
contentSha256: null,
|
|
13215
13448
|
reason: "enabled capability pack"
|
|
13449
|
+
})),
|
|
13450
|
+
...effectiveSessionSkills.map((skill) => ({
|
|
13451
|
+
id: `session:${skill.name}`,
|
|
13452
|
+
name: skill.name,
|
|
13453
|
+
source: "session",
|
|
13454
|
+
version: null,
|
|
13455
|
+
contentSha256: null,
|
|
13456
|
+
reason: "attached to session"
|
|
13216
13457
|
}))
|
|
13217
13458
|
];
|
|
13218
13459
|
}
|
|
13460
|
+
function sessionSkillsForMaterialization(packSkills, librarySkills, sessionSkills) {
|
|
13461
|
+
const configured = /* @__PURE__ */ new Map();
|
|
13462
|
+
for (const skill of [...librarySkills, ...packSkills]) {
|
|
13463
|
+
configured.set(skill.name.toLowerCase(), skill);
|
|
13464
|
+
}
|
|
13465
|
+
const bundledNames = new Set(
|
|
13466
|
+
bundledSkillDirNames(bundledSkillsDir()).map((name) => name.toLowerCase())
|
|
13467
|
+
);
|
|
13468
|
+
const selected = /* @__PURE__ */ new Map();
|
|
13469
|
+
for (const skill of sessionSkills) {
|
|
13470
|
+
assertSafePackSkillName(skill.name);
|
|
13471
|
+
const key = skill.name.toLowerCase();
|
|
13472
|
+
if (bundledNames.has(key)) {
|
|
13473
|
+
throw new Error(`Session skill "${skill.name}" conflicts with a bundled skill`);
|
|
13474
|
+
}
|
|
13475
|
+
const existing = selected.get(key) ?? configured.get(key);
|
|
13476
|
+
if (existing) {
|
|
13477
|
+
if (skillFingerprint(existing) !== skillFingerprint(skill)) {
|
|
13478
|
+
throw new Error(`Conflicting skill definitions for "${skill.name}"`);
|
|
13479
|
+
}
|
|
13480
|
+
continue;
|
|
13481
|
+
}
|
|
13482
|
+
selected.set(key, skill);
|
|
13483
|
+
}
|
|
13484
|
+
return [...selected.values()];
|
|
13485
|
+
}
|
|
13486
|
+
function skillFingerprint(skill) {
|
|
13487
|
+
return JSON.stringify(
|
|
13488
|
+
[...skill.files].sort((left, right) => left.path.localeCompare(right.path)).map(({ path, content }) => ({ path, content }))
|
|
13489
|
+
);
|
|
13490
|
+
}
|
|
13219
13491
|
function removeSkillChildByNameKey(children, nameKey) {
|
|
13220
13492
|
for (const name of Object.keys(children)) {
|
|
13221
13493
|
if (name.toLowerCase() === nameKey) {
|
|
@@ -13590,6 +13862,7 @@ export {
|
|
|
13590
13862
|
renderSelfhostedFault,
|
|
13591
13863
|
repositoryCloneCommand,
|
|
13592
13864
|
repositoryUsesSandboxClone,
|
|
13865
|
+
repositoryWorkspaceSkillPathsOption,
|
|
13593
13866
|
requirePersistableReplacementSandboxEnvelope,
|
|
13594
13867
|
resolveTurnModel,
|
|
13595
13868
|
restoredSandboxSessionStateFromEntry,
|