@odla-ai/harness 0.8.1 → 0.9.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/README.md +11 -0
- package/dist/{chunk-IWVGSWY6.js → chunk-4EPJJMFG.js} +330 -106
- package/dist/chunk-4EPJJMFG.js.map +1 -0
- package/dist/{chunk-NWNBSX56.js → chunk-CIKYMC67.js} +4 -4
- package/dist/{chunk-CR6RE3A2.js → chunk-HDIR4MM5.js} +3 -3
- package/dist/{chunk-RXNHCGWE.js → chunk-I43KTCJ2.js} +1 -1
- package/dist/{chunk-RXNHCGWE.js.map → chunk-I43KTCJ2.js.map} +1 -1
- package/dist/{chunk-Q7CKOT7T.js → chunk-VGNIDRKM.js} +2 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +4 -4
- package/dist/code-runtime-cli.cjs +330 -102
- package/dist/code-runtime-cli.cjs.map +1 -1
- package/dist/code-runtime-cli.js +12 -5
- package/dist/code-runtime-cli.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/node.cjs +327 -101
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +71 -17
- package/dist/node.d.ts +71 -17
- package/dist/node.js +9 -5
- package/dist/node.js.map +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-BNJikP5h.d.cts → types-BazqxWK8.d.cts} +14 -0
- package/dist/{types-BNJikP5h.d.ts → types-BazqxWK8.d.ts} +14 -0
- package/package.json +2 -2
- package/dist/chunk-IWVGSWY6.js.map +0 -1
- /package/dist/{chunk-NWNBSX56.js.map → chunk-CIKYMC67.js.map} +0 -0
- /package/dist/{chunk-CR6RE3A2.js.map → chunk-HDIR4MM5.js.map} +0 -0
- /package/dist/{chunk-Q7CKOT7T.js.map → chunk-VGNIDRKM.js.map} +0 -0
package/dist/node.cjs
CHANGED
|
@@ -43,6 +43,7 @@ __export(node_exports, {
|
|
|
43
43
|
codeSkill: () => codeSkill,
|
|
44
44
|
createCodeRuntimeControlClient: () => createCodeRuntimeControlClient,
|
|
45
45
|
createCodeRuntimeInference: () => createCodeRuntimeInference,
|
|
46
|
+
createCodeRuntimeSessionSkillLoader: () => createCodeRuntimeSessionSkillLoader,
|
|
46
47
|
createCodeToolBroker: () => createCodeToolBroker,
|
|
47
48
|
createCodeWorkspaceCheckpoint: () => createCodeWorkspaceCheckpoint,
|
|
48
49
|
createContainerRecipeExecutor: () => createContainerRecipeExecutor,
|
|
@@ -79,6 +80,7 @@ __export(node_exports, {
|
|
|
79
80
|
safeWorkspaceLabel: () => safeWorkspaceLabel,
|
|
80
81
|
selectContainerEngine: () => selectContainerEngine,
|
|
81
82
|
selectWinner: () => selectWinner,
|
|
83
|
+
sessionSkillsFor: () => sessionSkillsFor,
|
|
82
84
|
stageWorkspace: () => stageWorkspace,
|
|
83
85
|
stageWorkspacePair: () => stageWorkspacePair,
|
|
84
86
|
straySubGoalFiles: () => straySubGoalFiles,
|
|
@@ -892,7 +894,7 @@ async function runHarnessRunner(options) {
|
|
|
892
894
|
} while (!options.signal?.aborted);
|
|
893
895
|
}
|
|
894
896
|
|
|
895
|
-
// src/code-runtime-client.ts
|
|
897
|
+
// src/code-runtime-client-validation.ts
|
|
896
898
|
var import_code = require("@odla-ai/camel/code");
|
|
897
899
|
var CodeRuntimeControlError = class extends Error {
|
|
898
900
|
constructor(message2, status, code = "control_error") {
|
|
@@ -904,101 +906,6 @@ var CodeRuntimeControlError = class extends Error {
|
|
|
904
906
|
code;
|
|
905
907
|
name = "CodeRuntimeControlError";
|
|
906
908
|
};
|
|
907
|
-
function createCodeRuntimeControlClient(options) {
|
|
908
|
-
const endpoint = validatedEndpoint(options.endpoint);
|
|
909
|
-
if (!/^odla_code_host_[0-9a-f]{64}$/.test(options.token)) throw new TypeError("invalid Code host credential");
|
|
910
|
-
const requestTimeoutMs = options.requestTimeoutMs ?? 3e4;
|
|
911
|
-
if (!Number.isSafeInteger(requestTimeoutMs) || requestTimeoutMs < 1e3 || requestTimeoutMs > 12e4) {
|
|
912
|
-
throw new TypeError("requestTimeoutMs must be an integer from 1000 to 120000");
|
|
913
|
-
}
|
|
914
|
-
const modelRequestTimeoutMs = options.modelRequestTimeoutMs ?? 15 * 6e4;
|
|
915
|
-
if (!Number.isSafeInteger(modelRequestTimeoutMs) || modelRequestTimeoutMs < 3e4 || modelRequestTimeoutMs > 30 * 6e4) {
|
|
916
|
-
throw new TypeError("modelRequestTimeoutMs must be an integer from 30000 to 1800000");
|
|
917
|
-
}
|
|
918
|
-
const request = options.fetch ?? fetch;
|
|
919
|
-
const call = async (path, body, timeoutMs = requestTimeoutMs) => {
|
|
920
|
-
const timeout = AbortSignal.timeout(timeoutMs);
|
|
921
|
-
const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
|
|
922
|
-
let response2;
|
|
923
|
-
try {
|
|
924
|
-
response2 = await request(`${endpoint}${path}`, {
|
|
925
|
-
method: "POST",
|
|
926
|
-
headers: { authorization: `Bearer ${options.token}`, "content-type": "application/json" },
|
|
927
|
-
body: JSON.stringify(body),
|
|
928
|
-
redirect: "error",
|
|
929
|
-
signal
|
|
930
|
-
});
|
|
931
|
-
} catch (cause) {
|
|
932
|
-
if (options.signal?.aborted) throw cause;
|
|
933
|
-
throw new CodeRuntimeControlError("Code runtime control plane is unavailable", 503, "transport_unavailable");
|
|
934
|
-
}
|
|
935
|
-
const value = await response2.json().catch(() => null);
|
|
936
|
-
if (!response2.ok) {
|
|
937
|
-
const problem = record2(record2(value)?.error);
|
|
938
|
-
throw new CodeRuntimeControlError(
|
|
939
|
-
typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
|
|
940
|
-
response2.status,
|
|
941
|
-
typeof problem?.code === "string" ? problem.code : void 0
|
|
942
|
-
);
|
|
943
|
-
}
|
|
944
|
-
return value;
|
|
945
|
-
};
|
|
946
|
-
return {
|
|
947
|
-
heartbeat: async (version, capabilities) => {
|
|
948
|
-
validateHeartbeat(version, capabilities);
|
|
949
|
-
return parseSnapshot(await call("/registry/code/runtime/heartbeat", { runtimeVersion: version, capabilities }));
|
|
950
|
-
},
|
|
951
|
-
acknowledge: async (commandId, result) => {
|
|
952
|
-
if (!/^ccmd_[0-9a-f]{32}$/.test(commandId)) throw new TypeError("invalid Code runtime command id");
|
|
953
|
-
await call(`/registry/code/runtime/commands/${commandId}/ack`, result);
|
|
954
|
-
},
|
|
955
|
-
source: async (sessionId) => parseSource(
|
|
956
|
-
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
|
|
957
|
-
),
|
|
958
|
-
infer: async (sessionId, inference) => {
|
|
959
|
-
const value = record2(await call(
|
|
960
|
-
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
|
|
961
|
-
inference,
|
|
962
|
-
modelRequestTimeoutMs
|
|
963
|
-
));
|
|
964
|
-
if (!value || value.requestId !== inference.requestId || !record2(value.response) || !record2(value.receipt)) {
|
|
965
|
-
throw new CodeRuntimeControlError("invalid Code inference response", 502, "invalid_response");
|
|
966
|
-
}
|
|
967
|
-
return value;
|
|
968
|
-
},
|
|
969
|
-
review: async (sessionId, review) => parseReview(
|
|
970
|
-
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/review`, review, modelRequestTimeoutMs)
|
|
971
|
-
),
|
|
972
|
-
submitCandidate: async (sessionId, checkpointId, verification) => {
|
|
973
|
-
if (!/^cpoint_[0-9a-f]{32}$/.test(checkpointId)) throw new TypeError("invalid Code checkpoint id");
|
|
974
|
-
return parseCandidate(await call(
|
|
975
|
-
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/candidates`,
|
|
976
|
-
{ checkpointId, verification }
|
|
977
|
-
));
|
|
978
|
-
},
|
|
979
|
-
appendSessionEvent: async (sessionId, eventId, event) => {
|
|
980
|
-
const serialized = JSON.stringify(event);
|
|
981
|
-
if (!/^[A-Za-z0-9._:-]{1,120}$/.test(eventId) || !event || typeof event !== "object" || new TextEncoder().encode(serialized).byteLength > 24e3) {
|
|
982
|
-
throw new TypeError("invalid Code session event");
|
|
983
|
-
}
|
|
984
|
-
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/chat/events`, { eventId, event });
|
|
985
|
-
},
|
|
986
|
-
recallMemories: async (sessionId, subjects, limit) => {
|
|
987
|
-
const response2 = await call(
|
|
988
|
-
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/recall`,
|
|
989
|
-
{ subjects: [...subjects], limit }
|
|
990
|
-
);
|
|
991
|
-
return Array.isArray(response2.memories) ? response2.memories : [];
|
|
992
|
-
},
|
|
993
|
-
rememberMemory: async (sessionId, memory) => {
|
|
994
|
-
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/remember`, memory);
|
|
995
|
-
},
|
|
996
|
-
reportSessionFailure: async (sessionId, message2) => {
|
|
997
|
-
if (!message2.trim() || message2.length > 2e3) throw new TypeError("invalid Code session failure");
|
|
998
|
-
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/failure`, { message: message2 });
|
|
999
|
-
}
|
|
1000
|
-
};
|
|
1001
|
-
}
|
|
1002
909
|
function validatedEndpoint(value) {
|
|
1003
910
|
const endpoint = value.replace(/\/+$/, "");
|
|
1004
911
|
let url;
|
|
@@ -1017,6 +924,10 @@ function validSessionId(value) {
|
|
|
1017
924
|
if (!/^csess_[0-9a-f]{32}$/.test(value)) throw new TypeError("invalid Code session id");
|
|
1018
925
|
return value;
|
|
1019
926
|
}
|
|
927
|
+
function validCommandId(value) {
|
|
928
|
+
if (!/^ccmd_[0-9a-f]{32}$/.test(value)) throw new TypeError("invalid Code runtime command id");
|
|
929
|
+
return value;
|
|
930
|
+
}
|
|
1020
931
|
function validateHeartbeat(version, capabilities) {
|
|
1021
932
|
if (!version.trim() || version.length > 80) throw new TypeError("runtimeVersion is required and at most 80 characters");
|
|
1022
933
|
if (capabilities.protocolVersion !== CODE_RUNTIME_PROTOCOL_VERSION) throw new TypeError("unsupported Code runtime protocol version");
|
|
@@ -1098,9 +1009,211 @@ function parseCandidate(value) {
|
|
|
1098
1009
|
}
|
|
1099
1010
|
return { candidateId: candidate.candidateId, status: candidate.status };
|
|
1100
1011
|
}
|
|
1012
|
+
function parseCollaborationSkills(value) {
|
|
1013
|
+
const items = record2(value)?.skills;
|
|
1014
|
+
if (!Array.isArray(items) || items.length > 16) throw invalid("collaboration skills");
|
|
1015
|
+
const skillNames = /* @__PURE__ */ new Set();
|
|
1016
|
+
const toolNames = /* @__PURE__ */ new Set();
|
|
1017
|
+
return items.map((item) => {
|
|
1018
|
+
const skill = record2(item);
|
|
1019
|
+
if (!skill || !validManifestName(skill.name) || skillNames.has(skill.name) || skill.instructions !== void 0 && (typeof skill.instructions !== "string" || utf8Bytes(skill.instructions) > 32e3) || !Array.isArray(skill.tools) || !skill.tools.length || skill.tools.length > 128) {
|
|
1020
|
+
throw invalid("collaboration skill");
|
|
1021
|
+
}
|
|
1022
|
+
skillNames.add(skill.name);
|
|
1023
|
+
const tools = skill.tools.map((candidate) => {
|
|
1024
|
+
const tool = record2(candidate);
|
|
1025
|
+
const inputSchema = record2(tool?.inputSchema);
|
|
1026
|
+
if (!tool || !validManifestName(tool.name) || toolNames.has(tool.name) || typeof tool.description !== "string" || utf8Bytes(tool.description) > 8e3 || !inputSchema || jsonBytes(inputSchema) > 64e3 || tool.concurrency !== void 0 && tool.concurrency !== "parallel") {
|
|
1027
|
+
throw invalid("collaboration tool");
|
|
1028
|
+
}
|
|
1029
|
+
const outputTaint = parseTaintLabels(tool.outputTaint);
|
|
1030
|
+
const acceptsTaint = parseTaintLabels(tool.acceptsTaint);
|
|
1031
|
+
toolNames.add(tool.name);
|
|
1032
|
+
return {
|
|
1033
|
+
name: tool.name,
|
|
1034
|
+
description: tool.description,
|
|
1035
|
+
inputSchema,
|
|
1036
|
+
...tool.concurrency === "parallel" ? { concurrency: "parallel" } : {},
|
|
1037
|
+
...outputTaint ? { outputTaint } : {},
|
|
1038
|
+
...acceptsTaint ? { acceptsTaint } : {}
|
|
1039
|
+
};
|
|
1040
|
+
});
|
|
1041
|
+
return {
|
|
1042
|
+
name: skill.name,
|
|
1043
|
+
...typeof skill.instructions === "string" ? { instructions: skill.instructions } : {},
|
|
1044
|
+
tools
|
|
1045
|
+
};
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
function validateCollaborationToolRequest(value) {
|
|
1049
|
+
validCommandId(value.commandId);
|
|
1050
|
+
if (typeof value.toolCallId !== "string" || value.toolCallId.length > 256 || !/^[^\s\u0000-\u001f\u007f]+$/.test(value.toolCallId) || !validManifestName(value.skill) || !validManifestName(value.tool) || !record2(value.input) || jsonBytes(value.input) > 128e3) {
|
|
1051
|
+
throw new TypeError("invalid Code collaboration tool request");
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
function parseCollaborationToolOutput(value) {
|
|
1055
|
+
const output = record2(record2(value)?.output);
|
|
1056
|
+
if (!output || output.isError !== void 0 && typeof output.isError !== "boolean") {
|
|
1057
|
+
throw invalid("collaboration tool");
|
|
1058
|
+
}
|
|
1059
|
+
if (typeof output.content === "string") {
|
|
1060
|
+
if (utf8Bytes(output.content) > 1e6) throw invalid("collaboration tool");
|
|
1061
|
+
return { content: output.content, ...output.isError === true ? { isError: true } : {} };
|
|
1062
|
+
}
|
|
1063
|
+
if (!Array.isArray(output.content) || output.content.length > 64 || jsonBytes(output.content) > 1e6 || !output.content.every((block) => {
|
|
1064
|
+
const item = record2(block);
|
|
1065
|
+
return item && ["text", "image", "audio", "document", "tool_use", "tool_result", "thinking"].includes(String(item.type));
|
|
1066
|
+
})) throw invalid("collaboration tool");
|
|
1067
|
+
return {
|
|
1068
|
+
content: output.content,
|
|
1069
|
+
...output.isError === true ? { isError: true } : {}
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
function parseTaintLabels(value) {
|
|
1073
|
+
if (value === void 0) return void 0;
|
|
1074
|
+
if (!Array.isArray(value) || value.length > 16) throw invalid("collaboration tool taint");
|
|
1075
|
+
const labels = value.map((item) => {
|
|
1076
|
+
if (item === "web_untrusted" || item === "operator_pasted_untrusted" || item === "llm_inherited") return item;
|
|
1077
|
+
if (typeof item === "string" && /^tool_untrusted:[^\s\u0000-\u001f\u007f]{1,100}$/.test(item)) {
|
|
1078
|
+
return item;
|
|
1079
|
+
}
|
|
1080
|
+
throw invalid("collaboration tool taint");
|
|
1081
|
+
});
|
|
1082
|
+
return [...new Set(labels)];
|
|
1083
|
+
}
|
|
1084
|
+
function validManifestName(value) {
|
|
1085
|
+
return typeof value === "string" && /^[A-Za-z][A-Za-z0-9._:-]{0,127}$/.test(value);
|
|
1086
|
+
}
|
|
1087
|
+
function utf8Bytes(value) {
|
|
1088
|
+
return new TextEncoder().encode(value).byteLength;
|
|
1089
|
+
}
|
|
1090
|
+
function jsonBytes(value) {
|
|
1091
|
+
try {
|
|
1092
|
+
return utf8Bytes(JSON.stringify(value));
|
|
1093
|
+
} catch {
|
|
1094
|
+
return Number.POSITIVE_INFINITY;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1101
1097
|
var record2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1102
1098
|
var invalid = (part) => new CodeRuntimeControlError(`invalid Code runtime ${part} response`, 502, "invalid_response");
|
|
1103
1099
|
|
|
1100
|
+
// src/code-runtime-client.ts
|
|
1101
|
+
function createCodeRuntimeControlClient(options) {
|
|
1102
|
+
const endpoint = validatedEndpoint(options.endpoint);
|
|
1103
|
+
if (!/^odla_code_host_[0-9a-f]{64}$/.test(options.token)) throw new TypeError("invalid Code host credential");
|
|
1104
|
+
const requestTimeoutMs = options.requestTimeoutMs ?? 3e4;
|
|
1105
|
+
if (!Number.isSafeInteger(requestTimeoutMs) || requestTimeoutMs < 1e3 || requestTimeoutMs > 12e4) {
|
|
1106
|
+
throw new TypeError("requestTimeoutMs must be an integer from 1000 to 120000");
|
|
1107
|
+
}
|
|
1108
|
+
const modelRequestTimeoutMs = options.modelRequestTimeoutMs ?? 15 * 6e4;
|
|
1109
|
+
if (!Number.isSafeInteger(modelRequestTimeoutMs) || modelRequestTimeoutMs < 3e4 || modelRequestTimeoutMs > 30 * 6e4) {
|
|
1110
|
+
throw new TypeError("modelRequestTimeoutMs must be an integer from 30000 to 1800000");
|
|
1111
|
+
}
|
|
1112
|
+
const request = options.fetch ?? fetch;
|
|
1113
|
+
const call = async (path, body, timeoutMs = requestTimeoutMs, operationSignal) => {
|
|
1114
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
1115
|
+
const signals = [options.signal, operationSignal, timeout].filter((item) => Boolean(item));
|
|
1116
|
+
const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
|
|
1117
|
+
let response2;
|
|
1118
|
+
try {
|
|
1119
|
+
response2 = await request(`${endpoint}${path}`, {
|
|
1120
|
+
method: "POST",
|
|
1121
|
+
headers: { authorization: `Bearer ${options.token}`, "content-type": "application/json" },
|
|
1122
|
+
body: JSON.stringify(body),
|
|
1123
|
+
redirect: "error",
|
|
1124
|
+
signal
|
|
1125
|
+
});
|
|
1126
|
+
} catch (cause) {
|
|
1127
|
+
if (options.signal?.aborted || operationSignal?.aborted) throw cause;
|
|
1128
|
+
throw new CodeRuntimeControlError("Code runtime control plane is unavailable", 503, "transport_unavailable");
|
|
1129
|
+
}
|
|
1130
|
+
const value = await response2.json().catch(() => null);
|
|
1131
|
+
if (!response2.ok) {
|
|
1132
|
+
const problem = record2(record2(value)?.error);
|
|
1133
|
+
throw new CodeRuntimeControlError(
|
|
1134
|
+
typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
|
|
1135
|
+
response2.status,
|
|
1136
|
+
typeof problem?.code === "string" ? problem.code : void 0
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
return value;
|
|
1140
|
+
};
|
|
1141
|
+
return {
|
|
1142
|
+
heartbeat: async (version, capabilities) => {
|
|
1143
|
+
validateHeartbeat(version, capabilities);
|
|
1144
|
+
return parseSnapshot(await call("/registry/code/runtime/heartbeat", { runtimeVersion: version, capabilities }));
|
|
1145
|
+
},
|
|
1146
|
+
acknowledge: async (commandId, result) => {
|
|
1147
|
+
await call(`/registry/code/runtime/commands/${validCommandId(commandId)}/ack`, result);
|
|
1148
|
+
},
|
|
1149
|
+
source: async (sessionId) => parseSource(
|
|
1150
|
+
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
|
|
1151
|
+
),
|
|
1152
|
+
infer: async (sessionId, inference) => {
|
|
1153
|
+
const value = record2(await call(
|
|
1154
|
+
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
|
|
1155
|
+
inference,
|
|
1156
|
+
modelRequestTimeoutMs
|
|
1157
|
+
));
|
|
1158
|
+
if (!value || value.requestId !== inference.requestId || !record2(value.response) || !record2(value.receipt)) {
|
|
1159
|
+
throw new CodeRuntimeControlError("invalid Code inference response", 502, "invalid_response");
|
|
1160
|
+
}
|
|
1161
|
+
return value;
|
|
1162
|
+
},
|
|
1163
|
+
review: async (sessionId, review) => parseReview(
|
|
1164
|
+
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/review`, review, modelRequestTimeoutMs)
|
|
1165
|
+
),
|
|
1166
|
+
submitCandidate: async (sessionId, checkpointId, verification) => {
|
|
1167
|
+
if (!/^cpoint_[0-9a-f]{32}$/.test(checkpointId)) throw new TypeError("invalid Code checkpoint id");
|
|
1168
|
+
return parseCandidate(await call(
|
|
1169
|
+
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/candidates`,
|
|
1170
|
+
{ checkpointId, verification }
|
|
1171
|
+
));
|
|
1172
|
+
},
|
|
1173
|
+
appendSessionEvent: async (sessionId, eventId, event) => {
|
|
1174
|
+
const serialized = JSON.stringify(event);
|
|
1175
|
+
if (!/^[A-Za-z0-9._:-]{1,120}$/.test(eventId) || !event || typeof event !== "object" || new TextEncoder().encode(serialized).byteLength > 24e3) {
|
|
1176
|
+
throw new TypeError("invalid Code session event");
|
|
1177
|
+
}
|
|
1178
|
+
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/chat/events`, { eventId, event });
|
|
1179
|
+
},
|
|
1180
|
+
recallMemories: async (sessionId, subjects, limit) => {
|
|
1181
|
+
const response2 = await call(
|
|
1182
|
+
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/recall`,
|
|
1183
|
+
{ subjects: [...subjects], limit }
|
|
1184
|
+
);
|
|
1185
|
+
return Array.isArray(response2.memories) ? response2.memories : [];
|
|
1186
|
+
},
|
|
1187
|
+
rememberMemory: async (sessionId, memory) => {
|
|
1188
|
+
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/remember`, memory);
|
|
1189
|
+
},
|
|
1190
|
+
collaborationSkills: async (sessionId, commandId) => {
|
|
1191
|
+
try {
|
|
1192
|
+
return parseCollaborationSkills(await call(
|
|
1193
|
+
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/collaboration/skills`,
|
|
1194
|
+
{ commandId: validCommandId(commandId) }
|
|
1195
|
+
));
|
|
1196
|
+
} catch (cause) {
|
|
1197
|
+
if (cause instanceof CodeRuntimeControlError && cause.status === 404 && cause.code === "not_found") return [];
|
|
1198
|
+
throw cause;
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
executeCollaborationTool: async (sessionId, collaboration, signal) => {
|
|
1202
|
+
validateCollaborationToolRequest(collaboration);
|
|
1203
|
+
return parseCollaborationToolOutput(await call(
|
|
1204
|
+
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/collaboration/tools`,
|
|
1205
|
+
collaboration,
|
|
1206
|
+
requestTimeoutMs,
|
|
1207
|
+
signal
|
|
1208
|
+
));
|
|
1209
|
+
},
|
|
1210
|
+
reportSessionFailure: async (sessionId, message2) => {
|
|
1211
|
+
if (!message2.trim() || message2.length > 2e3) throw new TypeError("invalid Code session failure");
|
|
1212
|
+
await call(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/failure`, { message: message2 });
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1104
1217
|
// src/code-runtime.ts
|
|
1105
1218
|
var CODE_RUNTIME_PROTOCOL_VERSION = 1;
|
|
1106
1219
|
async function runCodeRuntimeHeartbeatLoop(options) {
|
|
@@ -1127,12 +1240,14 @@ async function runCodeRuntimeHeartbeatLoop(options) {
|
|
|
1127
1240
|
} while (!options.signal?.aborted);
|
|
1128
1241
|
}
|
|
1129
1242
|
var CodeRuntimeReconciler = class {
|
|
1130
|
-
constructor(control, engine) {
|
|
1243
|
+
constructor(control, engine, onDiagnostic) {
|
|
1131
1244
|
this.control = control;
|
|
1132
1245
|
this.engine = engine;
|
|
1246
|
+
this.onDiagnostic = onDiagnostic;
|
|
1133
1247
|
}
|
|
1134
1248
|
control;
|
|
1135
1249
|
engine;
|
|
1250
|
+
onDiagnostic;
|
|
1136
1251
|
results = /* @__PURE__ */ new Map();
|
|
1137
1252
|
async reconcile(snapshot) {
|
|
1138
1253
|
for (const command of snapshot.commands) {
|
|
@@ -1150,7 +1265,13 @@ var CodeRuntimeReconciler = class {
|
|
|
1150
1265
|
}
|
|
1151
1266
|
await this.control.acknowledge(command.commandId, completed.result);
|
|
1152
1267
|
if (!completed.notified) {
|
|
1153
|
-
|
|
1268
|
+
try {
|
|
1269
|
+
await this.engine.acknowledged?.(command, completed.result);
|
|
1270
|
+
} catch (error) {
|
|
1271
|
+
this.onDiagnostic?.(
|
|
1272
|
+
`command ${command.commandId} acknowledged handling failed \xB7 ${error instanceof Error ? error.message : String(error)}`
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1154
1275
|
completed.notified = true;
|
|
1155
1276
|
}
|
|
1156
1277
|
}
|
|
@@ -2241,6 +2362,36 @@ Finish with a concise, non-empty answer to the owner. Do not call tools or promi
|
|
|
2241
2362
|
}
|
|
2242
2363
|
|
|
2243
2364
|
// src/code-runtime-session-skills.ts
|
|
2365
|
+
function createCodeRuntimeSessionSkillLoader(control) {
|
|
2366
|
+
const load = control.collaborationSkills?.bind(control);
|
|
2367
|
+
const execute2 = control.executeCollaborationTool?.bind(control);
|
|
2368
|
+
if (!load || !execute2) return async () => [];
|
|
2369
|
+
return async (command) => {
|
|
2370
|
+
const manifests = await load(command.sessionId, command.commandId);
|
|
2371
|
+
return manifests.map((manifest) => ({
|
|
2372
|
+
name: manifest.name,
|
|
2373
|
+
...manifest.instructions === void 0 ? {} : { instructions: manifest.instructions },
|
|
2374
|
+
tools: manifest.tools.map((tool) => ({
|
|
2375
|
+
name: tool.name,
|
|
2376
|
+
description: tool.description,
|
|
2377
|
+
inputSchema: tool.inputSchema,
|
|
2378
|
+
...tool.concurrency === void 0 ? {} : { concurrency: tool.concurrency },
|
|
2379
|
+
...tool.outputTaint === void 0 ? {} : { outputTaint: tool.outputTaint },
|
|
2380
|
+
...tool.acceptsTaint === void 0 ? {} : { acceptsTaint: tool.acceptsTaint },
|
|
2381
|
+
handler: async (input, context) => {
|
|
2382
|
+
if (!context.toolCallId) throw new TypeError("collaboration tool call identity is required");
|
|
2383
|
+
return execute2(command.sessionId, {
|
|
2384
|
+
commandId: command.commandId,
|
|
2385
|
+
toolCallId: context.toolCallId,
|
|
2386
|
+
skill: manifest.name,
|
|
2387
|
+
tool: tool.name,
|
|
2388
|
+
input
|
|
2389
|
+
}, context.signal);
|
|
2390
|
+
}
|
|
2391
|
+
}))
|
|
2392
|
+
}));
|
|
2393
|
+
};
|
|
2394
|
+
}
|
|
2244
2395
|
async function sessionSkillsFor(options, command) {
|
|
2245
2396
|
try {
|
|
2246
2397
|
return await options.sessionSkills?.(command) ?? [];
|
|
@@ -3470,6 +3621,76 @@ function codeToolResultPresentation(request, response2) {
|
|
|
3470
3621
|
};
|
|
3471
3622
|
}
|
|
3472
3623
|
|
|
3624
|
+
// src/code-runtime-acknowledgement-gate.ts
|
|
3625
|
+
function codeRuntimeAcknowledgementGate(signal) {
|
|
3626
|
+
let settle;
|
|
3627
|
+
let settled = false;
|
|
3628
|
+
const ready = new Promise((resolve7) => {
|
|
3629
|
+
settle = resolve7;
|
|
3630
|
+
});
|
|
3631
|
+
const release = (run) => {
|
|
3632
|
+
if (settled) return;
|
|
3633
|
+
settled = true;
|
|
3634
|
+
signal.removeEventListener("abort", onAbort);
|
|
3635
|
+
settle(run);
|
|
3636
|
+
};
|
|
3637
|
+
const onAbort = () => release(false);
|
|
3638
|
+
if (signal.aborted) release(false);
|
|
3639
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
3640
|
+
return { ready, release };
|
|
3641
|
+
}
|
|
3642
|
+
|
|
3643
|
+
// src/code-runtime-session-activity.ts
|
|
3644
|
+
function observeCodeRuntimeSessionSkills(command, skills, emit) {
|
|
3645
|
+
return skills.map((skill) => ({
|
|
3646
|
+
...skill,
|
|
3647
|
+
tools: skill.tools.map((tool) => {
|
|
3648
|
+
if (!tool.handler) return tool;
|
|
3649
|
+
const handler = tool.handler;
|
|
3650
|
+
return {
|
|
3651
|
+
...tool,
|
|
3652
|
+
handler: async (input, context) => {
|
|
3653
|
+
const startedAt = Date.now();
|
|
3654
|
+
const operationId = digestRuntimeValue(
|
|
3655
|
+
`${command.commandId}:${skill.name}:${tool.name}:${context.toolCallId ?? "missing"}`
|
|
3656
|
+
);
|
|
3657
|
+
await emit({
|
|
3658
|
+
type: "collaboration",
|
|
3659
|
+
phase: "started",
|
|
3660
|
+
skill: skill.name,
|
|
3661
|
+
tool: tool.name,
|
|
3662
|
+
operationId
|
|
3663
|
+
}).catch(() => void 0);
|
|
3664
|
+
try {
|
|
3665
|
+
const output = await handler(input, context);
|
|
3666
|
+
await emit({
|
|
3667
|
+
type: "collaboration",
|
|
3668
|
+
phase: "completed",
|
|
3669
|
+
skill: skill.name,
|
|
3670
|
+
tool: tool.name,
|
|
3671
|
+
operationId,
|
|
3672
|
+
ok: output.isError !== true,
|
|
3673
|
+
durationMs: Date.now() - startedAt
|
|
3674
|
+
}).catch(() => void 0);
|
|
3675
|
+
return output;
|
|
3676
|
+
} catch (cause) {
|
|
3677
|
+
await emit({
|
|
3678
|
+
type: "collaboration",
|
|
3679
|
+
phase: "completed",
|
|
3680
|
+
skill: skill.name,
|
|
3681
|
+
tool: tool.name,
|
|
3682
|
+
operationId,
|
|
3683
|
+
ok: false,
|
|
3684
|
+
durationMs: Date.now() - startedAt
|
|
3685
|
+
}).catch(() => void 0);
|
|
3686
|
+
throw cause;
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
};
|
|
3690
|
+
})
|
|
3691
|
+
}));
|
|
3692
|
+
}
|
|
3693
|
+
|
|
3473
3694
|
// src/code-runtime-engine.ts
|
|
3474
3695
|
var TheseusRuntimeEngine = class {
|
|
3475
3696
|
constructor(options) {
|
|
@@ -3500,6 +3721,8 @@ var TheseusRuntimeEngine = class {
|
|
|
3500
3721
|
const active = this.#active.get(command.sessionId);
|
|
3501
3722
|
if (!active || result.status !== "running") return;
|
|
3502
3723
|
active.acknowledged = true;
|
|
3724
|
+
active.startGate?.release(true);
|
|
3725
|
+
active.startGate = void 0;
|
|
3503
3726
|
if (active.failure) await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
|
|
3504
3727
|
}
|
|
3505
3728
|
async close() {
|
|
@@ -3519,13 +3742,14 @@ var TheseusRuntimeEngine = class {
|
|
|
3519
3742
|
control: this.options.control,
|
|
3520
3743
|
...this.options.localSource ? { localSource: this.options.localSource } : {}
|
|
3521
3744
|
});
|
|
3522
|
-
const abort = new AbortController();
|
|
3745
|
+
const abort = new AbortController(), startGate = codeRuntimeAcknowledgementGate(abort.signal);
|
|
3523
3746
|
const conversationRefs = [];
|
|
3524
3747
|
const active = {
|
|
3525
3748
|
workspace,
|
|
3526
3749
|
abort,
|
|
3527
3750
|
conversationRefs,
|
|
3528
3751
|
acknowledged: false,
|
|
3752
|
+
startGate,
|
|
3529
3753
|
role: metadata.role,
|
|
3530
3754
|
title: metadata.title,
|
|
3531
3755
|
maxTokensPerInteraction: metadata.maxTokensPerInteraction,
|
|
@@ -3549,7 +3773,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3549
3773
|
body: `Source snapshot: local checkout ${requestedLocal.snapshotDigest} \xB7 ${requestedLocal.modified ? "modified" : "clean"} \xB7 Git ${requestedLocal.headCommitSha}`
|
|
3550
3774
|
}, conversationRefs);
|
|
3551
3775
|
}
|
|
3552
|
-
active.done = this.#runAttempt(command, metadata, active).catch(async (cause) => {
|
|
3776
|
+
active.done = startGate.ready.then((run) => run ? this.#runAttempt(command, metadata, active) : null).catch(async (cause) => {
|
|
3553
3777
|
const detail = runtimeErrorMessage(cause);
|
|
3554
3778
|
await this.#event(command, { type: "message", actor: "system", body: detail }, conversationRefs).catch(() => void 0);
|
|
3555
3779
|
await this.#diagnostic(command, active, detail);
|
|
@@ -3664,7 +3888,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3664
3888
|
event: (event) => this.#event(command, event, active.conversationRefs)
|
|
3665
3889
|
});
|
|
3666
3890
|
await this.#event(command, { type: "status", status: "running" }, active.conversationRefs);
|
|
3667
|
-
const extraSkills = await sessionSkillsFor(this.options, command);
|
|
3891
|
+
const extraSkills = observeCodeRuntimeSessionSkills(command, await sessionSkillsFor(this.options, command), (event) => this.#event(command, event, active.conversationRefs));
|
|
3668
3892
|
const result = await this.#attempt({
|
|
3669
3893
|
inference,
|
|
3670
3894
|
broker,
|
|
@@ -4086,6 +4310,7 @@ async function installedDependencies(repoRoot) {
|
|
|
4086
4310
|
codeSkill,
|
|
4087
4311
|
createCodeRuntimeControlClient,
|
|
4088
4312
|
createCodeRuntimeInference,
|
|
4313
|
+
createCodeRuntimeSessionSkillLoader,
|
|
4089
4314
|
createCodeToolBroker,
|
|
4090
4315
|
createCodeWorkspaceCheckpoint,
|
|
4091
4316
|
createContainerRecipeExecutor,
|
|
@@ -4122,6 +4347,7 @@ async function installedDependencies(repoRoot) {
|
|
|
4122
4347
|
safeWorkspaceLabel,
|
|
4123
4348
|
selectContainerEngine,
|
|
4124
4349
|
selectWinner,
|
|
4350
|
+
sessionSkillsFor,
|
|
4125
4351
|
stageWorkspace,
|
|
4126
4352
|
stageWorkspacePair,
|
|
4127
4353
|
straySubGoalFiles,
|