@opengeni/worker-bundle 0.27.0-canary.1 → 0.27.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.
- package/dist/activities/agent-turn/agent-build.d.ts +3 -4
- package/dist/activities/agent-turn/governance-model.d.ts +2 -3
- package/dist/activities/agent-turn/skill-checkout.d.ts +21 -0
- package/dist/activities/agent-turn/skill-install.d.ts +12 -0
- package/dist/activities/agent-turn/skill-read.d.ts +15 -0
- package/dist/activities/agent-turn/skill-save.d.ts +26 -0
- package/dist/activities/agent-turn/skill-search.d.ts +16 -0
- package/dist/activities/agent-turn/skill-selection.d.ts +17 -0
- package/dist/activities/agent-turn/skill-tools.d.ts +20 -0
- package/dist/activities/agent-turn/skill-transfer.d.ts +26 -0
- package/dist/activities/agent-turn/tool-environment.d.ts +7 -0
- package/dist/activities/parent-wake.d.ts +12 -2
- package/dist/activities/run-input.d.ts +11 -5
- package/dist/activities/sandbox-lease.d.ts +5 -4
- package/dist/activities/types.d.ts +4 -2
- package/dist/activities/workflow-wake.d.ts +2 -4
- package/dist/{activities-control-VMA3XMHE.js → activities-control-WZRFEIJH.js} +103 -26
- package/dist/activities-control-WZRFEIJH.js.map +1 -0
- package/dist/{activities-turn-57AOUNYN.js → activities-turn-V7J34ZOF.js} +945 -532
- package/dist/activities-turn-V7J34ZOF.js.map +1 -0
- package/dist/{chunk-D4ZEFOYH.js → chunk-BARTLVBK.js} +1 -1
- package/dist/chunk-BARTLVBK.js.map +1 -0
- package/dist/{chunk-7LS42PHP.js → chunk-C54VDT6I.js} +590 -34
- package/dist/chunk-C54VDT6I.js.map +1 -0
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/model-context-contributions.d.ts +2 -0
- package/dist/observability-metrics.d.ts +1 -1
- package/dist/workflow-bundle.js +1 -1
- package/package.json +17 -17
- package/src/activities/agent-turn/agent-build.ts +8 -34
- package/src/activities/agent-turn/errors.ts +4 -0
- package/src/activities/agent-turn/governance-model.ts +15 -19
- package/src/activities/agent-turn/run.ts +4 -6
- package/src/activities/agent-turn/sandbox-provision.ts +9 -0
- package/src/activities/agent-turn/skill-checkout.ts +124 -0
- package/src/activities/agent-turn/skill-install.ts +57 -0
- package/src/activities/agent-turn/skill-read.ts +117 -0
- package/src/activities/agent-turn/skill-save.ts +124 -0
- package/src/activities/agent-turn/skill-search.ts +110 -0
- package/src/activities/agent-turn/skill-selection.ts +53 -0
- package/src/activities/agent-turn/skill-tools.ts +268 -0
- package/src/activities/agent-turn/skill-transfer.ts +137 -0
- package/src/activities/agent-turn/tool-environment.ts +93 -1
- package/src/activities/automations.ts +3 -1
- package/src/activities/context-compaction.ts +26 -2
- package/src/activities/parent-wake.ts +66 -5
- package/src/activities/run-input.ts +88 -12
- package/src/activities/sandbox-lease.ts +77 -20
- package/src/activities/scheduled-tasks.ts +2 -0
- package/src/activities/types.ts +4 -2
- package/src/activities/workflow-wake.ts +42 -5
- package/src/index.ts +3 -1
- package/src/model-context-contributions.ts +18 -2
- package/src/observability-metrics.ts +2 -0
- package/src/sandbox-routing.ts +42 -1
- package/dist/activities-control-VMA3XMHE.js.map +0 -1
- package/dist/activities-turn-57AOUNYN.js.map +0 -1
- package/dist/chunk-7LS42PHP.js.map +0 -1
- package/dist/chunk-D4ZEFOYH.js.map +0 -1
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
compactionFailureReason,
|
|
24
24
|
compactionFailureReasonFromError,
|
|
25
25
|
computeIdleDelayMs,
|
|
26
|
+
createModelHistoryAttachmentProjector,
|
|
26
27
|
createRuntimeBatcher,
|
|
27
28
|
createSharedActivityServices,
|
|
28
29
|
createTurnSandboxProvisioner,
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
persistOrSignalSessionAttemptQuiescence,
|
|
45
46
|
postClaimDatabaseRecoveryFailure,
|
|
46
47
|
preClaimAdmissionFailure,
|
|
48
|
+
projectRejectedProviderArtifacts,
|
|
47
49
|
providerRecoveryCountAfterModelRequestPhase,
|
|
48
50
|
providerRecoveryCountFromMetadata,
|
|
49
51
|
providerRecoveryExhaustedFailure,
|
|
@@ -53,7 +55,6 @@ import {
|
|
|
53
55
|
refreshExhaustedXaiQuota,
|
|
54
56
|
releaseTurnSandboxAfterWriterDrain,
|
|
55
57
|
requireAgentStreamFinalOutput,
|
|
56
|
-
resolveWorkspaceInstalledSkillRuntime,
|
|
57
58
|
resolveWorkspacePackRuntime,
|
|
58
59
|
resumeBoxForTurn,
|
|
59
60
|
rigProviderImageSourceImage,
|
|
@@ -75,6 +76,7 @@ import {
|
|
|
75
76
|
startActivityHeartbeat,
|
|
76
77
|
throwIfTurnOperationCancelled,
|
|
77
78
|
turnFinalizerCancellationSignal,
|
|
79
|
+
turnInput,
|
|
78
80
|
turnOperationCancellationFailure,
|
|
79
81
|
unavailableMcpOperationalContext,
|
|
80
82
|
validateIncidentTelemetrySystemUpdateAuthority,
|
|
@@ -84,7 +86,7 @@ import {
|
|
|
84
86
|
withFirstPartyTools,
|
|
85
87
|
wrapLazyTurnBoxWithRouting,
|
|
86
88
|
wrapTurnBoxWithRouting
|
|
87
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-C54VDT6I.js";
|
|
88
90
|
import {
|
|
89
91
|
StreamTimingMetrics,
|
|
90
92
|
makeMachineOpObserver,
|
|
@@ -110,7 +112,7 @@ import {
|
|
|
110
112
|
recordTurnWorkerPreparationTotal,
|
|
111
113
|
runtimeMetricsHooksForObservability,
|
|
112
114
|
turnLifecycleMetricsFor
|
|
113
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-BARTLVBK.js";
|
|
114
116
|
|
|
115
117
|
// src/activities-turn.ts
|
|
116
118
|
import { createProductionAgentRuntime, summarizeForCompaction as summarizeForCompaction2 } from "@opengeni/runtime";
|
|
@@ -168,9 +170,6 @@ function summarizeCompanyBrainContributions(receipt) {
|
|
|
168
170
|
}
|
|
169
171
|
return Object.freeze([...bySource.values()].map((summary) => Object.freeze(summary)));
|
|
170
172
|
}
|
|
171
|
-
function modelVisibleCompanyBrainSkillActivations(sandboxBackend, skillActivations) {
|
|
172
|
-
return sandboxBackend === "none" ? [] : skillActivations;
|
|
173
|
-
}
|
|
174
173
|
function buildCompanyBrainContributionReceipt(input) {
|
|
175
174
|
const contributions = [];
|
|
176
175
|
for (const entry of input.instructionPolicy.entries) {
|
|
@@ -195,7 +194,7 @@ function buildCompanyBrainContributionReceipt(input) {
|
|
|
195
194
|
})
|
|
196
195
|
);
|
|
197
196
|
}
|
|
198
|
-
for (const descriptor of input.preferences?.descriptors ?? []) {
|
|
197
|
+
for (const descriptor of input.skillCatalogText !== void 0 ? [] : input.preferences?.descriptors ?? []) {
|
|
199
198
|
contributions.push(
|
|
200
199
|
contribution({
|
|
201
200
|
category: "skill_guide_descriptor",
|
|
@@ -228,7 +227,17 @@ function buildCompanyBrainContributionReceipt(input) {
|
|
|
228
227
|
})
|
|
229
228
|
);
|
|
230
229
|
}
|
|
231
|
-
|
|
230
|
+
if (input.skillCatalogText)
|
|
231
|
+
contributions.push(
|
|
232
|
+
contribution({
|
|
233
|
+
category: "skill_guide_descriptor",
|
|
234
|
+
source: "runtime_skill_catalog",
|
|
235
|
+
inclusionReason: "authorized_skill_descriptor",
|
|
236
|
+
authorityScope: "workspace",
|
|
237
|
+
text: input.skillCatalogText
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
for (const descriptor of input.skillCatalogText !== void 0 ? [] : composeRuntimeSkills(input.skillActivations).configuredDescriptors) {
|
|
232
241
|
contributions.push(
|
|
233
242
|
contribution({
|
|
234
243
|
category: "skill_guide_descriptor",
|
|
@@ -6809,7 +6818,7 @@ import { serviceTierForLatencyMode } from "@opengeni/config";
|
|
|
6809
6818
|
// src/activities/context-compaction.ts
|
|
6810
6819
|
import {
|
|
6811
6820
|
applyContextCompaction,
|
|
6812
|
-
getActiveSessionHistoryItemsPaged as
|
|
6821
|
+
getActiveSessionHistoryItemsPaged as getActiveSessionHistoryItemsPaged2,
|
|
6813
6822
|
recordSkippedContextCompaction,
|
|
6814
6823
|
recordStartedContextCompaction
|
|
6815
6824
|
} from "@opengeni/db";
|
|
@@ -6830,463 +6839,6 @@ import {
|
|
|
6830
6839
|
summarizeForCompaction
|
|
6831
6840
|
} from "@opengeni/runtime";
|
|
6832
6841
|
import { contextInputBudgetTokens } from "@opengeni/config";
|
|
6833
|
-
|
|
6834
|
-
// src/activities/run-input.ts
|
|
6835
|
-
import {
|
|
6836
|
-
MODEL_ATTACHMENT_REFS_FIELD,
|
|
6837
|
-
FileResourceRef,
|
|
6838
|
-
resourceMountPath as resourceMountPath2
|
|
6839
|
-
} from "@opengeni/contracts";
|
|
6840
|
-
import { createHash as createHash8 } from "crypto";
|
|
6841
|
-
import {
|
|
6842
|
-
getActiveSessionHistoryItemsPaged as getActiveSessionHistoryItemsPaged2,
|
|
6843
|
-
getFilesForSubject as getFilesForSubject2,
|
|
6844
|
-
getSandboxSessionEnvelope,
|
|
6845
|
-
listSessionSystemUpdatesForTurn,
|
|
6846
|
-
listTurnOpenSuffixToolCalls
|
|
6847
|
-
} from "@opengeni/db";
|
|
6848
|
-
import {
|
|
6849
|
-
projectHistoryForProvider,
|
|
6850
|
-
projectRejectedProviderArtifactsFromSerializedRunState,
|
|
6851
|
-
projectRejectedReasoningArtifact,
|
|
6852
|
-
hasOpaqueProviderArtifact
|
|
6853
|
-
} from "@opengeni/runtime";
|
|
6854
|
-
function projectRejectedProviderArtifacts(rows) {
|
|
6855
|
-
const out = [];
|
|
6856
|
-
for (const row of rows) {
|
|
6857
|
-
if (!row.providerArtifactInvalidatedAt) {
|
|
6858
|
-
out.push(row.item);
|
|
6859
|
-
continue;
|
|
6860
|
-
}
|
|
6861
|
-
const type = typeof row.item.type === "string" ? row.item.type : void 0;
|
|
6862
|
-
if (type === "reasoning") {
|
|
6863
|
-
out.push(projectRejectedReasoningArtifact(row.item));
|
|
6864
|
-
continue;
|
|
6865
|
-
}
|
|
6866
|
-
if (type === "compaction") {
|
|
6867
|
-
continue;
|
|
6868
|
-
}
|
|
6869
|
-
out.push(row.item);
|
|
6870
|
-
}
|
|
6871
|
-
return out;
|
|
6872
|
-
}
|
|
6873
|
-
async function measureHistoryPreparationPhase(options, phase, operation) {
|
|
6874
|
-
const startedAt = performance.now();
|
|
6875
|
-
let outcome = "completed";
|
|
6876
|
-
try {
|
|
6877
|
-
return await operation();
|
|
6878
|
-
} catch (error) {
|
|
6879
|
-
outcome = "failed";
|
|
6880
|
-
throw error;
|
|
6881
|
-
} finally {
|
|
6882
|
-
try {
|
|
6883
|
-
options.onPreparationPhase?.({
|
|
6884
|
-
phase,
|
|
6885
|
-
outcome,
|
|
6886
|
-
durationSeconds: (performance.now() - startedAt) / 1e3
|
|
6887
|
-
});
|
|
6888
|
-
} catch {
|
|
6889
|
-
}
|
|
6890
|
-
}
|
|
6891
|
-
}
|
|
6892
|
-
var MAX_INLINE_MODEL_ATTACHMENT_BYTES = 20 * 1024 * 1024;
|
|
6893
|
-
var MODEL_IMAGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["image/gif", "image/jpeg", "image/png", "image/webp"]);
|
|
6894
|
-
var MODEL_FILE_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
6895
|
-
"application/json",
|
|
6896
|
-
"application/pdf",
|
|
6897
|
-
"application/x-yaml",
|
|
6898
|
-
"application/yaml"
|
|
6899
|
-
]);
|
|
6900
|
-
var BLOCKED_TEXT_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
6901
|
-
"text/css",
|
|
6902
|
-
"text/html",
|
|
6903
|
-
"text/javascript",
|
|
6904
|
-
"text/xml"
|
|
6905
|
-
]);
|
|
6906
|
-
function safeErrorType(error) {
|
|
6907
|
-
if (!(error instanceof Error)) return typeof error;
|
|
6908
|
-
const name = error.name.trim();
|
|
6909
|
-
return /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(name) ? name : "Error";
|
|
6910
|
-
}
|
|
6911
|
-
function modelAttachmentDescriptor(contentType) {
|
|
6912
|
-
const normalized = contentType.toLowerCase().split(";", 1)[0]?.trim() ?? "";
|
|
6913
|
-
if (MODEL_IMAGE_CONTENT_TYPES.has(normalized)) {
|
|
6914
|
-
return { kind: "image", contentType: normalized };
|
|
6915
|
-
}
|
|
6916
|
-
if (MODEL_FILE_CONTENT_TYPES.has(normalized) || normalized.startsWith("text/") && !BLOCKED_TEXT_CONTENT_TYPES.has(normalized)) {
|
|
6917
|
-
return { kind: "file", contentType: normalized };
|
|
6918
|
-
}
|
|
6919
|
-
return null;
|
|
6920
|
-
}
|
|
6921
|
-
async function modelAttachmentContentForFiles(files, readFileBytes) {
|
|
6922
|
-
const selected = [];
|
|
6923
|
-
let remainingBytes = MAX_INLINE_MODEL_ATTACHMENT_BYTES;
|
|
6924
|
-
for (const file of files) {
|
|
6925
|
-
const descriptor = modelAttachmentDescriptor(file.contentType);
|
|
6926
|
-
const checksum = file.sha256?.trim().toLowerCase() ?? "";
|
|
6927
|
-
if (file.status !== "ready" || !descriptor || descriptor.kind !== "image" || file.sizeBytes > remainingBytes || !/^[a-f0-9]{64}$/.test(checksum)) {
|
|
6928
|
-
continue;
|
|
6929
|
-
}
|
|
6930
|
-
selected.push({ file, descriptor, checksum });
|
|
6931
|
-
remainingBytes -= file.sizeBytes;
|
|
6932
|
-
}
|
|
6933
|
-
const attachments = new Array(selected.length);
|
|
6934
|
-
let cursor = 0;
|
|
6935
|
-
const worker = async () => {
|
|
6936
|
-
while (cursor < selected.length) {
|
|
6937
|
-
const index = cursor++;
|
|
6938
|
-
const { file, descriptor, checksum } = selected[index];
|
|
6939
|
-
try {
|
|
6940
|
-
const bytes = await readFileBytes(file);
|
|
6941
|
-
if (bytes.byteLength !== file.sizeBytes) {
|
|
6942
|
-
console.error("model attachment bytes did not match finalized metadata", {
|
|
6943
|
-
fileId: file.id,
|
|
6944
|
-
expectedSizeBytes: file.sizeBytes,
|
|
6945
|
-
actualSizeBytes: bytes.byteLength
|
|
6946
|
-
});
|
|
6947
|
-
continue;
|
|
6948
|
-
}
|
|
6949
|
-
if (createHash8("sha256").update(bytes).digest("hex") !== checksum) {
|
|
6950
|
-
console.error("model attachment checksum did not match finalized metadata", {
|
|
6951
|
-
fileId: file.id
|
|
6952
|
-
});
|
|
6953
|
-
continue;
|
|
6954
|
-
}
|
|
6955
|
-
attachments[index] = {
|
|
6956
|
-
kind: descriptor.kind,
|
|
6957
|
-
fileId: file.id,
|
|
6958
|
-
filename: file.safeFilename,
|
|
6959
|
-
contentType: descriptor.contentType,
|
|
6960
|
-
dataUrl: `data:${descriptor.contentType};base64,${Buffer.from(bytes).toString("base64")}`
|
|
6961
|
-
};
|
|
6962
|
-
} catch (error) {
|
|
6963
|
-
console.error("model attachment content read failed; retaining sandbox path fallback", {
|
|
6964
|
-
fileId: file.id,
|
|
6965
|
-
errorType: safeErrorType(error)
|
|
6966
|
-
});
|
|
6967
|
-
}
|
|
6968
|
-
}
|
|
6969
|
-
};
|
|
6970
|
-
await Promise.all(
|
|
6971
|
-
Array.from({ length: Math.min(8, selected.length) }, async () => await worker())
|
|
6972
|
-
);
|
|
6973
|
-
return attachments.filter(
|
|
6974
|
-
(attachment) => attachment !== void 0
|
|
6975
|
-
);
|
|
6976
|
-
}
|
|
6977
|
-
function attachmentRefsFromItem(item) {
|
|
6978
|
-
const raw = item[MODEL_ATTACHMENT_REFS_FIELD];
|
|
6979
|
-
if (!Array.isArray(raw)) return [];
|
|
6980
|
-
const refs = [];
|
|
6981
|
-
for (const candidate of raw) {
|
|
6982
|
-
const parsed = FileResourceRef.safeParse(candidate);
|
|
6983
|
-
if (parsed.success) refs.push(parsed.data);
|
|
6984
|
-
}
|
|
6985
|
-
return refs;
|
|
6986
|
-
}
|
|
6987
|
-
function attachmentReceiptText(ref, file) {
|
|
6988
|
-
if (!file) {
|
|
6989
|
-
return `[Earlier attachment: fileId=${ref.fileId}; mountDirectory=${resourceMountPath2(ref)}. Use the existing file there, or call files__files_get_download_url with this fileId and download it with the shell.]`;
|
|
6990
|
-
}
|
|
6991
|
-
const path = sandboxFilePath(ref, file);
|
|
6992
|
-
return `[Attachment: ${file.safeFilename}; fileId=${file.id}; type=${file.contentType}; bytes=${file.sizeBytes}; path=${path}. If the local path is absent, call files__files_get_download_url with this fileId and download it with the shell.]`;
|
|
6993
|
-
}
|
|
6994
|
-
function createModelHistoryAttachmentProjector(policy, readFileBytes) {
|
|
6995
|
-
const contentById = /* @__PURE__ */ new Map();
|
|
6996
|
-
const attemptedContentIds = /* @__PURE__ */ new Set();
|
|
6997
|
-
return async (items, options = {}) => {
|
|
6998
|
-
const currentFileById = new Map((options.inlineFiles ?? []).map((file) => [file.id, file]));
|
|
6999
|
-
const refsByIndex = /* @__PURE__ */ new Map();
|
|
7000
|
-
const orderedFileIds = [];
|
|
7001
|
-
const seenFileIds = /* @__PURE__ */ new Set();
|
|
7002
|
-
for (let index = 0; index < items.length; index += 1) {
|
|
7003
|
-
const refs = attachmentRefsFromItem(items[index]);
|
|
7004
|
-
if (refs.length === 0) continue;
|
|
7005
|
-
refsByIndex.set(index, refs);
|
|
7006
|
-
for (const ref of refs) {
|
|
7007
|
-
if (seenFileIds.has(ref.fileId)) continue;
|
|
7008
|
-
seenFileIds.add(ref.fileId);
|
|
7009
|
-
orderedFileIds.push(ref.fileId);
|
|
7010
|
-
}
|
|
7011
|
-
}
|
|
7012
|
-
if (refsByIndex.size === 0) return items;
|
|
7013
|
-
if (readFileBytes) {
|
|
7014
|
-
const readable = [...orderedFileIds].reverse().map((id) => currentFileById.get(id)).filter((file) => {
|
|
7015
|
-
if (!file || attemptedContentIds.has(file.id)) return false;
|
|
7016
|
-
const descriptor = modelAttachmentDescriptor(file.contentType);
|
|
7017
|
-
return Boolean(descriptor && descriptor.kind === "image" && policy.supportsImageInput);
|
|
7018
|
-
});
|
|
7019
|
-
for (const file of readable) attemptedContentIds.add(file.id);
|
|
7020
|
-
const content = await modelAttachmentContentForFiles(readable, readFileBytes);
|
|
7021
|
-
for (const attachment of content) contentById.set(attachment.fileId, attachment);
|
|
7022
|
-
}
|
|
7023
|
-
const projected = [...items];
|
|
7024
|
-
for (const [index, refs] of refsByIndex) {
|
|
7025
|
-
const original = items[index];
|
|
7026
|
-
const existingContent = Array.isArray(original.content) ? [...original.content] : [{ type: "input_text", text: String(original.content ?? "") }];
|
|
7027
|
-
const attachmentParts = refs.flatMap((ref) => {
|
|
7028
|
-
const currentFile = currentFileById.get(ref.fileId);
|
|
7029
|
-
const attachment = currentFile ? contentById.get(ref.fileId) : void 0;
|
|
7030
|
-
const receipt = {
|
|
7031
|
-
type: "input_text",
|
|
7032
|
-
text: attachmentReceiptText(ref, currentFile)
|
|
7033
|
-
};
|
|
7034
|
-
if (!attachment || attachment.kind !== "image") {
|
|
7035
|
-
return [receipt];
|
|
7036
|
-
}
|
|
7037
|
-
return [receipt, { type: "input_image", image: attachment.dataUrl }];
|
|
7038
|
-
});
|
|
7039
|
-
const clone = {
|
|
7040
|
-
...original,
|
|
7041
|
-
content: [...existingContent, ...attachmentParts]
|
|
7042
|
-
};
|
|
7043
|
-
delete clone[MODEL_ATTACHMENT_REFS_FIELD];
|
|
7044
|
-
projected[index] = clone;
|
|
7045
|
-
}
|
|
7046
|
-
return projected;
|
|
7047
|
-
};
|
|
7048
|
-
}
|
|
7049
|
-
function withCurrentUserAttachmentRefs(historyItems, refs) {
|
|
7050
|
-
if (refs.length === 0) return historyItems;
|
|
7051
|
-
for (let index = historyItems.length - 1; index >= 0; index -= 1) {
|
|
7052
|
-
const item = historyItems[index];
|
|
7053
|
-
if (item.type !== "message" || item.role !== "user") continue;
|
|
7054
|
-
const existing = attachmentRefsFromItem(item);
|
|
7055
|
-
const existingIds = new Set(existing.map((ref) => ref.fileId));
|
|
7056
|
-
const additions = refs.filter((ref) => !existingIds.has(ref.fileId));
|
|
7057
|
-
if (additions.length === 0) return historyItems;
|
|
7058
|
-
const projected = [...historyItems];
|
|
7059
|
-
projected[index] = { ...item, [MODEL_ATTACHMENT_REFS_FIELD]: [...existing, ...additions] };
|
|
7060
|
-
return projected;
|
|
7061
|
-
}
|
|
7062
|
-
return historyItems;
|
|
7063
|
-
}
|
|
7064
|
-
async function turnInput(db, runtime, agent, trigger, options) {
|
|
7065
|
-
if (!trigger) {
|
|
7066
|
-
throw new Error("Missing trigger event");
|
|
7067
|
-
}
|
|
7068
|
-
const updates = await measureHistoryPreparationPhase(
|
|
7069
|
-
options,
|
|
7070
|
-
"system_update_load",
|
|
7071
|
-
async () => await listSessionSystemUpdatesForTurn(
|
|
7072
|
-
db,
|
|
7073
|
-
trigger.workspaceId,
|
|
7074
|
-
trigger.sessionId,
|
|
7075
|
-
options.turnId
|
|
7076
|
-
)
|
|
7077
|
-
);
|
|
7078
|
-
if (updates.some((update) => !update.deliveredHistoryItemId)) {
|
|
7079
|
-
throw new Error("Delivered internal update has no durable model-memory batch");
|
|
7080
|
-
}
|
|
7081
|
-
const internalContext = joinInternalContext(
|
|
7082
|
-
options.recovering ? [
|
|
7083
|
-
"[OpenGeni inference recovery]",
|
|
7084
|
-
"Continue the same inference from durable conversation and sandbox state. A previous execution stopped before it could finish. Do not repeat completed side effects; inspect actual state when uncertain."
|
|
7085
|
-
].join("\n") : void 0,
|
|
7086
|
-
options.unavailableSandboxFilesNote,
|
|
7087
|
-
options.runCredentialsNote,
|
|
7088
|
-
options.mcpAvailabilityNote
|
|
7089
|
-
);
|
|
7090
|
-
if (trigger.type === "user.message") {
|
|
7091
|
-
const payload = trigger.payload;
|
|
7092
|
-
const hasAnnotations = Array.isArray(payload.annotations) && payload.annotations.length > 0;
|
|
7093
|
-
if (typeof payload.text !== "string" || payload.text.trim().length === 0 && !hasAnnotations) {
|
|
7094
|
-
throw new Error("user.message payload is missing text and annotations");
|
|
7095
|
-
}
|
|
7096
|
-
const resources = Array.isArray(payload.resources) ? payload.resources : [];
|
|
7097
|
-
const fileAttachments = await measureHistoryPreparationPhase(
|
|
7098
|
-
options,
|
|
7099
|
-
"current_attachment_resolution",
|
|
7100
|
-
async () => await resolveUserMessageFileAttachments(
|
|
7101
|
-
db,
|
|
7102
|
-
options.fileAuthority.accountId,
|
|
7103
|
-
trigger.workspaceId,
|
|
7104
|
-
options.fileAuthority.subjectId,
|
|
7105
|
-
resources
|
|
7106
|
-
)
|
|
7107
|
-
);
|
|
7108
|
-
const attachmentContext = userMessageAttachmentsContext(fileAttachments);
|
|
7109
|
-
return await messageInput(
|
|
7110
|
-
db,
|
|
7111
|
-
runtime,
|
|
7112
|
-
agent,
|
|
7113
|
-
trigger,
|
|
7114
|
-
void 0,
|
|
7115
|
-
joinInternalContext(internalContext, attachmentContext),
|
|
7116
|
-
fileAttachments,
|
|
7117
|
-
options.providerApi,
|
|
7118
|
-
options.projectCanonicalHistory,
|
|
7119
|
-
options.materializeModelHistory,
|
|
7120
|
-
options.projectModelHistory,
|
|
7121
|
-
options.loadActiveHistory,
|
|
7122
|
-
options
|
|
7123
|
-
);
|
|
7124
|
-
}
|
|
7125
|
-
if (trigger.type === "system.update.delivered") {
|
|
7126
|
-
if (updates.length === 0) {
|
|
7127
|
-
throw new Error("Internal update inference has no delivered updates");
|
|
7128
|
-
}
|
|
7129
|
-
return await messageInput(
|
|
7130
|
-
db,
|
|
7131
|
-
runtime,
|
|
7132
|
-
agent,
|
|
7133
|
-
trigger,
|
|
7134
|
-
void 0,
|
|
7135
|
-
internalContext,
|
|
7136
|
-
[],
|
|
7137
|
-
options.providerApi,
|
|
7138
|
-
options.projectCanonicalHistory,
|
|
7139
|
-
options.materializeModelHistory,
|
|
7140
|
-
options.projectModelHistory,
|
|
7141
|
-
options.loadActiveHistory,
|
|
7142
|
-
options
|
|
7143
|
-
);
|
|
7144
|
-
}
|
|
7145
|
-
if (trigger.type === "user.approvalDecision" || trigger.type === "user.humanInputResponse") {
|
|
7146
|
-
return await openSuffixMessageInput(db, runtime, agent, trigger, internalContext, options);
|
|
7147
|
-
}
|
|
7148
|
-
throw new Error(`Unsupported trigger event type: ${trigger.type}`);
|
|
7149
|
-
}
|
|
7150
|
-
function joinInternalContext(...parts) {
|
|
7151
|
-
const content = parts.map((part) => part?.trim()).filter((part) => Boolean(part));
|
|
7152
|
-
return content.length > 0 ? content.join("\n\n") : void 0;
|
|
7153
|
-
}
|
|
7154
|
-
async function openSuffixMessageInput(db, runtime, agent, trigger, internalContext, options) {
|
|
7155
|
-
const suffixRows = await listTurnOpenSuffixToolCalls(
|
|
7156
|
-
db,
|
|
7157
|
-
trigger.workspaceId,
|
|
7158
|
-
trigger.sessionId,
|
|
7159
|
-
options.turnId
|
|
7160
|
-
);
|
|
7161
|
-
if (suffixRows.length === 0) {
|
|
7162
|
-
throw new Error("Open suffix resume has no interruption rows");
|
|
7163
|
-
}
|
|
7164
|
-
if (suffixRows.some((row) => row.resultItem == null)) {
|
|
7165
|
-
throw new Error("Open suffix resume still has unresolved members");
|
|
7166
|
-
}
|
|
7167
|
-
return await messageInput(
|
|
7168
|
-
db,
|
|
7169
|
-
runtime,
|
|
7170
|
-
agent,
|
|
7171
|
-
trigger,
|
|
7172
|
-
void 0,
|
|
7173
|
-
internalContext,
|
|
7174
|
-
[],
|
|
7175
|
-
options.providerApi,
|
|
7176
|
-
options.projectCanonicalHistory,
|
|
7177
|
-
options.materializeModelHistory,
|
|
7178
|
-
options.projectModelHistory,
|
|
7179
|
-
options.loadActiveHistory,
|
|
7180
|
-
options
|
|
7181
|
-
);
|
|
7182
|
-
}
|
|
7183
|
-
async function messageInput(db, runtime, agent, trigger, text, internalContext, currentAttachments = [], providerApi = "responses", projectCanonicalHistory, materializeModelHistory, projectModelHistory, loadActiveHistory = getActiveSessionHistoryItemsPaged2, preparationOptions = {}) {
|
|
7184
|
-
const currentAttachmentRefs = currentAttachments.map((attachment) => attachment.resource);
|
|
7185
|
-
const [stored, envelope] = await Promise.all([
|
|
7186
|
-
measureHistoryPreparationPhase(
|
|
7187
|
-
preparationOptions,
|
|
7188
|
-
"durable_history_load",
|
|
7189
|
-
async () => loadActiveHistory(db, trigger.workspaceId, trigger.sessionId)
|
|
7190
|
-
),
|
|
7191
|
-
measureHistoryPreparationPhase(
|
|
7192
|
-
preparationOptions,
|
|
7193
|
-
"sandbox_envelope_load",
|
|
7194
|
-
async () => getSandboxSessionEnvelope(db, trigger.workspaceId, trigger.sessionId)
|
|
7195
|
-
)
|
|
7196
|
-
]);
|
|
7197
|
-
const canonicalView = await measureHistoryPreparationPhase(
|
|
7198
|
-
preparationOptions,
|
|
7199
|
-
"canonical_projection",
|
|
7200
|
-
async () => {
|
|
7201
|
-
const active = projectRejectedProviderArtifacts(stored);
|
|
7202
|
-
return projectCanonicalHistory ? await projectCanonicalHistory(active) : active;
|
|
7203
|
-
}
|
|
7204
|
-
);
|
|
7205
|
-
const providerView = await measureHistoryPreparationPhase(
|
|
7206
|
-
preparationOptions,
|
|
7207
|
-
"provider_projection",
|
|
7208
|
-
() => projectHistoryForProvider(canonicalView, providerApi)
|
|
7209
|
-
);
|
|
7210
|
-
const referencedHistory = await measureHistoryPreparationPhase(
|
|
7211
|
-
preparationOptions,
|
|
7212
|
-
"attachment_ref_projection",
|
|
7213
|
-
() => withCurrentUserAttachmentRefs(providerView, currentAttachmentRefs)
|
|
7214
|
-
);
|
|
7215
|
-
const materializedHistory = await measureHistoryPreparationPhase(
|
|
7216
|
-
preparationOptions,
|
|
7217
|
-
"screenshot_materialization",
|
|
7218
|
-
async () => materializeModelHistory ? await materializeModelHistory(referencedHistory) : referencedHistory
|
|
7219
|
-
);
|
|
7220
|
-
const historyItems = await measureHistoryPreparationPhase(
|
|
7221
|
-
preparationOptions,
|
|
7222
|
-
"model_attachment_projection",
|
|
7223
|
-
async () => projectModelHistory ? await projectModelHistory(materializedHistory, {
|
|
7224
|
-
inlineFiles: currentAttachments.map((attachment) => attachment.file)
|
|
7225
|
-
}) : materializedHistory
|
|
7226
|
-
);
|
|
7227
|
-
const prepared = await measureHistoryPreparationPhase(
|
|
7228
|
-
preparationOptions,
|
|
7229
|
-
"runtime_input_assembly",
|
|
7230
|
-
async () => await runtime.prepareInput(agent, {
|
|
7231
|
-
kind: "message",
|
|
7232
|
-
...text ? { text } : {},
|
|
7233
|
-
...internalContext ? { internalContext } : {},
|
|
7234
|
-
historyItems,
|
|
7235
|
-
sandboxEnvelope: envelope,
|
|
7236
|
-
...projectModelHistory ? { modelInputAlreadyProjected: true } : {}
|
|
7237
|
-
})
|
|
7238
|
-
);
|
|
7239
|
-
const providerArtifactCandidates = await measureHistoryPreparationPhase(
|
|
7240
|
-
preparationOptions,
|
|
7241
|
-
"artifact_candidate_scan",
|
|
7242
|
-
() => {
|
|
7243
|
-
const preparedItems = Array.isArray(prepared.input) ? new Set(prepared.input) : /* @__PURE__ */ new Set();
|
|
7244
|
-
return {
|
|
7245
|
-
knownHistoryItemIds: stored.map((row) => row.id),
|
|
7246
|
-
historyItemIds: stored.filter(
|
|
7247
|
-
(row) => row.providerArtifactInvalidatedAt === null && hasOpaqueProviderArtifact(row.item) && preparedItems.has(row.item)
|
|
7248
|
-
).map((row) => row.id)
|
|
7249
|
-
};
|
|
7250
|
-
}
|
|
7251
|
-
);
|
|
7252
|
-
return {
|
|
7253
|
-
input: prepared,
|
|
7254
|
-
persistedHistoryCount: prepared.persistedHistoryCount,
|
|
7255
|
-
providerArtifactCandidates
|
|
7256
|
-
};
|
|
7257
|
-
}
|
|
7258
|
-
async function resolveUserMessageFileAttachments(db, accountId, workspaceId, subjectId, resources) {
|
|
7259
|
-
const fileResources = resources.filter(
|
|
7260
|
-
(resource) => resource.kind === "file"
|
|
7261
|
-
);
|
|
7262
|
-
if (fileResources.length === 0) return [];
|
|
7263
|
-
const files = await getFilesForSubject2(db, {
|
|
7264
|
-
accountId,
|
|
7265
|
-
workspaceId,
|
|
7266
|
-
subjectId,
|
|
7267
|
-
fileIds: fileResources.map((resource) => resource.fileId)
|
|
7268
|
-
});
|
|
7269
|
-
const fileById = new Map(files.map((file) => [file.id, file]));
|
|
7270
|
-
return fileResources.map((resource) => {
|
|
7271
|
-
const file = fileById.get(resource.fileId);
|
|
7272
|
-
if (!file) throw new Error(`File not found: ${resource.fileId}`);
|
|
7273
|
-
return { resource, file };
|
|
7274
|
-
});
|
|
7275
|
-
}
|
|
7276
|
-
function userMessageAttachmentsContext(attachments) {
|
|
7277
|
-
const attachedFiles = attachments.map(
|
|
7278
|
-
({ resource, file }) => `- ${file.filename} (${file.contentType}, ${file.sizeBytes} bytes): ${sandboxFilePath(resource, file)}`
|
|
7279
|
-
);
|
|
7280
|
-
if (attachedFiles.length === 0) {
|
|
7281
|
-
return void 0;
|
|
7282
|
-
}
|
|
7283
|
-
return ["Attached files are available in the sandbox:", ...attachedFiles].join("\n");
|
|
7284
|
-
}
|
|
7285
|
-
function sandboxFilePath(resource, file) {
|
|
7286
|
-
return `${resourceMountPath2(resource)}/${file.safeFilename}`;
|
|
7287
|
-
}
|
|
7288
|
-
|
|
7289
|
-
// src/activities/context-compaction.ts
|
|
7290
6842
|
async function maybeCompactContext(db, settings, scope, lastInputTokens, summarize = (s, m) => summarizeForCompaction(s, m, {
|
|
7291
6843
|
maxOutputTokens: SUMMARY_BUFFER_TOKENS
|
|
7292
6844
|
}), options = {}) {
|
|
@@ -7307,7 +6859,7 @@ async function maybeCompactContext(db, settings, scope, lastInputTokens, summari
|
|
|
7307
6859
|
};
|
|
7308
6860
|
}
|
|
7309
6861
|
}
|
|
7310
|
-
const active = await
|
|
6862
|
+
const active = await getActiveSessionHistoryItemsPaged2(db, scope.workspaceId, scope.sessionId);
|
|
7311
6863
|
if (active.length === 0) {
|
|
7312
6864
|
let requestConsumed = false;
|
|
7313
6865
|
if (options.clearRequestedCompaction) {
|
|
@@ -7460,7 +7012,12 @@ async function compactContextRemoteV2(db, settings, scope, canonicalItems, items
|
|
|
7460
7012
|
rewrittenToolOutputs = retry.rewrittenToolOutputs;
|
|
7461
7013
|
compactionItem = await options.requestRemoteCompactionV2(settings, retry.input);
|
|
7462
7014
|
}
|
|
7463
|
-
const
|
|
7015
|
+
const retainedTokens = await retentionTokenCounts(canonicalItems, projectForWire);
|
|
7016
|
+
const replacementHistory = buildRemoteV2ReplacementHistory(
|
|
7017
|
+
canonicalItems,
|
|
7018
|
+
compactionItem,
|
|
7019
|
+
(item) => retainedTokens.get(item) ?? estimateTokens([item])
|
|
7020
|
+
);
|
|
7464
7021
|
const estimatedTokensAfter = estimateTokens(await projectForWire(replacementHistory));
|
|
7465
7022
|
const replacementFingerprint = compactionReplacementFingerprint(replacementHistory);
|
|
7466
7023
|
const tailItem = replacementHistory.at(-1);
|
|
@@ -7510,7 +7067,12 @@ async function compactContextPortable(db, settings, scope, canonicalItems, items
|
|
|
7510
7067
|
const estimatedTokensBefore = estimateTokens(items);
|
|
7511
7068
|
const summarized = await summarizeWithCodexOverflowTrimming(summarize, settings, items);
|
|
7512
7069
|
const summaryBody = summarized.summaryBody;
|
|
7513
|
-
const
|
|
7070
|
+
const retainedTokens = await retentionTokenCounts(canonicalItems, projectForWire);
|
|
7071
|
+
const replacementHistory = buildCompactionReplacementHistory(
|
|
7072
|
+
canonicalItems,
|
|
7073
|
+
summaryBody,
|
|
7074
|
+
(item) => retainedTokens.get(item) ?? estimateTokens([item])
|
|
7075
|
+
);
|
|
7514
7076
|
const estimatedTokensAfter = estimateTokens(await projectForWire(replacementHistory));
|
|
7515
7077
|
const replacementFingerprint = compactionReplacementFingerprint(replacementHistory);
|
|
7516
7078
|
const previousReplacementFingerprint = latestCompactionReplacementFingerprint(canonicalItems);
|
|
@@ -7609,6 +7171,15 @@ function isExactContextLengthExceeded(error, seen = /* @__PURE__ */ new WeakSet(
|
|
|
7609
7171
|
}
|
|
7610
7172
|
return isExactContextLengthExceeded(record5.cause, seen) || isExactContextLengthExceeded(record5.error, seen) || isExactContextLengthExceeded(record5.diagnostics, seen);
|
|
7611
7173
|
}
|
|
7174
|
+
async function retentionTokenCounts(items, project) {
|
|
7175
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7176
|
+
for (const item of items) {
|
|
7177
|
+
if (item.role === "user" || item.role === "developer") {
|
|
7178
|
+
counts.set(item, estimateTokens(await project([item])));
|
|
7179
|
+
}
|
|
7180
|
+
}
|
|
7181
|
+
return counts;
|
|
7182
|
+
}
|
|
7612
7183
|
|
|
7613
7184
|
// src/activities/open-suffix-resume.ts
|
|
7614
7185
|
import {
|
|
@@ -7619,7 +7190,7 @@ import {
|
|
|
7619
7190
|
appendSessionHistoryItems as appendSessionHistoryItems2,
|
|
7620
7191
|
getActiveSessionHistoryItems,
|
|
7621
7192
|
interruptedToolCallResult,
|
|
7622
|
-
listTurnOpenSuffixToolCalls
|
|
7193
|
+
listTurnOpenSuffixToolCalls,
|
|
7623
7194
|
nextSessionHistoryPosition,
|
|
7624
7195
|
recordPendingSessionToolCallResult
|
|
7625
7196
|
} from "@opengeni/db";
|
|
@@ -7770,7 +7341,7 @@ async function settleOpenSuffixResumeIfNeeded(input) {
|
|
|
7770
7341
|
if (input.trigger.type !== "user.approvalDecision" && input.trigger.type !== "user.humanInputResponse") {
|
|
7771
7342
|
return { action: "continue" };
|
|
7772
7343
|
}
|
|
7773
|
-
const rows = await
|
|
7344
|
+
const rows = await listTurnOpenSuffixToolCalls(
|
|
7774
7345
|
input.db,
|
|
7775
7346
|
input.workspaceId,
|
|
7776
7347
|
input.sessionId,
|
|
@@ -7816,7 +7387,7 @@ async function settleOpenSuffixResumeIfNeeded(input) {
|
|
|
7816
7387
|
}
|
|
7817
7388
|
if (!recorded.recorded) {
|
|
7818
7389
|
const latest = resolveOpenSuffixResumeTarget(
|
|
7819
|
-
await
|
|
7390
|
+
await listTurnOpenSuffixToolCalls(
|
|
7820
7391
|
input.db,
|
|
7821
7392
|
input.workspaceId,
|
|
7822
7393
|
input.sessionId,
|
|
@@ -7868,7 +7439,7 @@ async function settleOpenSuffixResumeIfNeeded(input) {
|
|
|
7868
7439
|
return { action: "cancelled" };
|
|
7869
7440
|
}
|
|
7870
7441
|
}
|
|
7871
|
-
const remaining = (await
|
|
7442
|
+
const remaining = (await listTurnOpenSuffixToolCalls(input.db, input.workspaceId, input.sessionId, input.turnId)).filter((row) => row.resultItem == null);
|
|
7872
7443
|
if (remaining.length === 0) {
|
|
7873
7444
|
return { action: "continue" };
|
|
7874
7445
|
}
|
|
@@ -9577,7 +9148,7 @@ async function runTurnStreamAttempt(deps) {
|
|
|
9577
9148
|
import {
|
|
9578
9149
|
applySessionTurnSettlement,
|
|
9579
9150
|
claimSessionWorkForAttempt,
|
|
9580
|
-
getSessionEvent as
|
|
9151
|
+
getSessionEvent as getSessionEvent2,
|
|
9581
9152
|
getHumanInputResumeForEvent as getHumanInputResumeForEvent2,
|
|
9582
9153
|
getInteractionInterventionResumeForEvent,
|
|
9583
9154
|
installOrReadTurnExecutionPolicyForAttempt,
|
|
@@ -9934,7 +9505,7 @@ async function claimTurnAttempt(deps) {
|
|
|
9934
9505
|
billingState.countsTowardTokenCap = billingIdentity.countsTowardTokenCap;
|
|
9935
9506
|
billingState.isCodexTurn = billingIdentity.codexSubscription;
|
|
9936
9507
|
billingState.isXaiTurn = billingIdentity.xaiSubscription;
|
|
9937
|
-
const trigger = await
|
|
9508
|
+
const trigger = await getSessionEvent2(db, input.workspaceId, attempt.triggerEventId);
|
|
9938
9509
|
if (!trigger) {
|
|
9939
9510
|
throw new Error(`Trigger event not found: ${attempt.triggerEventId}`);
|
|
9940
9511
|
}
|
|
@@ -10990,10 +10561,11 @@ async function selectCodexTurnCapacity(deps) {
|
|
|
10990
10561
|
import {
|
|
10991
10562
|
materializeRigVersionForAttempt,
|
|
10992
10563
|
getWorkspaceModelPolicy,
|
|
10564
|
+
getFilesForSubject as getFilesForSubject2,
|
|
10993
10565
|
getWorkspace as getWorkspace2,
|
|
10994
10566
|
resolveCompanyBrainContextSelection,
|
|
10995
10567
|
getGeneratedVideoArtifact,
|
|
10996
|
-
listSessionSystemUpdatesForTurn
|
|
10568
|
+
listSessionSystemUpdatesForTurn,
|
|
10997
10569
|
getOrCreateCompanyProfileSnapshot,
|
|
10998
10570
|
getOrCreatePreferenceRegistrySnapshot,
|
|
10999
10571
|
getOrCreateWorkspaceInstructionPolicySnapshot,
|
|
@@ -11001,7 +10573,7 @@ import {
|
|
|
11001
10573
|
resolveSessionAttemptPersonalResources
|
|
11002
10574
|
} from "@opengeni/db";
|
|
11003
10575
|
import {
|
|
11004
|
-
projectHistoryForProvider
|
|
10576
|
+
projectHistoryForProvider,
|
|
11005
10577
|
restoreGenericDispatchHistoryItems,
|
|
11006
10578
|
projectModelInputForCapabilities,
|
|
11007
10579
|
hasActiveWorkspaceInstructionPolicy,
|
|
@@ -11034,7 +10606,7 @@ import {
|
|
|
11034
10606
|
prepareImageGenerationOperation,
|
|
11035
10607
|
resetImageGenerationOperationBeforeProviderDispatch
|
|
11036
10608
|
} from "@opengeni/db";
|
|
11037
|
-
import { createHash as
|
|
10609
|
+
import { createHash as createHash8 } from "crypto";
|
|
11038
10610
|
var ImageGenerationOutcomeUnknownError = class extends Error {
|
|
11039
10611
|
constructor(operationId) {
|
|
11040
10612
|
super(
|
|
@@ -11247,7 +10819,7 @@ async function recoverCompletedImage(input, identity) {
|
|
|
11247
10819
|
return retainedGeneratedImageFromArtifact(recovered).receipt;
|
|
11248
10820
|
}
|
|
11249
10821
|
function digest(prefix, ...values) {
|
|
11250
|
-
const hash =
|
|
10822
|
+
const hash = createHash8("sha256").update(prefix);
|
|
11251
10823
|
for (const value of values) hash.update(value).update("\0");
|
|
11252
10824
|
return hash.digest("hex");
|
|
11253
10825
|
}
|
|
@@ -11358,13 +10930,11 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11358
10930
|
};
|
|
11359
10931
|
const [
|
|
11360
10932
|
packRuntime,
|
|
11361
|
-
installedSkillRuntime,
|
|
11362
10933
|
rigMaterialization,
|
|
11363
10934
|
[workspace, companyProfileSnapshot, instructionPolicySnapshot, preferenceSnapshot],
|
|
11364
10935
|
workspaceModelPolicy
|
|
11365
10936
|
] = await Promise.all([
|
|
11366
10937
|
resolveWorkspacePackRuntime(db, input.workspaceId),
|
|
11367
|
-
resolveWorkspaceInstalledSkillRuntime(db, input.workspaceId),
|
|
11368
10938
|
session.rigId && session.rigVersionId ? (async () => await materializeRigVersionForAttempt(db, {
|
|
11369
10939
|
accountId: input.accountId,
|
|
11370
10940
|
workspaceId: input.workspaceId,
|
|
@@ -11403,12 +10973,13 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11403
10973
|
preferences: preferenceSnapshot
|
|
11404
10974
|
},
|
|
11405
10975
|
{
|
|
11406
|
-
includeCompanyProfile: companyProfileIncluded
|
|
10976
|
+
includeCompanyProfile: companyProfileIncluded,
|
|
10977
|
+
sharedSkillReader: true
|
|
11407
10978
|
}
|
|
11408
10979
|
);
|
|
11409
10980
|
const structuredWorkspacePolicyActive = hasActiveWorkspaceInstructionPolicy(instructionPolicySnapshot);
|
|
11410
10981
|
const workspaceMemory = contextSelection.workspaceMemory;
|
|
11411
|
-
const buildCompanyBrainContributionReceiptFor = (
|
|
10982
|
+
const buildCompanyBrainContributionReceiptFor = (skillCatalogText) => buildCompanyBrainContributionReceipt({
|
|
11412
10983
|
contextSelectionReceiptId: contextSelection.receipt.id,
|
|
11413
10984
|
attemptId: input.attemptId,
|
|
11414
10985
|
turnId: turn.id,
|
|
@@ -11420,11 +10991,12 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11420
10991
|
companyProfile: companyProfileSnapshot,
|
|
11421
10992
|
companyProfileIncluded,
|
|
11422
10993
|
workspaceMemory,
|
|
11423
|
-
skillActivations
|
|
10994
|
+
skillActivations: [],
|
|
10995
|
+
skillCatalogText
|
|
11424
10996
|
});
|
|
11425
10997
|
try {
|
|
11426
10998
|
eventing.companyBrainContextContributions = summarizeCompanyBrainContributions(
|
|
11427
|
-
buildCompanyBrainContributionReceiptFor(
|
|
10999
|
+
buildCompanyBrainContributionReceiptFor("")
|
|
11428
11000
|
);
|
|
11429
11001
|
} catch {
|
|
11430
11002
|
}
|
|
@@ -11475,7 +11047,13 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11475
11047
|
);
|
|
11476
11048
|
if (!object) throw new Error("attachment object is missing");
|
|
11477
11049
|
return object.bytes;
|
|
11478
|
-
} : void 0
|
|
11050
|
+
} : void 0,
|
|
11051
|
+
(fileIds) => getFilesForSubject2(db, {
|
|
11052
|
+
accountId: input.accountId,
|
|
11053
|
+
workspaceId: input.workspaceId,
|
|
11054
|
+
subjectId: fileAuthoritySubjectId,
|
|
11055
|
+
fileIds
|
|
11056
|
+
})
|
|
11479
11057
|
);
|
|
11480
11058
|
const modelHistoryProjector = async (items, projectionOptions) => projectModelInputForCapabilities(
|
|
11481
11059
|
await attachmentProjector(items, projectionOptions),
|
|
@@ -11486,7 +11064,7 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11486
11064
|
return projectGeneratedImageHistoryForModel(items);
|
|
11487
11065
|
};
|
|
11488
11066
|
const compactionModelHistoryProjector = async (items) => await modelHistoryProjector(
|
|
11489
|
-
|
|
11067
|
+
projectHistoryForProvider(
|
|
11490
11068
|
await generatedImageHistoryProjector(restoreGenericDispatchHistoryItems(items)),
|
|
11491
11069
|
providerApi
|
|
11492
11070
|
)
|
|
@@ -11507,7 +11085,7 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11507
11085
|
}
|
|
11508
11086
|
}
|
|
11509
11087
|
}
|
|
11510
|
-
for (const update of await
|
|
11088
|
+
for (const update of await listSessionSystemUpdatesForTurn(
|
|
11511
11089
|
db,
|
|
11512
11090
|
input.workspaceId,
|
|
11513
11091
|
input.sessionId,
|
|
@@ -11537,7 +11115,6 @@ async function prepareGovernanceAndModel(deps) {
|
|
|
11537
11115
|
ok: {
|
|
11538
11116
|
runtimePreparationStartedAt,
|
|
11539
11117
|
packRuntime,
|
|
11540
|
-
installedSkillRuntime,
|
|
11541
11118
|
rigVersion,
|
|
11542
11119
|
rigName,
|
|
11543
11120
|
agentHumanInputEnabled,
|
|
@@ -14710,6 +14287,8 @@ async function prepareRunCredentials(deps) {
|
|
|
14710
14287
|
import { getWorkspaceConnectionModelRestrictions } from "@opengeni/db";
|
|
14711
14288
|
import {
|
|
14712
14289
|
beginConnectorActionExecution,
|
|
14290
|
+
getWorkspaceVideoGenerationPolicy,
|
|
14291
|
+
listSkillDescriptors as listSkillDescriptors2,
|
|
14713
14292
|
completeConnectorActionExecution,
|
|
14714
14293
|
getScheduledVariableSetExpectedGenerationForAttempt,
|
|
14715
14294
|
getWorkspaceModelPolicy as getWorkspaceModelPolicy2,
|
|
@@ -14734,7 +14313,7 @@ import {
|
|
|
14734
14313
|
} from "@opengeni/runtime";
|
|
14735
14314
|
|
|
14736
14315
|
// src/activities/google-drive-publication.ts
|
|
14737
|
-
import { createHash as
|
|
14316
|
+
import { createHash as createHash9 } from "crypto";
|
|
14738
14317
|
import {
|
|
14739
14318
|
GOOGLE_DRIVE_FILE_SCOPE,
|
|
14740
14319
|
GOOGLE_DRIVE_FULL_SCOPE,
|
|
@@ -14834,7 +14413,7 @@ function googleDrivePublicationConnectorCall(target, rawRequest, approvalId) {
|
|
|
14834
14413
|
sourceSha256: request.file.sha256
|
|
14835
14414
|
},
|
|
14836
14415
|
canonicalReceipt: { ...request.file },
|
|
14837
|
-
idempotencyKeyDigest:
|
|
14416
|
+
idempotencyKeyDigest: createHash9("sha256").update(request.idempotencyKey, "utf8").digest("hex")
|
|
14838
14417
|
}
|
|
14839
14418
|
};
|
|
14840
14419
|
}
|
|
@@ -15022,7 +14601,7 @@ async function executeGoogleDrivePublication(input, ports = defaultPorts) {
|
|
|
15022
14601
|
);
|
|
15023
14602
|
if (!object) throw new Error("Editable artifact export object is missing");
|
|
15024
14603
|
const bytes = object.bytes;
|
|
15025
|
-
if (bytes.byteLength !== request.file.sizeBytes ||
|
|
14604
|
+
if (bytes.byteLength !== request.file.sizeBytes || createHash9("sha256").update(bytes).digest("hex") !== request.file.sha256) {
|
|
15026
14605
|
throw new Error("Editable artifact export bytes failed verification");
|
|
15027
14606
|
}
|
|
15028
14607
|
const authorizedFetch = async (url, init) => {
|
|
@@ -15104,7 +14683,7 @@ function assertPublicationConnection(input, connection) {
|
|
|
15104
14683
|
}
|
|
15105
14684
|
}
|
|
15106
14685
|
function publicationActorReplicaId(identity) {
|
|
15107
|
-
const value =
|
|
14686
|
+
const value = createHash9("sha256").update(
|
|
15108
14687
|
`google-drive-publication:${identity.sessionId}:${identity.turnId}:${identity.attemptId}:${identity.executionGeneration}`,
|
|
15109
14688
|
"utf8"
|
|
15110
14689
|
).digest("hex").slice(0, 16);
|
|
@@ -15149,7 +14728,7 @@ function officeFormat(modality, contentType) {
|
|
|
15149
14728
|
return expected.format;
|
|
15150
14729
|
}
|
|
15151
14730
|
function deterministicUuid(seed) {
|
|
15152
|
-
const bytes =
|
|
14731
|
+
const bytes = createHash9("sha256").update(seed, "utf8").digest().subarray(0, 16);
|
|
15153
14732
|
bytes[6] = (bytes[6] ?? 0) & 15 | 80;
|
|
15154
14733
|
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
15155
14734
|
const hex = bytes.toString("hex");
|
|
@@ -15287,7 +14866,7 @@ function driveReceipt(input, file, replayed) {
|
|
|
15287
14866
|
});
|
|
15288
14867
|
}
|
|
15289
14868
|
function publicationOperationKey(input) {
|
|
15290
|
-
return
|
|
14869
|
+
return createHash9("sha256").update(
|
|
15291
14870
|
JSON.stringify({
|
|
15292
14871
|
workspaceId: input.workspaceId,
|
|
15293
14872
|
connectionId: input.connectionId,
|
|
@@ -15956,7 +15535,7 @@ function canWrite(permissions) {
|
|
|
15956
15535
|
}
|
|
15957
15536
|
|
|
15958
15537
|
// src/activities/connector-attachments.ts
|
|
15959
|
-
import { createHash as
|
|
15538
|
+
import { createHash as createHash10 } from "crypto";
|
|
15960
15539
|
import {
|
|
15961
15540
|
CONNECTOR_ATTACHMENT_RECEIPT_VERSION,
|
|
15962
15541
|
ConnectorAttachmentReceiptEnvelope
|
|
@@ -15976,7 +15555,7 @@ var ConnectorAttachmentMaterializationError = class extends Error {
|
|
|
15976
15555
|
}
|
|
15977
15556
|
};
|
|
15978
15557
|
function digestParts(...parts) {
|
|
15979
|
-
const hash =
|
|
15558
|
+
const hash = createHash10("sha256");
|
|
15980
15559
|
for (const part of parts) {
|
|
15981
15560
|
const bytes = Buffer.from(part, "utf8");
|
|
15982
15561
|
hash.update(String(bytes.byteLength));
|
|
@@ -16581,6 +16160,780 @@ function createListModelsAttemptToolDefinition(input) {
|
|
|
16581
16160
|
};
|
|
16582
16161
|
}
|
|
16583
16162
|
|
|
16163
|
+
// src/activities/agent-turn/skill-tools.ts
|
|
16164
|
+
import { createHash as createHash11 } from "crypto";
|
|
16165
|
+
import {
|
|
16166
|
+
skillReviewHumanInput
|
|
16167
|
+
} from "@opengeni/contracts";
|
|
16168
|
+
import {
|
|
16169
|
+
assertSkillReadAttempt,
|
|
16170
|
+
skillReviewResolution,
|
|
16171
|
+
installPortableSkill,
|
|
16172
|
+
replayPortableSkillInstall,
|
|
16173
|
+
listSkillDescriptors
|
|
16174
|
+
} from "@opengeni/db";
|
|
16175
|
+
import {
|
|
16176
|
+
createGitHubSkillSourceClient,
|
|
16177
|
+
createPublicSkillSearchClient,
|
|
16178
|
+
portableSkillCapabilityId,
|
|
16179
|
+
portableSkillPluginKey,
|
|
16180
|
+
readSkill,
|
|
16181
|
+
resolveSkillImport,
|
|
16182
|
+
saveSkill
|
|
16183
|
+
} from "@opengeni/core";
|
|
16184
|
+
import {
|
|
16185
|
+
buildPortableSkillArtifact as buildPortableSkillArtifact3,
|
|
16186
|
+
loadSkillLibrarySkill,
|
|
16187
|
+
skillLibraryRepositoryUrl
|
|
16188
|
+
} from "@opengeni/runtime/skill-library";
|
|
16189
|
+
|
|
16190
|
+
// src/activities/agent-turn/skill-read.ts
|
|
16191
|
+
import {
|
|
16192
|
+
assertSkillRelativePath,
|
|
16193
|
+
PORTABLE_SKILL_MAX_FILES,
|
|
16194
|
+
readSkillFiles,
|
|
16195
|
+
SKILL_READ_MAX_OUTPUT_BYTES,
|
|
16196
|
+
SKILL_READ_MAX_PATHS
|
|
16197
|
+
} from "@opengeni/runtime/skill-library";
|
|
16198
|
+
var SKILL_READ_TOOL_NAME = "skill_read";
|
|
16199
|
+
function createSkillReadAttemptToolDefinition(input) {
|
|
16200
|
+
return {
|
|
16201
|
+
identity: { serverId: "opengeni", toolName: SKILL_READ_TOOL_NAME },
|
|
16202
|
+
modelName: SKILL_READ_TOOL_NAME,
|
|
16203
|
+
codemodePath: ["opengeni", SKILL_READ_TOOL_NAME],
|
|
16204
|
+
title: "Read Skill files",
|
|
16205
|
+
description: "Read Skill text without starting a sandbox. Omit paths to read SKILL.md; provide relative paths to read exactly those files, never implicitly adding SKILL.md. Set listFiles:true without paths to list relative paths and available revision identity only, with no file bodies. Use an id or name from the Skill index or skill_search. Management tools are lazy; when listed, opengeni-skills explains how to use them.",
|
|
16206
|
+
inputSchema: {
|
|
16207
|
+
type: "object",
|
|
16208
|
+
properties: {
|
|
16209
|
+
skill: { type: "string", minLength: 1, maxLength: 512 },
|
|
16210
|
+
listFiles: { type: "boolean" },
|
|
16211
|
+
paths: {
|
|
16212
|
+
type: "array",
|
|
16213
|
+
minItems: 1,
|
|
16214
|
+
maxItems: SKILL_READ_MAX_PATHS,
|
|
16215
|
+
uniqueItems: true,
|
|
16216
|
+
items: { type: "string", minLength: 1, maxLength: 1024 }
|
|
16217
|
+
}
|
|
16218
|
+
},
|
|
16219
|
+
required: ["skill"],
|
|
16220
|
+
additionalProperties: false
|
|
16221
|
+
},
|
|
16222
|
+
annotations: {
|
|
16223
|
+
title: "Read Skill files",
|
|
16224
|
+
readOnlyHint: true,
|
|
16225
|
+
destructiveHint: false,
|
|
16226
|
+
idempotentHint: true,
|
|
16227
|
+
openWorldHint: false
|
|
16228
|
+
},
|
|
16229
|
+
source: "opengeni",
|
|
16230
|
+
approval: "none",
|
|
16231
|
+
execute: async (args) => {
|
|
16232
|
+
if (typeof args.skill !== "string" || !args.skill || args.listFiles !== void 0 && typeof args.listFiles !== "boolean" || args.paths !== void 0 && (!Array.isArray(args.paths) || args.paths.some((path) => typeof path !== "string"))) {
|
|
16233
|
+
throw new Error("skill_read requires a Skill identifier and optional relative paths.");
|
|
16234
|
+
}
|
|
16235
|
+
if (args.listFiles === true && args.paths !== void 0) {
|
|
16236
|
+
throw new Error("skill_read listFiles:true cannot be combined with paths.");
|
|
16237
|
+
}
|
|
16238
|
+
await input.authorize();
|
|
16239
|
+
const loaded = await input.load(args.skill);
|
|
16240
|
+
const metadata = "files" in loaded ? loaded : null;
|
|
16241
|
+
const files = metadata ? metadata.files : loaded;
|
|
16242
|
+
const selected = args.listFiles === true ? listSkillPaths(files) : readSkillFiles(files, args.paths);
|
|
16243
|
+
const output = {
|
|
16244
|
+
...metadata ? {
|
|
16245
|
+
skillId: metadata.skillId,
|
|
16246
|
+
revisionId: metadata.revisionId,
|
|
16247
|
+
scopeVersion: metadata.scopeVersion,
|
|
16248
|
+
...metadata.installationVersion !== void 0 ? { installationVersion: metadata.installationVersion } : {}
|
|
16249
|
+
} : {},
|
|
16250
|
+
...selected
|
|
16251
|
+
};
|
|
16252
|
+
return {
|
|
16253
|
+
isError: false,
|
|
16254
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
16255
|
+
structuredContent: output
|
|
16256
|
+
};
|
|
16257
|
+
}
|
|
16258
|
+
};
|
|
16259
|
+
}
|
|
16260
|
+
function listSkillPaths(files) {
|
|
16261
|
+
if (files.length > PORTABLE_SKILL_MAX_FILES) {
|
|
16262
|
+
throw new Error(`Skill inventory exceeds ${PORTABLE_SKILL_MAX_FILES} files.`);
|
|
16263
|
+
}
|
|
16264
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16265
|
+
for (const { path } of files) {
|
|
16266
|
+
assertSkillRelativePath(path);
|
|
16267
|
+
if (seen.has(path)) throw new Error(`Duplicate stored Skill path: ${path}`);
|
|
16268
|
+
seen.add(path);
|
|
16269
|
+
}
|
|
16270
|
+
const result = { paths: [...seen].sort() };
|
|
16271
|
+
if (Buffer.byteLength(JSON.stringify(result), "utf8") > SKILL_READ_MAX_OUTPUT_BYTES) {
|
|
16272
|
+
throw new Error("Skill inventory exceeds the read output limit.");
|
|
16273
|
+
}
|
|
16274
|
+
return result;
|
|
16275
|
+
}
|
|
16276
|
+
|
|
16277
|
+
// src/activities/agent-turn/skill-search.ts
|
|
16278
|
+
import { PublicSkillSearchError } from "@opengeni/core";
|
|
16279
|
+
import { listSkillLibraryEntries } from "@opengeni/runtime/skill-library";
|
|
16280
|
+
function createSkillSearchAttemptToolDefinition(input) {
|
|
16281
|
+
return {
|
|
16282
|
+
identity: { serverId: "opengeni", toolName: "skill_search" },
|
|
16283
|
+
modelName: "skill_search",
|
|
16284
|
+
codemodePath: ["opengeni", "skill_search"],
|
|
16285
|
+
title: "Search Skills",
|
|
16286
|
+
description: "Find installed workspace Skills or available curated and public Skills. Returns identifiers and install sources, not file contents. Search never installs or starts a sandbox. Scope defaults to all; use installed to avoid external search.",
|
|
16287
|
+
inputSchema: {
|
|
16288
|
+
type: "object",
|
|
16289
|
+
properties: {
|
|
16290
|
+
query: { type: "string", minLength: 2, maxLength: 200 },
|
|
16291
|
+
scope: { type: "string", enum: ["installed", "catalog", "all"] },
|
|
16292
|
+
limit: { type: "integer", minimum: 1, maximum: 20 }
|
|
16293
|
+
},
|
|
16294
|
+
required: ["query"],
|
|
16295
|
+
additionalProperties: false
|
|
16296
|
+
},
|
|
16297
|
+
annotations: {
|
|
16298
|
+
title: "Search Skills",
|
|
16299
|
+
readOnlyHint: true,
|
|
16300
|
+
destructiveHint: false,
|
|
16301
|
+
idempotentHint: true,
|
|
16302
|
+
openWorldHint: true
|
|
16303
|
+
},
|
|
16304
|
+
source: "opengeni",
|
|
16305
|
+
approval: "none",
|
|
16306
|
+
execute: async (args) => {
|
|
16307
|
+
await input.authorize();
|
|
16308
|
+
const query = String(args.query).trim();
|
|
16309
|
+
const scope = args.scope ?? "all";
|
|
16310
|
+
const limit = typeof args.limit === "number" ? args.limit : 20;
|
|
16311
|
+
const searchText = query.toLowerCase();
|
|
16312
|
+
const matches = (entry) => `${entry.name}
|
|
16313
|
+
${entry.description}`.toLowerCase().includes(searchText);
|
|
16314
|
+
const installed = scope === "catalog" ? [] : await input.listWorkspace();
|
|
16315
|
+
const workspaceHits = installed.filter(matches).slice(0, limit).map((entry) => ({
|
|
16316
|
+
...entry,
|
|
16317
|
+
source: entry.source ?? "workspace",
|
|
16318
|
+
installed: !entry.source || entry.source === "workspace"
|
|
16319
|
+
}));
|
|
16320
|
+
const libraryHits = scope === "installed" ? [] : listSkillLibraryEntries().filter(matches).slice(0, limit).map((entry) => ({
|
|
16321
|
+
id: `library:${entry.id}`,
|
|
16322
|
+
name: entry.name,
|
|
16323
|
+
description: entry.description,
|
|
16324
|
+
source: "library",
|
|
16325
|
+
libraryId: entry.id
|
|
16326
|
+
}));
|
|
16327
|
+
let publicResult = null;
|
|
16328
|
+
let publicError = null;
|
|
16329
|
+
if (scope !== "installed") {
|
|
16330
|
+
try {
|
|
16331
|
+
publicResult = await input.publicSearch.search({ query, limit });
|
|
16332
|
+
} catch (error) {
|
|
16333
|
+
if (!(error instanceof PublicSkillSearchError)) throw error;
|
|
16334
|
+
publicError = {
|
|
16335
|
+
source: "skills_sh",
|
|
16336
|
+
code: error.code,
|
|
16337
|
+
retryAfterSeconds: error.retryAfterSeconds
|
|
16338
|
+
};
|
|
16339
|
+
}
|
|
16340
|
+
}
|
|
16341
|
+
const output = {
|
|
16342
|
+
workspace: workspaceHits,
|
|
16343
|
+
library: libraryHits,
|
|
16344
|
+
public: publicResult?.items.map((entry) => ({ ...entry })) ?? [],
|
|
16345
|
+
// A provider outage is not an empty search. Keep local results useful
|
|
16346
|
+
// and expose partial failure explicitly, without leaking network details.
|
|
16347
|
+
partial: publicError !== null,
|
|
16348
|
+
errors: publicError ? [publicError] : []
|
|
16349
|
+
};
|
|
16350
|
+
return {
|
|
16351
|
+
isError: false,
|
|
16352
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
16353
|
+
structuredContent: output
|
|
16354
|
+
};
|
|
16355
|
+
}
|
|
16356
|
+
};
|
|
16357
|
+
}
|
|
16358
|
+
|
|
16359
|
+
// src/activities/agent-turn/skill-save.ts
|
|
16360
|
+
import {
|
|
16361
|
+
applySkillFileChanges,
|
|
16362
|
+
buildPortableSkillArtifact,
|
|
16363
|
+
PORTABLE_SKILL_MAX_FILES as PORTABLE_SKILL_MAX_FILES2
|
|
16364
|
+
} from "@opengeni/runtime/skill-library";
|
|
16365
|
+
function createSkillSaveAttemptToolDefinition(input) {
|
|
16366
|
+
return {
|
|
16367
|
+
identity: { serverId: "opengeni", toolName: "skill_save" },
|
|
16368
|
+
modelName: "skill_save",
|
|
16369
|
+
codemodePath: ["opengeni", "skill_save"],
|
|
16370
|
+
title: "Save Skill text",
|
|
16371
|
+
description: "Create or edit a workspace Skill without a sandbox. Supply only changed UTF-8 text files and explicit deletions; omitted files are preserved. Use the revision and scope version returned by Skill discovery for stale-write protection. For creation choose a new UUID, set expectedRevisionId to null and expectedScopeVersion to 1. Learning mode determines whether the change is live, pending approval, or refused. If humanInput is returned, call request_human_input verbatim, Save activates the exact reviewed revision as the answer is accepted. Do not ask for a second review or call a separate activation tool.",
|
|
16372
|
+
inputSchema: {
|
|
16373
|
+
type: "object",
|
|
16374
|
+
properties: {
|
|
16375
|
+
operationId: { type: "string", format: "uuid" },
|
|
16376
|
+
skillId: { type: "string", format: "uuid" },
|
|
16377
|
+
expectedRevisionId: { type: ["string", "null"], format: "uuid" },
|
|
16378
|
+
expectedScopeVersion: { type: "integer", minimum: 0 },
|
|
16379
|
+
files: {
|
|
16380
|
+
type: "array",
|
|
16381
|
+
maxItems: PORTABLE_SKILL_MAX_FILES2,
|
|
16382
|
+
items: {
|
|
16383
|
+
type: "object",
|
|
16384
|
+
properties: {
|
|
16385
|
+
path: { type: "string", minLength: 1, maxLength: 1024 },
|
|
16386
|
+
content: { type: "string" }
|
|
16387
|
+
},
|
|
16388
|
+
required: ["path", "content"],
|
|
16389
|
+
additionalProperties: false
|
|
16390
|
+
}
|
|
16391
|
+
},
|
|
16392
|
+
deletions: {
|
|
16393
|
+
type: "array",
|
|
16394
|
+
maxItems: PORTABLE_SKILL_MAX_FILES2,
|
|
16395
|
+
uniqueItems: true,
|
|
16396
|
+
items: { type: "string", minLength: 1, maxLength: 1024 }
|
|
16397
|
+
},
|
|
16398
|
+
reason: { type: "string", minLength: 1, maxLength: 2e3 }
|
|
16399
|
+
},
|
|
16400
|
+
required: [
|
|
16401
|
+
"operationId",
|
|
16402
|
+
"skillId",
|
|
16403
|
+
"expectedRevisionId",
|
|
16404
|
+
"expectedScopeVersion",
|
|
16405
|
+
"files",
|
|
16406
|
+
"reason"
|
|
16407
|
+
],
|
|
16408
|
+
additionalProperties: false
|
|
16409
|
+
},
|
|
16410
|
+
annotations: {
|
|
16411
|
+
title: "Save Skill text",
|
|
16412
|
+
readOnlyHint: false,
|
|
16413
|
+
destructiveHint: false,
|
|
16414
|
+
idempotentHint: true,
|
|
16415
|
+
openWorldHint: false
|
|
16416
|
+
},
|
|
16417
|
+
source: "opengeni",
|
|
16418
|
+
approval: "none",
|
|
16419
|
+
execute: async (args) => {
|
|
16420
|
+
await input.authorize();
|
|
16421
|
+
const skillId = args.skillId;
|
|
16422
|
+
const expectedRevisionId = args.expectedRevisionId;
|
|
16423
|
+
const current = expectedRevisionId === null ? null : await input.load(skillId, expectedRevisionId);
|
|
16424
|
+
if (current && current.revisionId !== expectedRevisionId) {
|
|
16425
|
+
throw new Error("Skill edit base did not match the requested revision.");
|
|
16426
|
+
}
|
|
16427
|
+
const files = applySkillFileChanges(
|
|
16428
|
+
current?.files ?? [],
|
|
16429
|
+
args.files,
|
|
16430
|
+
args.deletions ?? []
|
|
16431
|
+
);
|
|
16432
|
+
const artifact = buildPortableSkillArtifact(files);
|
|
16433
|
+
const output = await input.save({
|
|
16434
|
+
operationId: args.operationId,
|
|
16435
|
+
skillId,
|
|
16436
|
+
expectedRevisionId,
|
|
16437
|
+
expectedScopeVersion: args.expectedScopeVersion,
|
|
16438
|
+
files: artifact.files,
|
|
16439
|
+
reason: args.reason
|
|
16440
|
+
});
|
|
16441
|
+
return {
|
|
16442
|
+
isError: false,
|
|
16443
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
16444
|
+
structuredContent: output
|
|
16445
|
+
};
|
|
16446
|
+
}
|
|
16447
|
+
};
|
|
16448
|
+
}
|
|
16449
|
+
|
|
16450
|
+
// src/activities/agent-turn/skill-install.ts
|
|
16451
|
+
function createSkillInstallAttemptToolDefinition(input) {
|
|
16452
|
+
return {
|
|
16453
|
+
identity: { serverId: "opengeni", toolName: "skill_install" },
|
|
16454
|
+
modelName: "skill_install",
|
|
16455
|
+
codemodePath: ["opengeni", "skill_install"],
|
|
16456
|
+
title: "Install a Skill",
|
|
16457
|
+
description: "Install a Skill from a public skills.sh or GitHub URL, or library:<id> returned by skill_search. The server resolves and pins the source; no prior preview or invented hash is required. Learning mode controls activation. Replacing an existing installation requires its current installation version, and preserves workspace customizations.",
|
|
16458
|
+
inputSchema: {
|
|
16459
|
+
type: "object",
|
|
16460
|
+
properties: {
|
|
16461
|
+
operationId: { type: "string", format: "uuid" },
|
|
16462
|
+
source: { type: "string", minLength: 1, maxLength: 2048 },
|
|
16463
|
+
expectedInstallationVersion: { type: "integer", minimum: 0 },
|
|
16464
|
+
reason: { type: "string", minLength: 1, maxLength: 2e3 }
|
|
16465
|
+
},
|
|
16466
|
+
required: ["operationId", "source", "reason"],
|
|
16467
|
+
additionalProperties: false
|
|
16468
|
+
},
|
|
16469
|
+
annotations: {
|
|
16470
|
+
readOnlyHint: false,
|
|
16471
|
+
destructiveHint: false,
|
|
16472
|
+
idempotentHint: true,
|
|
16473
|
+
openWorldHint: true
|
|
16474
|
+
},
|
|
16475
|
+
source: "opengeni",
|
|
16476
|
+
approval: "none",
|
|
16477
|
+
execute: async (args) => {
|
|
16478
|
+
await input.authorize();
|
|
16479
|
+
const output = await input.install({
|
|
16480
|
+
operationId: args.operationId,
|
|
16481
|
+
source: args.source,
|
|
16482
|
+
...args.expectedInstallationVersion !== void 0 ? { expectedInstallationVersion: args.expectedInstallationVersion } : {},
|
|
16483
|
+
reason: args.reason
|
|
16484
|
+
});
|
|
16485
|
+
return {
|
|
16486
|
+
isError: false,
|
|
16487
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
16488
|
+
structuredContent: output
|
|
16489
|
+
};
|
|
16490
|
+
}
|
|
16491
|
+
};
|
|
16492
|
+
}
|
|
16493
|
+
|
|
16494
|
+
// src/activities/agent-turn/skill-transfer.ts
|
|
16495
|
+
import { posix } from "path";
|
|
16496
|
+
import {
|
|
16497
|
+
assertSkillRelativePath as assertSkillRelativePath2,
|
|
16498
|
+
buildPortableSkillArtifact as buildPortableSkillArtifact2,
|
|
16499
|
+
PORTABLE_SKILL_MAX_FILES as PORTABLE_SKILL_MAX_FILES3,
|
|
16500
|
+
PORTABLE_SKILL_MAX_FILE_BYTES,
|
|
16501
|
+
PORTABLE_SKILL_MAX_TOTAL_BYTES
|
|
16502
|
+
} from "@opengeni/runtime/skill-library";
|
|
16503
|
+
var maxTraversalEntries = 1024;
|
|
16504
|
+
function guardSkillFilesystem(fs, authority) {
|
|
16505
|
+
const read = (operation) => {
|
|
16506
|
+
authority.assertActive();
|
|
16507
|
+
return operation();
|
|
16508
|
+
};
|
|
16509
|
+
const write = (operation) => {
|
|
16510
|
+
authority.assertActive();
|
|
16511
|
+
return authority.runMutation(() => read(operation));
|
|
16512
|
+
};
|
|
16513
|
+
return {
|
|
16514
|
+
fsList: (request) => read(() => fs.fsList(request)),
|
|
16515
|
+
fsRead: (request) => read(() => fs.fsRead(request)),
|
|
16516
|
+
fsWrite: (request) => write(() => fs.fsWrite(request)),
|
|
16517
|
+
fsMkdir: (request) => write(() => fs.fsMkdir(request))
|
|
16518
|
+
};
|
|
16519
|
+
}
|
|
16520
|
+
async function checkoutSkillDirectory(fs, directory, files) {
|
|
16521
|
+
assertSkillRelativePath2(directory);
|
|
16522
|
+
const artifact = buildPortableSkillArtifact2(files);
|
|
16523
|
+
const parent = posix.dirname(directory);
|
|
16524
|
+
if (parent !== ".") await fs.fsMkdir({ path: parent, recursive: true });
|
|
16525
|
+
await fs.fsMkdir({ path: directory, recursive: false });
|
|
16526
|
+
for (const file of artifact.files) {
|
|
16527
|
+
const result = await fs.fsWrite({
|
|
16528
|
+
path: `${directory}/${file.path}`,
|
|
16529
|
+
content: file.content,
|
|
16530
|
+
encoding: "utf8",
|
|
16531
|
+
overwrite: false,
|
|
16532
|
+
createParents: true
|
|
16533
|
+
});
|
|
16534
|
+
if (result.sizeBytes !== new TextEncoder().encode(file.content).byteLength) {
|
|
16535
|
+
throw new Error(`Skill checkout wrote an unexpected byte count: ${file.path}`);
|
|
16536
|
+
}
|
|
16537
|
+
}
|
|
16538
|
+
return { directory, fileCount: artifact.files.length };
|
|
16539
|
+
}
|
|
16540
|
+
async function readSkillDirectory(fs, directory) {
|
|
16541
|
+
assertSkillRelativePath2(directory);
|
|
16542
|
+
const pending = [directory];
|
|
16543
|
+
const seen = new Set(pending);
|
|
16544
|
+
const files = [];
|
|
16545
|
+
let entries = 0;
|
|
16546
|
+
let totalBytes = 0;
|
|
16547
|
+
while (pending.length) {
|
|
16548
|
+
const current = pending.shift();
|
|
16549
|
+
const listing = await fs.fsList({
|
|
16550
|
+
path: current,
|
|
16551
|
+
depth: 1,
|
|
16552
|
+
maxEntries: maxTraversalEntries + 1,
|
|
16553
|
+
includeHidden: true
|
|
16554
|
+
});
|
|
16555
|
+
if (listing.root.type !== "dir" || listing.root.path !== current) {
|
|
16556
|
+
throw new Error(`Expected a real Skill directory: ${current}`);
|
|
16557
|
+
}
|
|
16558
|
+
if (listing.truncated || listing.root.truncated || !listing.root.children) {
|
|
16559
|
+
throw new Error(`Skill directory listing is incomplete: ${current}`);
|
|
16560
|
+
}
|
|
16561
|
+
for (const entry of listing.root.children) {
|
|
16562
|
+
assertSkillRelativePath2(entry.path);
|
|
16563
|
+
if (posix.dirname(entry.path) !== current || posix.basename(entry.path) !== entry.name) {
|
|
16564
|
+
throw new Error("Skill directory listing returned a path outside the requested directory.");
|
|
16565
|
+
}
|
|
16566
|
+
if (seen.has(entry.path)) throw new Error(`Duplicate Skill directory entry: ${entry.path}`);
|
|
16567
|
+
seen.add(entry.path);
|
|
16568
|
+
if (++entries > maxTraversalEntries) throw new Error("Skill directory has too many entries.");
|
|
16569
|
+
if (entry.type === "dir") {
|
|
16570
|
+
pending.push(entry.path);
|
|
16571
|
+
continue;
|
|
16572
|
+
}
|
|
16573
|
+
if (entry.type !== "file") throw new Error(`Unsupported Skill file type: ${entry.path}`);
|
|
16574
|
+
if (files.length >= PORTABLE_SKILL_MAX_FILES3) throw new Error("Skill has too many files.");
|
|
16575
|
+
if (entry.sizeBytes !== null && entry.sizeBytes > PORTABLE_SKILL_MAX_FILE_BYTES) {
|
|
16576
|
+
throw new Error(`Skill file exceeds the size limit: ${entry.path}`);
|
|
16577
|
+
}
|
|
16578
|
+
const read = await fs.fsRead({
|
|
16579
|
+
path: entry.path,
|
|
16580
|
+
encoding: "base64",
|
|
16581
|
+
maxBytes: PORTABLE_SKILL_MAX_FILE_BYTES + 1
|
|
16582
|
+
});
|
|
16583
|
+
if (read.truncated || read.sizeBytes > PORTABLE_SKILL_MAX_FILE_BYTES) {
|
|
16584
|
+
throw new Error(`Skill file exceeds the size limit: ${entry.path}`);
|
|
16585
|
+
}
|
|
16586
|
+
if (read.encoding !== "base64" || read.path !== entry.path) {
|
|
16587
|
+
throw new Error(`Invalid Skill file read response: ${entry.path}`);
|
|
16588
|
+
}
|
|
16589
|
+
const bytes = Buffer.from(read.content, "base64");
|
|
16590
|
+
if (bytes.byteLength !== read.sizeBytes) {
|
|
16591
|
+
throw new Error(`Invalid Skill file byte count: ${entry.path}`);
|
|
16592
|
+
}
|
|
16593
|
+
totalBytes += bytes.byteLength;
|
|
16594
|
+
if (totalBytes > PORTABLE_SKILL_MAX_TOTAL_BYTES)
|
|
16595
|
+
throw new Error("Skill exceeds the total size limit.");
|
|
16596
|
+
let content;
|
|
16597
|
+
try {
|
|
16598
|
+
content = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
16599
|
+
} catch {
|
|
16600
|
+
throw new Error(`Skill file is not valid UTF-8 text: ${entry.path}`);
|
|
16601
|
+
}
|
|
16602
|
+
files.push({ path: entry.path.slice(directory.length + 1), content });
|
|
16603
|
+
}
|
|
16604
|
+
}
|
|
16605
|
+
return buildPortableSkillArtifact2(files);
|
|
16606
|
+
}
|
|
16607
|
+
|
|
16608
|
+
// src/activities/agent-turn/skill-checkout.ts
|
|
16609
|
+
function createSkillCheckoutAttemptToolDefinition(input) {
|
|
16610
|
+
return {
|
|
16611
|
+
identity: { serverId: "opengeni", toolName: "skill_checkout" },
|
|
16612
|
+
modelName: "skill_checkout",
|
|
16613
|
+
codemodePath: ["opengeni", "skill_checkout"],
|
|
16614
|
+
title: "Check out Skill files",
|
|
16615
|
+
description: "Copy a Skill to a fresh sandbox-relative directory for execution or larger edits. Starts the sandbox if needed. Never overwrites an existing directory and does not publish changes. Retain the returned revision and scope version for skill_publish. Use skill_read for ordinary reading without a sandbox.",
|
|
16616
|
+
inputSchema: {
|
|
16617
|
+
type: "object",
|
|
16618
|
+
properties: {
|
|
16619
|
+
skill: { type: "string", minLength: 1, maxLength: 512 },
|
|
16620
|
+
directory: { type: "string", minLength: 1, maxLength: 1024 }
|
|
16621
|
+
},
|
|
16622
|
+
required: ["skill", "directory"],
|
|
16623
|
+
additionalProperties: false
|
|
16624
|
+
},
|
|
16625
|
+
annotations: {
|
|
16626
|
+
readOnlyHint: false,
|
|
16627
|
+
destructiveHint: false,
|
|
16628
|
+
idempotentHint: false,
|
|
16629
|
+
openWorldHint: false
|
|
16630
|
+
},
|
|
16631
|
+
source: "opengeni",
|
|
16632
|
+
approval: "none",
|
|
16633
|
+
execute: async (args) => {
|
|
16634
|
+
await input.authorize();
|
|
16635
|
+
const skill = await input.load(args.skill);
|
|
16636
|
+
const copied = await checkoutSkillDirectory(
|
|
16637
|
+
await input.filesystem(),
|
|
16638
|
+
args.directory,
|
|
16639
|
+
skill.files
|
|
16640
|
+
);
|
|
16641
|
+
const output = {
|
|
16642
|
+
...copied,
|
|
16643
|
+
skillId: skill.skillId,
|
|
16644
|
+
revisionId: skill.revisionId,
|
|
16645
|
+
scopeVersion: skill.scopeVersion
|
|
16646
|
+
};
|
|
16647
|
+
return {
|
|
16648
|
+
isError: false,
|
|
16649
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
16650
|
+
structuredContent: output
|
|
16651
|
+
};
|
|
16652
|
+
}
|
|
16653
|
+
};
|
|
16654
|
+
}
|
|
16655
|
+
function createSkillPublishAttemptToolDefinition(input) {
|
|
16656
|
+
return {
|
|
16657
|
+
identity: { serverId: "opengeni", toolName: "skill_publish" },
|
|
16658
|
+
modelName: "skill_publish",
|
|
16659
|
+
codemodePath: ["opengeni", "skill_publish"],
|
|
16660
|
+
title: "Publish Skill directory",
|
|
16661
|
+
description: "Save a complete sandbox Skill directory through the same Learning-controlled service as skill_save. Reads UTF-8 text files directly; do not serialize the directory into arguments. Files missing from the directory are removed from the new revision. Supply the checkout revision and scope version; stale edits are refused. The result reports whether the change is live or pending approval.",
|
|
16662
|
+
inputSchema: {
|
|
16663
|
+
type: "object",
|
|
16664
|
+
properties: {
|
|
16665
|
+
operationId: { type: "string", format: "uuid" },
|
|
16666
|
+
skillId: { type: "string", format: "uuid" },
|
|
16667
|
+
expectedRevisionId: { type: ["string", "null"], format: "uuid" },
|
|
16668
|
+
expectedScopeVersion: { type: "integer", minimum: 0 },
|
|
16669
|
+
directory: { type: "string", minLength: 1, maxLength: 1024 },
|
|
16670
|
+
reason: { type: "string", minLength: 1, maxLength: 2e3 }
|
|
16671
|
+
},
|
|
16672
|
+
required: [
|
|
16673
|
+
"operationId",
|
|
16674
|
+
"skillId",
|
|
16675
|
+
"expectedRevisionId",
|
|
16676
|
+
"expectedScopeVersion",
|
|
16677
|
+
"directory",
|
|
16678
|
+
"reason"
|
|
16679
|
+
],
|
|
16680
|
+
additionalProperties: false
|
|
16681
|
+
},
|
|
16682
|
+
annotations: {
|
|
16683
|
+
readOnlyHint: false,
|
|
16684
|
+
destructiveHint: false,
|
|
16685
|
+
idempotentHint: true,
|
|
16686
|
+
openWorldHint: false
|
|
16687
|
+
},
|
|
16688
|
+
source: "opengeni",
|
|
16689
|
+
approval: "none",
|
|
16690
|
+
execute: async (args) => {
|
|
16691
|
+
await input.authorize();
|
|
16692
|
+
const artifact = await readSkillDirectory(await input.filesystem(), args.directory);
|
|
16693
|
+
const output = await input.save({
|
|
16694
|
+
operationId: args.operationId,
|
|
16695
|
+
skillId: args.skillId,
|
|
16696
|
+
expectedRevisionId: args.expectedRevisionId,
|
|
16697
|
+
expectedScopeVersion: args.expectedScopeVersion,
|
|
16698
|
+
files: artifact.files,
|
|
16699
|
+
reason: args.reason
|
|
16700
|
+
});
|
|
16701
|
+
return {
|
|
16702
|
+
isError: false,
|
|
16703
|
+
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
16704
|
+
structuredContent: output
|
|
16705
|
+
};
|
|
16706
|
+
}
|
|
16707
|
+
};
|
|
16708
|
+
}
|
|
16709
|
+
|
|
16710
|
+
// src/activities/agent-turn/skill-tools.ts
|
|
16711
|
+
function createWorkspaceSkillTools(input) {
|
|
16712
|
+
const context = {
|
|
16713
|
+
accountId: input.accountId,
|
|
16714
|
+
workspaceId: input.workspaceId,
|
|
16715
|
+
...input.subjectId ? { subjectId: input.subjectId } : {}
|
|
16716
|
+
};
|
|
16717
|
+
const authorize = () => assertSkillReadAttempt(input.db, { ...context, actor: input.actor });
|
|
16718
|
+
const selected = new Map(input.selected.map((entry) => [entry.id, entry.artifact]));
|
|
16719
|
+
const list = async () => (await listSkillDescriptors(input.db, context)).filter(
|
|
16720
|
+
(entry) => entry.activationMode === "workspace_managed"
|
|
16721
|
+
);
|
|
16722
|
+
const load = async (identifier) => {
|
|
16723
|
+
const exact = selected.get(identifier);
|
|
16724
|
+
if (exact) return exact.files;
|
|
16725
|
+
const descriptors = await list();
|
|
16726
|
+
const exactWorkspace = descriptors.find((entry) => entry.id === identifier);
|
|
16727
|
+
const matches = exactWorkspace ? [exactWorkspace] : descriptors.filter((entry) => entry.title === identifier || entry.stableKey === identifier);
|
|
16728
|
+
const selectedMatches = [...selected.entries()].filter(
|
|
16729
|
+
([, artifact]) => artifact.name === identifier
|
|
16730
|
+
);
|
|
16731
|
+
if (!exactWorkspace && matches.length + selectedMatches.length > 1)
|
|
16732
|
+
throw new Error(
|
|
16733
|
+
"Multiple Skills match that name. Use the Skill id from the index or search."
|
|
16734
|
+
);
|
|
16735
|
+
if (!matches.length && selectedMatches.length === 1) return selectedMatches[0][1].files;
|
|
16736
|
+
const match = matches[0];
|
|
16737
|
+
if (!match) throw new Error("Skill is not available in this session.");
|
|
16738
|
+
const record5 = await readSkill(input.db, context, match.id);
|
|
16739
|
+
if (!record5 || record5.status !== "active" || !record5.activeRevisionId || record5.revisionId !== record5.activeRevisionId)
|
|
16740
|
+
throw new Error("Skill is no longer active. Search again for current Skills.");
|
|
16741
|
+
return {
|
|
16742
|
+
skillId: record5.id,
|
|
16743
|
+
revisionId: record5.activeRevisionId,
|
|
16744
|
+
scopeVersion: record5.scopeVersion,
|
|
16745
|
+
...match.installationVersion !== null ? { installationVersion: match.installationVersion } : {},
|
|
16746
|
+
files: record5.files
|
|
16747
|
+
};
|
|
16748
|
+
};
|
|
16749
|
+
const withConfirmation = async (receipt) => {
|
|
16750
|
+
const reviewResolution = receipt.skillReview ? await skillReviewResolution(input.db, context, receipt.skillReview) : void 0;
|
|
16751
|
+
return {
|
|
16752
|
+
...receipt,
|
|
16753
|
+
...reviewResolution ? { reviewResolution } : {},
|
|
16754
|
+
...receipt.skillReview && reviewResolution === "pending" ? { humanInput: skillReviewHumanInput(receipt.skillReview) } : {}
|
|
16755
|
+
};
|
|
16756
|
+
};
|
|
16757
|
+
const save = async (request) => {
|
|
16758
|
+
const artifact = buildPortableSkillArtifact3(request.files);
|
|
16759
|
+
const base = request.expectedRevisionId ? await readSkill(input.db, context, request.skillId, request.expectedRevisionId) : null;
|
|
16760
|
+
return withConfirmation(
|
|
16761
|
+
await saveSkill(input.db, {
|
|
16762
|
+
...context,
|
|
16763
|
+
...request,
|
|
16764
|
+
actor: input.actor,
|
|
16765
|
+
files: [...artifact.files],
|
|
16766
|
+
stableKey: base?.stableKey ?? `authored-${request.skillId.replaceAll("-", "")}`
|
|
16767
|
+
})
|
|
16768
|
+
);
|
|
16769
|
+
};
|
|
16770
|
+
return [
|
|
16771
|
+
createSkillReadAttemptToolDefinition({ authorize, load }),
|
|
16772
|
+
createSkillSearchAttemptToolDefinition({
|
|
16773
|
+
authorize,
|
|
16774
|
+
listWorkspace: async () => [
|
|
16775
|
+
...(await list()).map((entry) => ({
|
|
16776
|
+
id: entry.id,
|
|
16777
|
+
name: entry.title,
|
|
16778
|
+
description: entry.description,
|
|
16779
|
+
revisionId: entry.revisionId,
|
|
16780
|
+
scopeVersion: entry.scopeVersion,
|
|
16781
|
+
...entry.installationVersion !== null ? { installationVersion: entry.installationVersion } : {}
|
|
16782
|
+
})),
|
|
16783
|
+
...input.selected.map((entry) => ({
|
|
16784
|
+
id: entry.id,
|
|
16785
|
+
name: entry.artifact.name,
|
|
16786
|
+
description: entry.artifact.description || entry.artifact.name,
|
|
16787
|
+
source: entry.id.startsWith("builtin:") ? "builtin" : entry.id.startsWith("session:") ? "session" : "pack"
|
|
16788
|
+
}))
|
|
16789
|
+
],
|
|
16790
|
+
publicSearch: createPublicSkillSearchClient(input.settings)
|
|
16791
|
+
}),
|
|
16792
|
+
createSkillSaveAttemptToolDefinition({
|
|
16793
|
+
authorize,
|
|
16794
|
+
save,
|
|
16795
|
+
load: async (skillId, revisionId) => {
|
|
16796
|
+
const record5 = await readSkill(input.db, context, skillId, revisionId);
|
|
16797
|
+
if (!record5?.revisionId) throw new Error("Skill edit base is unavailable.");
|
|
16798
|
+
return { revisionId: record5.revisionId, files: record5.files };
|
|
16799
|
+
}
|
|
16800
|
+
}),
|
|
16801
|
+
createSkillInstallAttemptToolDefinition({
|
|
16802
|
+
authorize,
|
|
16803
|
+
install: async (request) => {
|
|
16804
|
+
const requestIdentity = {
|
|
16805
|
+
operation: "skill_install",
|
|
16806
|
+
source: request.source,
|
|
16807
|
+
expectedInstallationVersion: request.expectedInstallationVersion ?? null,
|
|
16808
|
+
reason: request.reason,
|
|
16809
|
+
owner: "direct"
|
|
16810
|
+
};
|
|
16811
|
+
const replay = await replayPortableSkillInstall(input.db, {
|
|
16812
|
+
...context,
|
|
16813
|
+
actor: input.actor,
|
|
16814
|
+
operationId: request.operationId,
|
|
16815
|
+
requestIdentity
|
|
16816
|
+
});
|
|
16817
|
+
if (replay) return withConfirmation(replay.skillReceipt);
|
|
16818
|
+
let source;
|
|
16819
|
+
if (request.source.startsWith("library:")) {
|
|
16820
|
+
const loaded = loadSkillLibrarySkill(request.source.slice("library:".length));
|
|
16821
|
+
source = {
|
|
16822
|
+
capabilityId: `skill:${loaded.entry.id}`,
|
|
16823
|
+
pluginKey: `skill/library/${loaded.entry.id}`,
|
|
16824
|
+
source: "library",
|
|
16825
|
+
sourceUrl: loaded.entry.sourceUrl,
|
|
16826
|
+
repositoryUrl: skillLibraryRepositoryUrl(loaded.entry.sourceUrl),
|
|
16827
|
+
version: loaded.entry.version,
|
|
16828
|
+
sourceCommit: loaded.entry.sourceCommit,
|
|
16829
|
+
sourcePath: loaded.entry.relativePath,
|
|
16830
|
+
name: loaded.entry.name,
|
|
16831
|
+
description: loaded.entry.description,
|
|
16832
|
+
contentSha256: loaded.entry.contentSha256,
|
|
16833
|
+
totalBytes: loaded.skill.files.reduce(
|
|
16834
|
+
(total, file) => total + Buffer.byteLength(file.content),
|
|
16835
|
+
0
|
|
16836
|
+
),
|
|
16837
|
+
files: fileMetadata(loaded.skill.files),
|
|
16838
|
+
provenance: "platform",
|
|
16839
|
+
sourceProvenance: loaded.entry.provenance,
|
|
16840
|
+
category: loaded.entry.category,
|
|
16841
|
+
tags: [...loaded.entry.tags],
|
|
16842
|
+
license: loaded.entry.license
|
|
16843
|
+
};
|
|
16844
|
+
} else {
|
|
16845
|
+
const resolved = await resolveSkillImport(
|
|
16846
|
+
request.source,
|
|
16847
|
+
createGitHubSkillSourceClient(input.settings)
|
|
16848
|
+
);
|
|
16849
|
+
source = {
|
|
16850
|
+
capabilityId: portableSkillCapabilityId(resolved.preview),
|
|
16851
|
+
pluginKey: portableSkillPluginKey(resolved.preview),
|
|
16852
|
+
source: resolved.preview.source,
|
|
16853
|
+
sourceUrl: resolved.preview.sourceUrl,
|
|
16854
|
+
repositoryUrl: resolved.preview.repositoryUrl,
|
|
16855
|
+
version: resolved.preview.sourceCommit,
|
|
16856
|
+
sourceCommit: resolved.preview.sourceCommit,
|
|
16857
|
+
sourcePath: resolved.preview.sourcePath,
|
|
16858
|
+
name: resolved.preview.name,
|
|
16859
|
+
description: resolved.preview.description,
|
|
16860
|
+
contentSha256: resolved.preview.contentSha256,
|
|
16861
|
+
totalBytes: resolved.preview.totalBytes,
|
|
16862
|
+
files: fileMetadata(resolved.files)
|
|
16863
|
+
};
|
|
16864
|
+
}
|
|
16865
|
+
const installed = await installPortableSkill(input.db, {
|
|
16866
|
+
...context,
|
|
16867
|
+
...source,
|
|
16868
|
+
subjectId: `service:skill-attempt:${input.actor.attemptId}`,
|
|
16869
|
+
skillActor: input.actor,
|
|
16870
|
+
skillOperationId: request.operationId,
|
|
16871
|
+
skillRequestIdentity: requestIdentity,
|
|
16872
|
+
...request.expectedInstallationVersion !== void 0 ? {
|
|
16873
|
+
expectedInstallationVersion: request.expectedInstallationVersion
|
|
16874
|
+
} : {}
|
|
16875
|
+
});
|
|
16876
|
+
return withConfirmation(installed.skillReceipt);
|
|
16877
|
+
}
|
|
16878
|
+
}),
|
|
16879
|
+
createSkillCheckoutAttemptToolDefinition({
|
|
16880
|
+
authorize,
|
|
16881
|
+
filesystem: input.filesystem,
|
|
16882
|
+
load: async (skill) => {
|
|
16883
|
+
const content = await load(skill);
|
|
16884
|
+
if (!("files" in content))
|
|
16885
|
+
return { skillId: skill, revisionId: null, scopeVersion: null, files: content };
|
|
16886
|
+
return content;
|
|
16887
|
+
}
|
|
16888
|
+
}),
|
|
16889
|
+
createSkillPublishAttemptToolDefinition({ authorize, filesystem: input.filesystem, save })
|
|
16890
|
+
];
|
|
16891
|
+
}
|
|
16892
|
+
function fileMetadata(files) {
|
|
16893
|
+
return files.map((file) => ({
|
|
16894
|
+
...file,
|
|
16895
|
+
byteSize: Buffer.byteLength(file.content),
|
|
16896
|
+
contentSha256: createHash11("sha256").update(file.content, "utf8").digest("hex")
|
|
16897
|
+
}));
|
|
16898
|
+
}
|
|
16899
|
+
|
|
16900
|
+
// src/activities/agent-turn/skill-selection.ts
|
|
16901
|
+
import { loadNativeToolSkillArtifacts } from "@opengeni/runtime";
|
|
16902
|
+
import { loadSkillManagementSkill } from "@opengeni/runtime/skill-library";
|
|
16903
|
+
function configuredBundledSkillNames(context) {
|
|
16904
|
+
const tools = new Set(context.firstPartyTools);
|
|
16905
|
+
const artifacts = () => tools.has("editable_artifact_list") && tools.has("editable_artifact_get");
|
|
16906
|
+
const definitions = [
|
|
16907
|
+
{ name: "opengeni-skills", include: () => true },
|
|
16908
|
+
{ name: "opengeni-projects", include: () => true },
|
|
16909
|
+
{ name: "opengeni-documents", include: artifacts },
|
|
16910
|
+
{ name: "opengeni-spreadsheets", include: artifacts },
|
|
16911
|
+
{ name: "opengeni-presentations", include: artifacts },
|
|
16912
|
+
{
|
|
16913
|
+
name: "opengeni-sites",
|
|
16914
|
+
include: () => tools.has("artifacts_create") && tools.has("artifacts_publish")
|
|
16915
|
+
},
|
|
16916
|
+
{ name: "opengeni-video-generation", include: () => context.videoGenerationEnabled }
|
|
16917
|
+
];
|
|
16918
|
+
return definitions.filter(
|
|
16919
|
+
(definition) => definition.include() && (context.bundledSkillIds === void 0 || context.bundledSkillIds.includes(`builtin:${definition.name}`))
|
|
16920
|
+
).map((definition) => definition.name);
|
|
16921
|
+
}
|
|
16922
|
+
function loadConfiguredBundledSkills(context) {
|
|
16923
|
+
const names = new Set(configuredBundledSkillNames(context));
|
|
16924
|
+
const artifacts = loadNativeToolSkillArtifacts({
|
|
16925
|
+
projects: names.has("opengeni-projects"),
|
|
16926
|
+
editableArtifacts: [
|
|
16927
|
+
"opengeni-documents",
|
|
16928
|
+
"opengeni-spreadsheets",
|
|
16929
|
+
"opengeni-presentations"
|
|
16930
|
+
].some((name) => names.has(name)),
|
|
16931
|
+
sites: names.has("opengeni-sites"),
|
|
16932
|
+
videoGeneration: names.has("opengeni-video-generation")
|
|
16933
|
+
});
|
|
16934
|
+
return [...artifacts, ...names.has("opengeni-skills") ? [loadSkillManagementSkill()] : []].filter((artifact) => names.has(artifact.name)).map((artifact) => ({ id: `builtin:${artifact.name}`, artifact }));
|
|
16935
|
+
}
|
|
16936
|
+
|
|
16584
16937
|
// src/activities/agent-turn/tool-environment.ts
|
|
16585
16938
|
async function prepareTurnToolPolicy(deps) {
|
|
16586
16939
|
const {
|
|
@@ -16907,7 +17260,82 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
16907
17260
|
outcome
|
|
16908
17261
|
})
|
|
16909
17262
|
};
|
|
17263
|
+
const skillConfiguration = await getWorkspaceVideoGenerationPolicy(db, input.workspaceId);
|
|
17264
|
+
const bundledSkills = loadConfiguredBundledSkills({
|
|
17265
|
+
bundledSkillIds: session.bundledSkillIds,
|
|
17266
|
+
firstPartyTools: selectedFirstPartyMcpTools,
|
|
17267
|
+
videoGenerationEnabled: skillConfiguration.defaultModelId !== null && skillConfiguration.enabledModelIds.length > 0
|
|
17268
|
+
});
|
|
17269
|
+
const selectedSkills = [
|
|
17270
|
+
...bundledSkills,
|
|
17271
|
+
...deps.selectedSkillActivations.map((entry) => ({ id: entry.id, artifact: entry.artifact })),
|
|
17272
|
+
...session.skills.map((skill) => ({
|
|
17273
|
+
id: `session:${session.id}:${skill.name}`,
|
|
17274
|
+
artifact: skill
|
|
17275
|
+
}))
|
|
17276
|
+
];
|
|
17277
|
+
const sharedSkillDescriptors = await listSkillDescriptors2(db, {
|
|
17278
|
+
accountId: input.accountId,
|
|
17279
|
+
workspaceId: input.workspaceId,
|
|
17280
|
+
...deps.fileAuthoritySubjectId ? { subjectId: deps.fileAuthoritySubjectId } : {}
|
|
17281
|
+
});
|
|
17282
|
+
const skillCatalog = [
|
|
17283
|
+
...sharedSkillDescriptors.filter((entry) => entry.activationMode === "workspace_managed").map((entry) => ({
|
|
17284
|
+
id: entry.id,
|
|
17285
|
+
name: entry.title,
|
|
17286
|
+
description: entry.description
|
|
17287
|
+
})),
|
|
17288
|
+
...selectedSkills.map((entry) => ({
|
|
17289
|
+
id: entry.id,
|
|
17290
|
+
name: entry.artifact.name,
|
|
17291
|
+
description: entry.artifact.description || entry.artifact.name
|
|
17292
|
+
}))
|
|
17293
|
+
];
|
|
17294
|
+
const skillTools = createWorkspaceSkillTools({
|
|
17295
|
+
db,
|
|
17296
|
+
settings: runSettings,
|
|
17297
|
+
accountId: input.accountId,
|
|
17298
|
+
workspaceId: input.workspaceId,
|
|
17299
|
+
...deps.fileAuthoritySubjectId ? { subjectId: deps.fileAuthoritySubjectId } : {},
|
|
17300
|
+
actor: {
|
|
17301
|
+
kind: "agent",
|
|
17302
|
+
sessionId: input.sessionId,
|
|
17303
|
+
turnId: turn.id,
|
|
17304
|
+
attemptId: input.attemptId,
|
|
17305
|
+
executionGeneration: attempt.executionGeneration
|
|
17306
|
+
},
|
|
17307
|
+
selected: selectedSkills,
|
|
17308
|
+
filesystem: async () => {
|
|
17309
|
+
throwIfWorkerShuttingDown();
|
|
17310
|
+
throwIfTurnCancelled();
|
|
17311
|
+
const access = await resolveTurnSandboxAccess(
|
|
17312
|
+
sandboxState,
|
|
17313
|
+
media.sdkOwnedSandboxSession,
|
|
17314
|
+
"Skill checkout/publish requires a sandbox or Connected Machine."
|
|
17315
|
+
);
|
|
17316
|
+
const machineRoot = sandboxState.machinePrimarySession?.workspaceRoot;
|
|
17317
|
+
const runAs = sandboxRunAs4(runSettings);
|
|
17318
|
+
const channel = new SandboxChannelAService3({
|
|
17319
|
+
session: access.session,
|
|
17320
|
+
workspaceRoot: machineRoot ?? "/workspace",
|
|
17321
|
+
...machineRoot ? { providerPathMode: "workspace-relative" } : {},
|
|
17322
|
+
leaseEpoch: access.leaseEpoch,
|
|
17323
|
+
emit: async (events) => {
|
|
17324
|
+
await eventing.publish?.(events, true);
|
|
17325
|
+
},
|
|
17326
|
+
...runAs ? { runAs } : {}
|
|
17327
|
+
});
|
|
17328
|
+
return guardSkillFilesystem(channel, {
|
|
17329
|
+
assertActive: () => {
|
|
17330
|
+
throwIfWorkerShuttingDown();
|
|
17331
|
+
throwIfTurnCancelled();
|
|
17332
|
+
},
|
|
17333
|
+
runMutation: async (mutation) => access.sandbox && !routingOn ? runWorkspaceMutationForSandbox(access.sandbox, "skillCheckout", mutation) : mutation()
|
|
17334
|
+
});
|
|
17335
|
+
}
|
|
17336
|
+
});
|
|
16910
17337
|
const attemptToolDefinitions = [
|
|
17338
|
+
...skillTools,
|
|
16911
17339
|
createListModelsAttemptToolDefinition({
|
|
16912
17340
|
currentModelId: turnExecutionPolicy.productModelId,
|
|
16913
17341
|
load: async () => {
|
|
@@ -17196,7 +17624,11 @@ async function prepareTurnToolRuntime(deps) {
|
|
|
17196
17624
|
connectorActionPolicy,
|
|
17197
17625
|
generateSessionTitleInParallel: titleToolPlan.generateTitleInParallel,
|
|
17198
17626
|
postToolPreparationStartedAt,
|
|
17199
|
-
preparationIndependentToolNames:
|
|
17627
|
+
preparationIndependentToolNames: [
|
|
17628
|
+
...titleToolPlan.preparationIndependentToolNames,
|
|
17629
|
+
"skill_read"
|
|
17630
|
+
],
|
|
17631
|
+
skillCatalog
|
|
17200
17632
|
};
|
|
17201
17633
|
}
|
|
17202
17634
|
|
|
@@ -17390,9 +17822,12 @@ import {
|
|
|
17390
17822
|
resolveXaiProviderAccountAuthoritySnapshotForAcceptance,
|
|
17391
17823
|
getXaiSessionAccountPin as getXaiSessionAccountPin2,
|
|
17392
17824
|
setXaiSessionAccountPin as setXaiSessionAccountPin2,
|
|
17393
|
-
getWorkspaceVideoGenerationPolicy,
|
|
17825
|
+
getWorkspaceVideoGenerationPolicy as getWorkspaceVideoGenerationPolicy2,
|
|
17394
17826
|
loadWorkspaceVercelAiGatewayCredentialLease
|
|
17395
17827
|
} from "@opengeni/db";
|
|
17828
|
+
import {
|
|
17829
|
+
formatSkillCatalog
|
|
17830
|
+
} from "@opengeni/runtime";
|
|
17396
17831
|
import {
|
|
17397
17832
|
serviceTierForLatencyMode as serviceTierForLatencyMode2,
|
|
17398
17833
|
environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes3,
|
|
@@ -18590,8 +19025,6 @@ async function buildTurnAgent(deps) {
|
|
|
18590
19025
|
workspaceMemory,
|
|
18591
19026
|
rigVersion,
|
|
18592
19027
|
rigName,
|
|
18593
|
-
packRuntime,
|
|
18594
|
-
installedSkillRuntime,
|
|
18595
19028
|
buildCompanyBrainContributionReceiptFor,
|
|
18596
19029
|
promptCacheKey,
|
|
18597
19030
|
workspaceVariableSet,
|
|
@@ -18774,7 +19207,7 @@ async function buildTurnAgent(deps) {
|
|
|
18774
19207
|
}
|
|
18775
19208
|
};
|
|
18776
19209
|
})();
|
|
18777
|
-
const videoGenerationPolicy = await
|
|
19210
|
+
const videoGenerationPolicy = await getWorkspaceVideoGenerationPolicy2(db, input.workspaceId);
|
|
18778
19211
|
const videoGenerationEnabled = videoGenerationPolicy.defaultModelId !== null && videoGenerationPolicy.enabledModelIds.length > 0;
|
|
18779
19212
|
let videoGenerationCredential = null;
|
|
18780
19213
|
if (objectStorage && videoGenerationEnabled) {
|
|
@@ -18925,30 +19358,10 @@ async function buildTurnAgent(deps) {
|
|
|
18925
19358
|
turnExecutionPolicy.latencyMode
|
|
18926
19359
|
);
|
|
18927
19360
|
const approvedToolCallId = approvedConnectorActionCallId(trigger);
|
|
18928
|
-
const
|
|
18929
|
-
...installedSkillRuntime.activations,
|
|
18930
|
-
...packRuntime.skillActivations,
|
|
18931
|
-
...session.skills.map((skill) => ({
|
|
18932
|
-
source: "session",
|
|
18933
|
-
id: `session:${session.id}:${skill.name}`,
|
|
18934
|
-
artifact: {
|
|
18935
|
-
name: skill.name,
|
|
18936
|
-
description: skill.description ?? null,
|
|
18937
|
-
files: skill.files.map((file) => ({
|
|
18938
|
-
path: file.path,
|
|
18939
|
-
content: file.content
|
|
18940
|
-
}))
|
|
18941
|
-
},
|
|
18942
|
-
reason: "attached to session"
|
|
18943
|
-
}))
|
|
18944
|
-
];
|
|
18945
|
-
const modelVisibleRuntimeSkillActivations = modelVisibleCompanyBrainSkillActivations(
|
|
18946
|
-
eventing.modelRunSettings.sandboxBackend,
|
|
18947
|
-
runtimeSkillActivations
|
|
18948
|
-
);
|
|
19361
|
+
const modelVisibleSkillCatalogText = formatSkillCatalog(deps.skillCatalog);
|
|
18949
19362
|
try {
|
|
18950
19363
|
eventing.companyBrainContextContributions = summarizeCompanyBrainContributions(
|
|
18951
|
-
buildCompanyBrainContributionReceiptFor(
|
|
19364
|
+
buildCompanyBrainContributionReceiptFor(modelVisibleSkillCatalogText)
|
|
18952
19365
|
);
|
|
18953
19366
|
} catch {
|
|
18954
19367
|
}
|
|
@@ -19049,7 +19462,8 @@ async function buildTurnAgent(deps) {
|
|
|
19049
19462
|
}
|
|
19050
19463
|
),
|
|
19051
19464
|
onRetainableSessionImageOutput: media.retainSessionImageAtToolBoundary,
|
|
19052
|
-
|
|
19465
|
+
skillCatalog: deps.skillCatalog,
|
|
19466
|
+
serverSkillReading: true,
|
|
19053
19467
|
...!structuredWorkspacePolicyActive && workspaceAgentInstructions ? { instructionsTemplate: workspaceAgentInstructions } : {},
|
|
19054
19468
|
...workspaceGovernance ? { workspaceGovernance } : {},
|
|
19055
19469
|
...workspaceMemory ? { workspaceMemory } : {},
|
|
@@ -19105,7 +19519,7 @@ async function buildTurnAgent(deps) {
|
|
|
19105
19519
|
}
|
|
19106
19520
|
return {
|
|
19107
19521
|
agent,
|
|
19108
|
-
|
|
19522
|
+
modelVisibleSkillCatalogText,
|
|
19109
19523
|
postAgentPreparationStartedAt
|
|
19110
19524
|
};
|
|
19111
19525
|
}
|
|
@@ -19431,7 +19845,6 @@ function createRunAgentTurnActivity(services) {
|
|
|
19431
19845
|
const {
|
|
19432
19846
|
runtimePreparationStartedAt,
|
|
19433
19847
|
packRuntime,
|
|
19434
|
-
installedSkillRuntime,
|
|
19435
19848
|
rigVersion,
|
|
19436
19849
|
rigName,
|
|
19437
19850
|
agentHumanInputEnabled,
|
|
@@ -20002,6 +20415,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
20002
20415
|
).values()
|
|
20003
20416
|
];
|
|
20004
20417
|
const toolRuntime = await prepareTurnToolRuntime({
|
|
20418
|
+
selectedSkillActivations: packRuntime.skillActivations,
|
|
20005
20419
|
input,
|
|
20006
20420
|
catalogSourceSettings,
|
|
20007
20421
|
db,
|
|
@@ -20048,6 +20462,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
20048
20462
|
preparationIndependentToolNames
|
|
20049
20463
|
} = toolRuntime;
|
|
20050
20464
|
const builtAgent = await buildTurnAgent({
|
|
20465
|
+
skillCatalog: toolRuntime.skillCatalog,
|
|
20051
20466
|
input,
|
|
20052
20467
|
db,
|
|
20053
20468
|
runtime,
|
|
@@ -20082,8 +20497,6 @@ function createRunAgentTurnActivity(services) {
|
|
|
20082
20497
|
workspaceMemory,
|
|
20083
20498
|
rigVersion,
|
|
20084
20499
|
rigName,
|
|
20085
|
-
packRuntime,
|
|
20086
|
-
installedSkillRuntime,
|
|
20087
20500
|
buildCompanyBrainContributionReceiptFor,
|
|
20088
20501
|
promptCacheKey,
|
|
20089
20502
|
workspaceVariableSet,
|
|
@@ -20105,7 +20518,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
20105
20518
|
postToolPreparationStartedAt,
|
|
20106
20519
|
codexContext
|
|
20107
20520
|
});
|
|
20108
|
-
const { agent,
|
|
20521
|
+
const { agent, modelVisibleSkillCatalogText, postAgentPreparationStartedAt } = builtAgent;
|
|
20109
20522
|
await bindLazySandboxProvisioner({
|
|
20110
20523
|
...sandboxRoute,
|
|
20111
20524
|
input,
|
|
@@ -20159,7 +20572,7 @@ function createRunAgentTurnActivity(services) {
|
|
|
20159
20572
|
companyBrainContributionReceiptRecorded = true;
|
|
20160
20573
|
try {
|
|
20161
20574
|
const companyBrainContributionReceipt = buildCompanyBrainContributionReceiptFor(
|
|
20162
|
-
|
|
20575
|
+
modelVisibleSkillCatalogText
|
|
20163
20576
|
);
|
|
20164
20577
|
eventing.companyBrainContextContributions = summarizeCompanyBrainContributions(
|
|
20165
20578
|
companyBrainContributionReceipt
|
|
@@ -21557,4 +21970,4 @@ export {
|
|
|
21557
21970
|
createTurnActivities,
|
|
21558
21971
|
createTurnActivitiesFromServices
|
|
21559
21972
|
};
|
|
21560
|
-
//# sourceMappingURL=activities-turn-
|
|
21973
|
+
//# sourceMappingURL=activities-turn-V7J34ZOF.js.map
|