@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.
Files changed (35) hide show
  1. package/README.md +11 -0
  2. package/dist/{chunk-IWVGSWY6.js → chunk-4EPJJMFG.js} +330 -106
  3. package/dist/chunk-4EPJJMFG.js.map +1 -0
  4. package/dist/{chunk-NWNBSX56.js → chunk-CIKYMC67.js} +4 -4
  5. package/dist/{chunk-CR6RE3A2.js → chunk-HDIR4MM5.js} +3 -3
  6. package/dist/{chunk-RXNHCGWE.js → chunk-I43KTCJ2.js} +1 -1
  7. package/dist/{chunk-RXNHCGWE.js.map → chunk-I43KTCJ2.js.map} +1 -1
  8. package/dist/{chunk-Q7CKOT7T.js → chunk-VGNIDRKM.js} +2 -2
  9. package/dist/cli.cjs.map +1 -1
  10. package/dist/cli.js +4 -4
  11. package/dist/code-runtime-cli.cjs +330 -102
  12. package/dist/code-runtime-cli.cjs.map +1 -1
  13. package/dist/code-runtime-cli.js +12 -5
  14. package/dist/code-runtime-cli.js.map +1 -1
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +2 -2
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +2 -2
  19. package/dist/node.cjs +327 -101
  20. package/dist/node.cjs.map +1 -1
  21. package/dist/node.d.cts +71 -17
  22. package/dist/node.d.ts +71 -17
  23. package/dist/node.js +9 -5
  24. package/dist/node.js.map +1 -1
  25. package/dist/testing.cjs.map +1 -1
  26. package/dist/testing.d.cts +1 -1
  27. package/dist/testing.d.ts +1 -1
  28. package/dist/testing.js +1 -1
  29. package/dist/{types-BNJikP5h.d.cts → types-BazqxWK8.d.cts} +14 -0
  30. package/dist/{types-BNJikP5h.d.ts → types-BazqxWK8.d.ts} +14 -0
  31. package/package.json +2 -2
  32. package/dist/chunk-IWVGSWY6.js.map +0 -1
  33. /package/dist/{chunk-NWNBSX56.js.map → chunk-CIKYMC67.js.map} +0 -0
  34. /package/dist/{chunk-CR6RE3A2.js.map → chunk-HDIR4MM5.js.map} +0 -0
  35. /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
- await this.engine.acknowledged?.(command, completed.result);
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,