mova_agent 0.1.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 (287) hide show
  1. package/README.md +94 -0
  2. package/build/scripts/check_docs.d.ts +2 -0
  3. package/build/scripts/check_docs.d.ts.map +1 -0
  4. package/build/scripts/check_docs.js +48 -0
  5. package/build/scripts/check_docs.js.map +1 -0
  6. package/build/scripts/check_schema_paths.d.ts +3 -0
  7. package/build/scripts/check_schema_paths.d.ts.map +1 -0
  8. package/build/scripts/check_schema_paths.js +15 -0
  9. package/build/scripts/check_schema_paths.js.map +1 -0
  10. package/build/scripts/check_schema_paths_dist.d.ts +3 -0
  11. package/build/scripts/check_schema_paths_dist.d.ts.map +1 -0
  12. package/build/scripts/check_schema_paths_dist.js +16 -0
  13. package/build/scripts/check_schema_paths_dist.js.map +1 -0
  14. package/build/scripts/check_structure.d.ts +2 -0
  15. package/build/scripts/check_structure.d.ts.map +1 -0
  16. package/build/scripts/check_structure.js +59 -0
  17. package/build/scripts/check_structure.js.map +1 -0
  18. package/build/scripts/debug_validate.d.ts +3 -0
  19. package/build/scripts/debug_validate.d.ts.map +1 -0
  20. package/build/scripts/debug_validate.js +39 -0
  21. package/build/scripts/debug_validate.js.map +1 -0
  22. package/build/scripts/debug_validate2.d.ts +3 -0
  23. package/build/scripts/debug_validate2.d.ts.map +1 -0
  24. package/build/scripts/debug_validate2.js +18 -0
  25. package/build/scripts/debug_validate2.js.map +1 -0
  26. package/build/scripts/debug_validate_runtime.d.ts +3 -0
  27. package/build/scripts/debug_validate_runtime.d.ts.map +1 -0
  28. package/build/scripts/debug_validate_runtime.js +39 -0
  29. package/build/scripts/debug_validate_runtime.js.map +1 -0
  30. package/build/scripts/dump_ajv_schemas.d.ts +2 -0
  31. package/build/scripts/dump_ajv_schemas.d.ts.map +1 -0
  32. package/build/scripts/dump_ajv_schemas.js +22 -0
  33. package/build/scripts/dump_ajv_schemas.js.map +1 -0
  34. package/build/scripts/dump_resolved_schema.d.ts +3 -0
  35. package/build/scripts/dump_resolved_schema.d.ts.map +1 -0
  36. package/build/scripts/dump_resolved_schema.js +22 -0
  37. package/build/scripts/dump_resolved_schema.js.map +1 -0
  38. package/build/scripts/gen_types.d.ts +2 -0
  39. package/build/scripts/gen_types.d.ts.map +1 -0
  40. package/build/scripts/gen_types.js +133 -0
  41. package/build/scripts/gen_types.js.map +1 -0
  42. package/build/scripts/inspect_validation.d.ts +3 -0
  43. package/build/scripts/inspect_validation.d.ts.map +1 -0
  44. package/build/scripts/inspect_validation.js +36 -0
  45. package/build/scripts/inspect_validation.js.map +1 -0
  46. package/build/scripts/legacy/check_errors.d.ts +3 -0
  47. package/build/scripts/legacy/check_errors.d.ts.map +1 -0
  48. package/build/scripts/legacy/check_errors.js +14 -0
  49. package/build/scripts/legacy/check_errors.js.map +1 -0
  50. package/build/scripts/legacy/compile_test.d.ts +5 -0
  51. package/build/scripts/legacy/compile_test.d.ts.map +1 -0
  52. package/build/scripts/legacy/compile_test.js +25 -0
  53. package/build/scripts/legacy/compile_test.js.map +1 -0
  54. package/build/scripts/legacy/debug_neg.d.ts +6 -0
  55. package/build/scripts/legacy/debug_neg.d.ts.map +1 -0
  56. package/build/scripts/legacy/debug_neg.js +230 -0
  57. package/build/scripts/legacy/debug_neg.js.map +1 -0
  58. package/build/scripts/legacy/debug_quality_pos.d.ts +5 -0
  59. package/build/scripts/legacy/debug_quality_pos.d.ts.map +1 -0
  60. package/build/scripts/legacy/debug_quality_pos.js +195 -0
  61. package/build/scripts/legacy/debug_quality_pos.js.map +1 -0
  62. package/build/scripts/legacy/debug_test.d.ts +1 -0
  63. package/build/scripts/legacy/debug_test.d.ts.map +1 -0
  64. package/build/scripts/legacy/debug_test.js +51 -0
  65. package/build/scripts/legacy/debug_test.js.map +1 -0
  66. package/build/scripts/legacy/hello_test.d.ts +1 -0
  67. package/build/scripts/legacy/hello_test.d.ts.map +1 -0
  68. package/build/scripts/legacy/hello_test.js +3 -0
  69. package/build/scripts/legacy/hello_test.js.map +1 -0
  70. package/build/scripts/legacy/import_test.d.ts +2 -0
  71. package/build/scripts/legacy/import_test.d.ts.map +1 -0
  72. package/build/scripts/legacy/import_test.js +4 -0
  73. package/build/scripts/legacy/import_test.js.map +1 -0
  74. package/build/scripts/legacy/quality_neg.d.ts +6 -0
  75. package/build/scripts/legacy/quality_neg.d.ts.map +1 -0
  76. package/build/scripts/legacy/quality_neg.js +362 -0
  77. package/build/scripts/legacy/quality_neg.js.map +1 -0
  78. package/build/scripts/legacy/quality_pos.d.ts +7 -0
  79. package/build/scripts/legacy/quality_pos.d.ts.map +1 -0
  80. package/build/scripts/legacy/quality_pos.js +345 -0
  81. package/build/scripts/legacy/quality_pos.js.map +1 -0
  82. package/build/scripts/legacy/simple_test.d.ts +2 -0
  83. package/build/scripts/legacy/simple_test.d.ts.map +1 -0
  84. package/build/scripts/legacy/simple_test.js +4 -0
  85. package/build/scripts/legacy/simple_test.js.map +1 -0
  86. package/build/scripts/legacy/test.d.ts +1 -0
  87. package/build/scripts/legacy/test.d.ts.map +1 -0
  88. package/build/scripts/legacy/test.js +3 -0
  89. package/build/scripts/legacy/test.js.map +1 -0
  90. package/build/scripts/legacy/test_additional_props.d.ts +6 -0
  91. package/build/scripts/legacy/test_additional_props.d.ts.map +1 -0
  92. package/build/scripts/legacy/test_additional_props.js +45 -0
  93. package/build/scripts/legacy/test_additional_props.js.map +1 -0
  94. package/build/scripts/legacy/test_ajv_validation.d.ts +2 -0
  95. package/build/scripts/legacy/test_ajv_validation.d.ts.map +1 -0
  96. package/build/scripts/legacy/test_ajv_validation.js +35 -0
  97. package/build/scripts/legacy/test_ajv_validation.js.map +1 -0
  98. package/build/scripts/legacy/test_build.d.ts +2 -0
  99. package/build/scripts/legacy/test_build.d.ts.map +1 -0
  100. package/build/scripts/legacy/test_build.js +14 -0
  101. package/build/scripts/legacy/test_build.js.map +1 -0
  102. package/build/scripts/legacy/test_direct.d.ts +3 -0
  103. package/build/scripts/legacy/test_direct.d.ts.map +1 -0
  104. package/build/scripts/legacy/test_direct.js +24 -0
  105. package/build/scripts/legacy/test_direct.js.map +1 -0
  106. package/build/scripts/legacy/test_import.d.ts +2 -0
  107. package/build/scripts/legacy/test_import.d.ts.map +1 -0
  108. package/build/scripts/legacy/test_import.js +7 -0
  109. package/build/scripts/legacy/test_import.js.map +1 -0
  110. package/build/scripts/legacy/test_mova_schemas.d.ts +2 -0
  111. package/build/scripts/legacy/test_mova_schemas.d.ts.map +1 -0
  112. package/build/scripts/legacy/test_mova_schemas.js +37 -0
  113. package/build/scripts/legacy/test_mova_schemas.js.map +1 -0
  114. package/build/scripts/legacy/test_scenario_integration.d.ts +13 -0
  115. package/build/scripts/legacy/test_scenario_integration.d.ts.map +1 -0
  116. package/build/scripts/legacy/test_scenario_integration.js +156 -0
  117. package/build/scripts/legacy/test_scenario_integration.js.map +1 -0
  118. package/build/scripts/legacy/test_schemas.d.ts +2 -0
  119. package/build/scripts/legacy/test_schemas.d.ts.map +1 -0
  120. package/build/scripts/legacy/test_schemas.js +48 -0
  121. package/build/scripts/legacy/test_schemas.js.map +1 -0
  122. package/build/scripts/legacy/test_schemas_simple.d.ts +2 -0
  123. package/build/scripts/legacy/test_schemas_simple.d.ts.map +1 -0
  124. package/build/scripts/legacy/test_schemas_simple.js +36 -0
  125. package/build/scripts/legacy/test_schemas_simple.js.map +1 -0
  126. package/build/scripts/legacy/test_simple.d.ts +4 -0
  127. package/build/scripts/legacy/test_simple.d.ts.map +1 -0
  128. package/build/scripts/legacy/test_simple.js +17 -0
  129. package/build/scripts/legacy/test_simple.js.map +1 -0
  130. package/build/scripts/legacy/test_warnings.d.ts +6 -0
  131. package/build/scripts/legacy/test_warnings.d.ts.map +1 -0
  132. package/build/scripts/legacy/test_warnings.js +48 -0
  133. package/build/scripts/legacy/test_warnings.js.map +1 -0
  134. package/build/scripts/legacy/very_simple_test.d.ts +1 -0
  135. package/build/scripts/legacy/very_simple_test.d.ts.map +1 -0
  136. package/build/scripts/legacy/very_simple_test.js +3 -0
  137. package/build/scripts/legacy/very_simple_test.js.map +1 -0
  138. package/build/scripts/merge_and_validate.d.ts +6 -0
  139. package/build/scripts/merge_and_validate.d.ts.map +1 -0
  140. package/build/scripts/merge_and_validate.js +53 -0
  141. package/build/scripts/merge_and_validate.js.map +1 -0
  142. package/build/src/ajv/ajv_loader.d.ts +47 -0
  143. package/build/src/ajv/ajv_loader.d.ts.map +1 -0
  144. package/build/src/ajv/ajv_loader.js +274 -0
  145. package/build/src/ajv/ajv_loader.js.map +1 -0
  146. package/build/src/ajv/schema_registry.d.ts +19 -0
  147. package/build/src/ajv/schema_registry.d.ts.map +1 -0
  148. package/build/src/ajv/schema_registry.js +121 -0
  149. package/build/src/ajv/schema_registry.js.map +1 -0
  150. package/build/src/drivers/__tests__/registry.test.d.ts +2 -0
  151. package/build/src/drivers/__tests__/registry.test.d.ts.map +1 -0
  152. package/build/src/drivers/__tests__/registry.test.js +100 -0
  153. package/build/src/drivers/__tests__/registry.test.js.map +1 -0
  154. package/build/src/drivers/httpDriver.d.ts +3 -0
  155. package/build/src/drivers/httpDriver.d.ts.map +1 -0
  156. package/build/src/drivers/httpDriver.js +76 -0
  157. package/build/src/drivers/httpDriver.js.map +1 -0
  158. package/build/src/drivers/index.d.ts +20 -0
  159. package/build/src/drivers/index.d.ts.map +1 -0
  160. package/build/src/drivers/index.js +33 -0
  161. package/build/src/drivers/index.js.map +1 -0
  162. package/build/src/drivers/restrictedShellDriver.d.ts +12 -0
  163. package/build/src/drivers/restrictedShellDriver.d.ts.map +1 -0
  164. package/build/src/drivers/restrictedShellDriver.js +88 -0
  165. package/build/src/drivers/restrictedShellDriver.js.map +1 -0
  166. package/build/src/episodes/__tests__/episode_writer_atomic.test.d.ts +2 -0
  167. package/build/src/episodes/__tests__/episode_writer_atomic.test.d.ts.map +1 -0
  168. package/build/src/episodes/__tests__/episode_writer_atomic.test.js +86 -0
  169. package/build/src/episodes/__tests__/episode_writer_atomic.test.js.map +1 -0
  170. package/build/src/episodes/episode_writer.d.ts +100 -0
  171. package/build/src/episodes/episode_writer.d.ts.map +1 -0
  172. package/build/src/episodes/episode_writer.js +503 -0
  173. package/build/src/episodes/episode_writer.js.map +1 -0
  174. package/build/src/episodes/episode_writer_atomic.d.ts +10 -0
  175. package/build/src/episodes/episode_writer_atomic.d.ts.map +1 -0
  176. package/build/src/episodes/episode_writer_atomic.js +46 -0
  177. package/build/src/episodes/episode_writer_atomic.js.map +1 -0
  178. package/build/src/evidence/evidence_writer.d.ts +16 -0
  179. package/build/src/evidence/evidence_writer.d.ts.map +1 -0
  180. package/build/src/evidence/evidence_writer.js +78 -0
  181. package/build/src/evidence/evidence_writer.js.map +1 -0
  182. package/build/src/handlers/registry.d.ts +20 -0
  183. package/build/src/handlers/registry.d.ts.map +1 -0
  184. package/build/src/handlers/registry.js +38 -0
  185. package/build/src/handlers/registry.js.map +1 -0
  186. package/build/src/interpreter/interpreter.d.ts +90 -0
  187. package/build/src/interpreter/interpreter.d.ts.map +1 -0
  188. package/build/src/interpreter/interpreter.js +732 -0
  189. package/build/src/interpreter/interpreter.js.map +1 -0
  190. package/build/src/interpreter/interpreter_with_budget.d.ts +92 -0
  191. package/build/src/interpreter/interpreter_with_budget.d.ts.map +1 -0
  192. package/build/src/interpreter/interpreter_with_budget.js +678 -0
  193. package/build/src/interpreter/interpreter_with_budget.js.map +1 -0
  194. package/build/src/logging/logger.d.ts +83 -0
  195. package/build/src/logging/logger.d.ts.map +1 -0
  196. package/build/src/logging/logger.js +226 -0
  197. package/build/src/logging/logger.js.map +1 -0
  198. package/build/src/policy/policy_engine.d.ts +116 -0
  199. package/build/src/policy/policy_engine.d.ts.map +1 -0
  200. package/build/src/policy/policy_engine.js +296 -0
  201. package/build/src/policy/policy_engine.js.map +1 -0
  202. package/build/src/skills/skills_layer.d.ts +94 -0
  203. package/build/src/skills/skills_layer.d.ts.map +1 -0
  204. package/build/src/skills/skills_layer.js +405 -0
  205. package/build/src/skills/skills_layer.js.map +1 -0
  206. package/build/src/telemetry/token_budget_enforcer.d.ts +113 -0
  207. package/build/src/telemetry/token_budget_enforcer.d.ts.map +1 -0
  208. package/build/src/telemetry/token_budget_enforcer.js +253 -0
  209. package/build/src/telemetry/token_budget_enforcer.js.map +1 -0
  210. package/build/src/telemetry/token_budget_loader.d.ts +29 -0
  211. package/build/src/telemetry/token_budget_loader.d.ts.map +1 -0
  212. package/build/src/telemetry/token_budget_loader.js +112 -0
  213. package/build/src/telemetry/token_budget_loader.js.map +1 -0
  214. package/build/src/telemetry/token_meter.d.ts +65 -0
  215. package/build/src/telemetry/token_meter.d.ts.map +1 -0
  216. package/build/src/telemetry/token_meter.js +153 -0
  217. package/build/src/telemetry/token_meter.js.map +1 -0
  218. package/build/src/ux/cli_interface.d.ts +85 -0
  219. package/build/src/ux/cli_interface.d.ts.map +1 -0
  220. package/build/src/ux/cli_interface.js +651 -0
  221. package/build/src/ux/cli_interface.js.map +1 -0
  222. package/build/test/drivers/registry.test.d.ts +2 -0
  223. package/build/test/drivers/registry.test.d.ts.map +1 -0
  224. package/build/test/drivers/registry.test.js +100 -0
  225. package/build/test/drivers/registry.test.js.map +1 -0
  226. package/build/test/episodes/episode_writer_atomic.test.d.ts +2 -0
  227. package/build/test/episodes/episode_writer_atomic.test.d.ts.map +1 -0
  228. package/build/test/episodes/episode_writer_atomic.test.js +86 -0
  229. package/build/test/episodes/episode_writer_atomic.test.js.map +1 -0
  230. package/build/tests/ajv/check_schemas.d.ts +4 -0
  231. package/build/tests/ajv/check_schemas.d.ts.map +1 -0
  232. package/build/tests/ajv/check_schemas.js +27 -0
  233. package/build/tests/ajv/check_schemas.js.map +1 -0
  234. package/build/tests/ajv/final_test.d.ts +2 -0
  235. package/build/tests/ajv/final_test.d.ts.map +1 -0
  236. package/build/tests/ajv/final_test.js +42 -0
  237. package/build/tests/ajv/final_test.js.map +1 -0
  238. package/build/tests/ajv/simple_test.d.ts +2 -0
  239. package/build/tests/ajv/simple_test.d.ts.map +1 -0
  240. package/build/tests/ajv/simple_test.js +40 -0
  241. package/build/tests/ajv/simple_test.js.map +1 -0
  242. package/build/tests/ajv/test_schema_loading.d.ts +2 -0
  243. package/build/tests/ajv/test_schema_loading.d.ts.map +1 -0
  244. package/build/tests/ajv/test_schema_loading.js +39 -0
  245. package/build/tests/ajv/test_schema_loading.js.map +1 -0
  246. package/build/tools/mova-agent.d.ts +2 -0
  247. package/build/tools/mova-agent.d.ts.map +1 -0
  248. package/build/tools/mova-agent.js +15 -0
  249. package/build/tools/mova-agent.js.map +1 -0
  250. package/package.json +63 -0
  251. package/src/ajv/ajv_loader.ts +311 -0
  252. package/src/ajv/schema_registry.ts +92 -0
  253. package/src/drivers/httpDriver.ts +90 -0
  254. package/src/drivers/index.ts +48 -0
  255. package/src/drivers/restrictedShellDriver.ts +68 -0
  256. package/src/episodes/episode_writer.ts +675 -0
  257. package/src/episodes/episode_writer_atomic.ts +44 -0
  258. package/src/evidence/evidence_writer.ts +74 -0
  259. package/src/handlers/registry.ts +53 -0
  260. package/src/interpreter/interpreter.ts +1009 -0
  261. package/src/interpreter/interpreter_with_budget.ts +923 -0
  262. package/src/logging/logger.ts +269 -0
  263. package/src/policy/policy_engine.ts +395 -0
  264. package/src/skills/skills_layer.ts +510 -0
  265. package/src/telemetry/token_budget_enforcer.ts +338 -0
  266. package/src/telemetry/token_budget_loader.ts +133 -0
  267. package/src/telemetry/token_meter.ts +185 -0
  268. package/src/types/generated/ds.connector_core_v1.d.ts +116 -0
  269. package/src/types/generated/ds.instruction_profile_core_v1.d.ts +141 -0
  270. package/src/types/generated/ds.mova4_core_catalog_v1.d.ts +80 -0
  271. package/src/types/generated/ds.mova_agent_run_summary_v1.d.ts +120 -0
  272. package/src/types/generated/ds.mova_agent_step_v1.d.ts +53 -0
  273. package/src/types/generated/ds.mova_agent_tool_pool_v1.d.ts +152 -0
  274. package/src/types/generated/ds.mova_agent_validation_report_v1.d.ts +43 -0
  275. package/src/types/generated/ds.mova_episode_core_v1.d.ts +56 -0
  276. package/src/types/generated/ds.mova_schema_core_v1.d.ts +49 -0
  277. package/src/types/generated/ds.mova_token_budget_contract_v0.d.ts +140 -0
  278. package/src/types/generated/ds.runtime_binding_core_v1.d.ts +112 -0
  279. package/src/types/generated/ds.security_event_episode_core_v1.d.ts +138 -0
  280. package/src/types/generated/ds.ui_text_bundle_core_v1.d.ts +118 -0
  281. package/src/types/generated/env.instruction_profile_publish_v1.d.ts +159 -0
  282. package/src/types/generated/env.mova4_core_catalog_publish_v1.d.ts +25 -0
  283. package/src/types/generated/env.mova_agent_plan_v1.d.ts +40 -0
  284. package/src/types/generated/env.mova_agent_request_v1.d.ts +43 -0
  285. package/src/types/generated/env.security_event_store_v1.d.ts +191 -0
  286. package/src/types/generated/index.d.ts +25 -0
  287. package/src/ux/cli_interface.ts +719 -0
@@ -0,0 +1,732 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Interpreter = void 0;
7
+ const ajv_loader_1 = require("../ajv/ajv_loader");
8
+ const schema_registry_1 = require("../ajv/schema_registry");
9
+ const registry_1 = require("../handlers/registry");
10
+ const evidence_writer_1 = require("../evidence/evidence_writer");
11
+ const episode_writer_1 = require("../episodes/episode_writer");
12
+ const policy_engine_1 = require("../policy/policy_engine");
13
+ const crypto_1 = require("crypto");
14
+ const token_meter_1 = require("../telemetry/token_meter");
15
+ const token_budget_enforcer_1 = require("../telemetry/token_budget_enforcer");
16
+ const token_budget_loader_1 = require("../telemetry/token_budget_loader");
17
+ const logger_1 = require("../logging/logger");
18
+ const path_1 = __importDefault(require("path"));
19
+ /**
20
+ * Основной интерпретатор планов MOVA Agent
21
+ */
22
+ class Interpreter {
23
+ evidenceWriter;
24
+ episodeWriter; // Base episode writer
25
+ policyEngine;
26
+ tokenBudgetLoader;
27
+ schemaInitializationPromise;
28
+ constructor() {
29
+ this.evidenceWriter = new evidence_writer_1.EvidenceWriter();
30
+ this.episodeWriter = new episode_writer_1.EpisodeWriter();
31
+ this.policyEngine = new policy_engine_1.PolicyEngine();
32
+ this.tokenBudgetLoader = new token_budget_loader_1.TokenBudgetLoader();
33
+ // Initialize schemas and track the promise
34
+ this.schemaInitializationPromise = this.initializeSchemas();
35
+ }
36
+ /**
37
+ * Wait for the interpreter to be fully initialized with all schemas
38
+ */
39
+ async ready() {
40
+ await this.schemaInitializationPromise;
41
+ }
42
+ async initializeSchemas() {
43
+ try {
44
+ const registry = new schema_registry_1.SchemaRegistry(ajv_loader_1.ajvLoader);
45
+ await registry.loadAllSchemas(); // Load both MOVA and local schemas
46
+ }
47
+ catch (error) {
48
+ (0, logger_1.getLogger)().info(`Warning: Could not initialize schema registry: ${error.message}`);
49
+ }
50
+ }
51
+ /**
52
+ * Основной метод запуска выполнения плана
53
+ */
54
+ async runPlan(params) {
55
+ // Wait for schema initialization to complete
56
+ await this.ready();
57
+ const { planEnvelope, toolPool, instructionProfile, tokenBudgetPath, tokenBudgetProfile } = params;
58
+ try {
59
+ // Load token budget contract
60
+ const tokenBudgetContract = await this.tokenBudgetLoader.load(tokenBudgetPath, tokenBudgetProfile);
61
+ // Set tool pool and instruction profile in policy engine for enforcement
62
+ this.policyEngine.setToolPool(toolPool);
63
+ this.policyEngine.setInstructionProfile(instructionProfile);
64
+ // 1) Ajv validate plan envelope
65
+ const planValidation = await (0, ajv_loader_1.validate)('env.mova_agent_plan_v1', planEnvelope);
66
+ if (!planValidation.ok) {
67
+ const error = `Plan validation failed: ${planValidation.errors?.join(', ')}`;
68
+ await this.recordSecurityEvent('validation_failed', { error, planEnvelope });
69
+ return { success: false, error };
70
+ }
71
+ // 2) Ajv validate tool pool
72
+ // Note: Since we don't have a specific schema for the full tool pool structure yet,
73
+ // we'll validate individual tools as we encounter them
74
+ if (!toolPool || !toolPool.tools || !Array.isArray(toolPool.tools)) {
75
+ const error = 'Invalid tool pool structure';
76
+ await this.recordSecurityEvent('validation_failed', { error, toolPool });
77
+ return { success: false, error };
78
+ }
79
+ // 3) Validate instruction profile with deny-by-default policy
80
+ const profileValidation = this.validateInstructionProfile(instructionProfile);
81
+ if (!profileValidation.ok) {
82
+ const error = `Instruction profile validation failed: ${profileValidation.errors?.join(', ')}`;
83
+ await this.recordSecurityEvent('validation_failed', { error, instructionProfile });
84
+ return { success: false, error };
85
+ }
86
+ // 4) Build an execution context
87
+ const runId = `run_${(0, crypto_1.randomUUID)()}`;
88
+ const requestId = `req_${(0, crypto_1.randomUUID)()}`;
89
+ const evidenceDir = await this.evidenceWriter.createRunDirectory(requestId, runId);
90
+ // Create run-specific episode writer
91
+ const runEpisodeWriter = this.episodeWriter.createRunWriter(requestId, runId);
92
+ // Initialize token meter and budget enforcer
93
+ const tokenMeter = new token_meter_1.TokenMeter(evidenceDir);
94
+ const tokenBudgetEnforcer = new token_budget_enforcer_1.TokenBudgetEnforcer(tokenBudgetContract, tokenMeter);
95
+ // Save the resolved token budget contract
96
+ this.tokenBudgetLoader.saveResolvedContract(tokenBudgetContract, evidenceDir);
97
+ const context = {
98
+ run_id: runId,
99
+ request_id: requestId,
100
+ evidence_dir: evidenceDir,
101
+ instructionProfile: instructionProfile,
102
+ caps: instructionProfile.caps,
103
+ redaction_rules: instructionProfile.redaction_rules,
104
+ step_inputs: new Map(),
105
+ step_outputs: new Map(),
106
+ step_bindings: new Map(),
107
+ current_step_index: 0,
108
+ step_security_events: [],
109
+ has_fatal_security_event: false,
110
+ episodeWriter: runEpisodeWriter,
111
+ tokenMeter,
112
+ tokenBudgetEnforcer,
113
+ budgetStatus: 'passed',
114
+ budgetViolations: [],
115
+ };
116
+ // Write initial artifacts
117
+ await this.evidenceWriter.writeArtifact(evidenceDir, 'request.envelope.json', params.requestEnvelope || {});
118
+ await this.evidenceWriter.writeArtifact(evidenceDir, 'plan.envelope.json', planEnvelope);
119
+ await this.evidenceWriter.writeArtifact(evidenceDir, 'tool_pool.resolved.json', toolPool);
120
+ await this.evidenceWriter.writeArtifact(evidenceDir, 'instruction_profile.resolved.json', instructionProfile);
121
+ // 5) Execute steps in order
122
+ let executionError;
123
+ try {
124
+ for (const step of planEnvelope.payload.steps) {
125
+ // Check if we can execute this step based on token budget
126
+ const budgetStatus = context.tokenBudgetEnforcer.checkModelCall();
127
+ if (budgetStatus.exceeded) {
128
+ // Handle budget violation
129
+ context.budgetStatus = budgetStatus.action === 'fail' ? 'failed' : 'warned';
130
+ context.budgetViolations.push(...budgetStatus.violations);
131
+ // Create budget violation episodes for each violation
132
+ for (const violation of budgetStatus.violations) {
133
+ const budgetViolationEpisode = context.tokenBudgetEnforcer.createBudgetViolationEpisode(violation, {
134
+ run_id: context.run_id,
135
+ request_id: context.request_id,
136
+ step_id: step.id,
137
+ });
138
+ await context.episodeWriter.writeSecurityEvent(budgetViolationEpisode);
139
+ }
140
+ if (budgetStatus.action === 'fail') {
141
+ executionError = `Budget exceeded: ${budgetStatus.violations.map((v) => v.message).join('; ')}`;
142
+ break;
143
+ }
144
+ else if (budgetStatus.action === 'warn') {
145
+ (0, logger_1.getLogger)().info(`Budget warning: ${budgetStatus.violations.map((v) => v.message).join('; ')}`);
146
+ }
147
+ }
148
+ const stepResult = await this.executeStep(step, context, toolPool);
149
+ if (!stepResult.success && step.on_error !== 'soft') {
150
+ // Step failed and is marked as fatal
151
+ executionError = `Step ${step.id} failed: ${stepResult.error}`;
152
+ break; // Exit the loop on fatal error
153
+ }
154
+ // Store output for potential use by subsequent steps
155
+ if (stepResult.output) {
156
+ context.step_outputs.set(step.id, stepResult.output);
157
+ }
158
+ }
159
+ // 6) Emit final run summary episode and return structured result
160
+ // Check if there were any fatal security events or execution errors
161
+ const finalStatus = context.has_fatal_security_event || executionError ? 'failed' : 'completed';
162
+ const finalError = context.has_fatal_security_event
163
+ ? 'Fatal security event occurred during execution'
164
+ : executionError;
165
+ const runSummary = await this.createRunSummary(context, finalStatus, finalError);
166
+ await this.evidenceWriter.writeArtifact(evidenceDir, 'run_summary.json', runSummary);
167
+ // Create a final execution episode for the overall run
168
+ await context.episodeWriter.writeExecutionEpisode({
169
+ episode_type: 'execution_run_summary',
170
+ result_status: finalStatus,
171
+ result_summary: finalError ? `Run failed: ${finalError}` : 'Run completed successfully',
172
+ input_data_refs: [
173
+ {
174
+ data_type: 'ds.mova_agent_plan_v1',
175
+ data_id: planEnvelope.payload.steps.length > 0
176
+ ? planEnvelope.payload.steps[0].id
177
+ : 'unknown',
178
+ },
179
+ ],
180
+ payload: {
181
+ run_id: context.run_id,
182
+ request_id: context.request_id,
183
+ total_steps: planEnvelope.payload.steps.length,
184
+ steps_completed: context.step_outputs.size,
185
+ status: finalStatus,
186
+ error: finalError,
187
+ },
188
+ });
189
+ return {
190
+ success: !context.has_fatal_security_event && !executionError,
191
+ run_summary: runSummary,
192
+ };
193
+ }
194
+ finally {
195
+ // Always save token usage report in the evidence directory, even if execution fails
196
+ // Determine if this is a quality suite run based on the evidence directory path
197
+ const isQualitySuite = evidenceDir.includes('quality');
198
+ context.tokenMeter.saveReport(path_1.default.join(evidenceDir, 'token_usage.json'), isQualitySuite ? 'quality suite uses noop handlers' : undefined);
199
+ }
200
+ }
201
+ catch (error) {
202
+ const errorMessage = `Unexpected error during plan execution: ${error.message}`;
203
+ // We don't have context here, so we'll call without it
204
+ await this.recordSecurityEvent('execution_error', {
205
+ error: errorMessage,
206
+ stack: error.stack,
207
+ });
208
+ return { success: false, error: errorMessage };
209
+ }
210
+ }
211
+ /**
212
+ * Выполнить один шаг плана
213
+ */
214
+ async executeStep(step, context, toolPool) {
215
+ try {
216
+ // a) Resolve input
217
+ let input = step.input;
218
+ if (step.input_from) {
219
+ const referencedStepId = step.input_from.step_id;
220
+ if (!context.step_outputs.has(referencedStepId)) {
221
+ throw new Error(`Input references non-existent step: ${referencedStepId}`);
222
+ }
223
+ const referencedOutput = context.step_outputs.get(referencedStepId);
224
+ if (step.input_from.path) {
225
+ // Simple path resolution - in a real implementation this would be more sophisticated
226
+ input = this.resolvePath(referencedOutput, step.input_from.path);
227
+ }
228
+ else {
229
+ input = referencedOutput;
230
+ }
231
+ }
232
+ // b) Validate input schema (if provided)
233
+ if (step.expected_output_schema_ref && input) {
234
+ const inputValidation = await (0, ajv_loader_1.validate)(step.expected_output_schema_ref, input);
235
+ if (!inputValidation.ok) {
236
+ const error = `Step input validation failed: ${inputValidation.errors?.join(', ')}`;
237
+ // Emit failure episode using MOVA 4.1.1 format
238
+ await context.episodeWriter.writeExecutionEpisode({
239
+ episode_type: 'execution_step',
240
+ result_status: 'failed',
241
+ result_summary: `Step ${step.id} failed: ${error}`,
242
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
243
+ payload: {
244
+ step_id: step.id,
245
+ error: error,
246
+ status: 'failed',
247
+ },
248
+ });
249
+ await this.recordSecurityEvent('input_validation_failed', { step_id: step.id, error, input }, context);
250
+ return { success: false, error };
251
+ }
252
+ }
253
+ // c) Policy checks using the policy engine
254
+ const tool = toolPool.tools.find((t) => t.id === step.connector_id);
255
+ if (!tool) {
256
+ const error = `Tool not found in pool: ${step.connector_id}`;
257
+ // Emit failure episode using MOVA 4.1.1 format
258
+ await context.episodeWriter.writeExecutionEpisode({
259
+ episode_type: 'execution_step',
260
+ result_status: 'failed',
261
+ result_summary: `Step ${step.id} failed: ${error}`,
262
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
263
+ payload: {
264
+ step_id: step.id,
265
+ error: error,
266
+ status: 'failed',
267
+ },
268
+ });
269
+ await this.recordSecurityEvent('tool_not_allowlisted', { step_id: step.id, error, connector_id: step.connector_id }, context);
270
+ return { success: false, error };
271
+ }
272
+ // Perform comprehensive policy check
273
+ const policyEvaluation = this.policyEngine.evaluateStepComprehensive({
274
+ id: step.id,
275
+ verb: step.verb,
276
+ connector_id: step.connector_id,
277
+ input: input,
278
+ tool_binding: tool.binding,
279
+ });
280
+ if (!policyEvaluation.allowed) {
281
+ const error = `Step failed policy evaluation: ${policyEvaluation.reason}`;
282
+ // Emit failure episode using MOVA 4.1.1 format
283
+ await context.episodeWriter.writeExecutionEpisode({
284
+ episode_type: 'execution_step',
285
+ result_status: 'failed',
286
+ result_summary: `Step ${step.id} failed: ${error}`,
287
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
288
+ payload: {
289
+ step_id: step.id,
290
+ error: error,
291
+ status: 'failed',
292
+ },
293
+ });
294
+ await this.recordSecurityEvent('policy_check_failed', {
295
+ step_id: step.id,
296
+ error,
297
+ policy_reason: policyEvaluation.reason,
298
+ input,
299
+ binding: tool.binding,
300
+ }, context);
301
+ return { success: false, error };
302
+ }
303
+ // Additional specific checks for destinations
304
+ if (input && (input.url || input.endpoint)) {
305
+ const destUrl = input.url || input.endpoint;
306
+ const allowlist = tool.binding.destination_allowlist;
307
+ if (allowlist && allowlist.length > 0) {
308
+ const isAllowed = allowlist.some((allowed) => {
309
+ try {
310
+ const inputUrl = new URL(destUrl);
311
+ const allowedUrl = new URL(allowed);
312
+ return (inputUrl.hostname === allowedUrl.hostname &&
313
+ inputUrl.protocol === allowedUrl.protocol &&
314
+ (inputUrl.port === allowedUrl.port || allowedUrl.port === ''));
315
+ }
316
+ catch {
317
+ return false; // If we can't parse the URL, consider it not allowed
318
+ }
319
+ });
320
+ if (!isAllowed) {
321
+ const error = `Destination not allowlisted: ${destUrl}`;
322
+ // Emit failure episode using MOVA 4.1.1 format
323
+ await context.episodeWriter.writeExecutionEpisode({
324
+ episode_type: 'execution_step',
325
+ result_status: 'failed',
326
+ result_summary: `Step ${step.id} failed: ${error}`,
327
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
328
+ payload: {
329
+ step_id: step.id,
330
+ error: error,
331
+ status: 'failed',
332
+ },
333
+ });
334
+ await this.recordSecurityEvent('destination_not_allowlisted', {
335
+ step_id: step.id,
336
+ error,
337
+ destination: destUrl,
338
+ allowed_destinations: allowlist,
339
+ }, context);
340
+ return { success: false, error };
341
+ }
342
+ }
343
+ }
344
+ // Check limits are present (already checked in policy engine, but keeping as extra safeguard)
345
+ if (!tool.binding.limits || !tool.binding.limits.timeout_ms) {
346
+ const error = `Required limits not specified for tool: ${step.connector_id}`;
347
+ // Emit failure episode using MOVA 4.1.1 format
348
+ await context.episodeWriter.writeExecutionEpisode({
349
+ episode_type: 'execution_step',
350
+ result_status: 'failed',
351
+ result_summary: `Step ${step.id} failed: ${error}`,
352
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
353
+ payload: {
354
+ step_id: step.id,
355
+ error: error,
356
+ status: 'failed',
357
+ },
358
+ });
359
+ await this.recordSecurityEvent('limits_not_specified', { step_id: step.id, error, connector_id: step.connector_id }, context);
360
+ return { success: false, error };
361
+ }
362
+ // Check tool call budget
363
+ const toolBudgetStatus = context.tokenBudgetEnforcer.checkToolCall();
364
+ if (toolBudgetStatus.exceeded) {
365
+ // Handle budget violation
366
+ context.budgetStatus = toolBudgetStatus.action === 'fail' ? 'failed' : 'warned';
367
+ context.budgetViolations.push(...toolBudgetStatus.violations);
368
+ // Create budget violation episodes for each violation
369
+ for (const violation of toolBudgetStatus.violations) {
370
+ const budgetViolationEpisode = context.tokenBudgetEnforcer.createBudgetViolationEpisode(violation, { run_id: context.run_id, request_id: context.request_id, step_id: step.id });
371
+ await context.episodeWriter.writeSecurityEvent(budgetViolationEpisode);
372
+ }
373
+ if (toolBudgetStatus.action === 'fail') {
374
+ const error = `Tool call budget exceeded: ${toolBudgetStatus.violations.map((v) => v.message).join('; ')}`;
375
+ // Emit failure episode using MOVA 4.1.1 format
376
+ await context.episodeWriter.writeExecutionEpisode({
377
+ episode_type: 'execution_step',
378
+ result_status: 'failed',
379
+ result_summary: `Step ${step.id} failed: ${error}`,
380
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
381
+ payload: {
382
+ step_id: step.id,
383
+ error: error,
384
+ status: 'failed',
385
+ },
386
+ });
387
+ return { success: false, error };
388
+ }
389
+ else if (toolBudgetStatus.action === 'warn') {
390
+ (0, logger_1.getLogger)().info(`Tool call budget warning: ${toolBudgetStatus.violations.map((v) => v.message).join('; ')}`);
391
+ }
392
+ }
393
+ // d) Dispatch handler by binding.driver_kind from static registry
394
+ const handler = registry_1.HandlerRegistry.getInstance()[tool.binding.driver_kind];
395
+ if (!handler) {
396
+ const error = `Handler not found for driver kind: ${tool.binding.driver_kind}`;
397
+ // Emit failure episode using MOVA 4.1.1 format
398
+ await context.episodeWriter.writeExecutionEpisode({
399
+ episode_type: 'execution_step',
400
+ result_status: 'failed',
401
+ result_summary: `Step ${step.id} failed: ${error}`,
402
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
403
+ payload: {
404
+ step_id: step.id,
405
+ error: error,
406
+ status: 'failed',
407
+ },
408
+ });
409
+ await this.recordSecurityEvent('handler_not_found', { step_id: step.id, error, driver_kind: tool.binding.driver_kind }, context);
410
+ return { success: false, error };
411
+ }
412
+ // e) Execute handler
413
+ const handlerResult = await handler(input, tool, context);
414
+ // Check tool output budget
415
+ const outputStr = JSON.stringify(handlerResult);
416
+ const toolOutputBudgetStatus = context.tokenBudgetEnforcer.checkToolOutput(outputStr);
417
+ if (toolOutputBudgetStatus.exceeded) {
418
+ // Handle budget violation
419
+ context.budgetStatus = toolOutputBudgetStatus.action === 'fail' ? 'failed' : 'warned';
420
+ context.budgetViolations.push(...toolOutputBudgetStatus.violations);
421
+ // Create budget violation episodes for each violation
422
+ for (const violation of toolOutputBudgetStatus.violations) {
423
+ const budgetViolationEpisode = context.tokenBudgetEnforcer.createBudgetViolationEpisode(violation, { run_id: context.run_id, request_id: context.request_id, step_id: step.id });
424
+ await context.episodeWriter.writeSecurityEvent(budgetViolationEpisode);
425
+ }
426
+ if (toolOutputBudgetStatus.action === 'fail') {
427
+ const error = `Tool output budget exceeded: ${toolOutputBudgetStatus.violations.map((v) => v.message).join('; ')}`;
428
+ // Emit failure episode using MOVA 4.1.1 format
429
+ await context.episodeWriter.writeExecutionEpisode({
430
+ episode_type: 'execution_step',
431
+ result_status: 'failed',
432
+ result_summary: `Step ${step.id} failed: ${error}`,
433
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
434
+ payload: {
435
+ step_id: step.id,
436
+ error: error,
437
+ status: 'failed',
438
+ },
439
+ });
440
+ return { success: false, error };
441
+ }
442
+ else if (toolOutputBudgetStatus.action === 'warn') {
443
+ (0, logger_1.getLogger)().info(`Tool output budget warning: ${toolOutputBudgetStatus.violations.map((v) => v.message).join('; ')}`);
444
+ }
445
+ }
446
+ // Record successful tool call
447
+ context.tokenBudgetEnforcer.recordSuccessfulToolCall(outputStr);
448
+ // f) Validate output schema (if provided)
449
+ if (tool.binding.schema_refs?.output && handlerResult) {
450
+ const outputValidation = await (0, ajv_loader_1.validate)(tool.binding.schema_refs.output, handlerResult);
451
+ if (!outputValidation.ok) {
452
+ const error = `Step output validation failed: ${outputValidation.errors?.join(', ')}`;
453
+ // Emit failure episode using MOVA 4.1.1 format
454
+ await context.episodeWriter.writeExecutionEpisode({
455
+ episode_type: 'execution_step',
456
+ result_status: 'failed',
457
+ result_summary: `Step ${step.id} failed: ${error}`,
458
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
459
+ payload: {
460
+ step_id: step.id,
461
+ error: error,
462
+ status: 'failed',
463
+ },
464
+ });
465
+ await this.recordSecurityEvent('output_validation_failed', { step_id: step.id, error, output: handlerResult }, context);
466
+ return { success: false, error };
467
+ }
468
+ }
469
+ // g) Write artifacts (inputs/outputs/logs)
470
+ await this.evidenceWriter.writeArtifact(context.evidence_dir, `logs/${step.id}.log`, {
471
+ input,
472
+ output: handlerResult,
473
+ timestamp: new Date().toISOString(),
474
+ });
475
+ // h) Emit episode for the step using MOVA 4.1.1 format
476
+ await context.episodeWriter.writeExecutionEpisode({
477
+ episode_type: 'execution_step',
478
+ result_status: 'completed',
479
+ result_summary: `Step ${step.id} executed successfully`,
480
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
481
+ payload: {
482
+ step_id: step.id,
483
+ input,
484
+ output: handlerResult,
485
+ status: 'success',
486
+ },
487
+ });
488
+ return { success: true, output: handlerResult };
489
+ }
490
+ catch (error) {
491
+ const errorMessage = `Step execution failed: ${error.message}`;
492
+ // Write error log
493
+ await this.evidenceWriter.writeArtifact(context.evidence_dir, `logs/${step.id}.log`, {
494
+ error: errorMessage,
495
+ timestamp: new Date().toISOString(),
496
+ });
497
+ // Emit failure episode using MOVA 4.1.1 format
498
+ await context.episodeWriter.writeExecutionEpisode({
499
+ episode_type: 'execution_step',
500
+ result_status: 'failed',
501
+ result_summary: `Step ${step.id} failed: ${errorMessage}`,
502
+ input_data_refs: [{ data_type: 'ds.mova_agent_step_v1', data_id: step.id }],
503
+ payload: {
504
+ step_id: step.id,
505
+ error: errorMessage,
506
+ status: 'failed',
507
+ },
508
+ });
509
+ return { success: false, error: errorMessage };
510
+ }
511
+ }
512
+ /**
513
+ * Простой резолвер пути для получения значения из объекта по строковому пути
514
+ */
515
+ resolvePath(obj, path) {
516
+ return path.split('.').reduce((current, part) => current?.[part], obj);
517
+ }
518
+ /**
519
+ * Записать событие безопасности
520
+ */
521
+ async recordSecurityEvent(eventType, details, context) {
522
+ // Determine if this is a high severity event that should mark the run as failed
523
+ const severity = this.getSecurityEventSeverity(eventType);
524
+ const isHighSeverity = ['high', 'critical'].includes(severity);
525
+ // If we have context, mark the run as having a fatal security event
526
+ if (context && isHighSeverity) {
527
+ context.has_fatal_security_event = true;
528
+ }
529
+ // Use the run-specific episode writer to write security events
530
+ const runEpisodeWriter = context?.episodeWriter ||
531
+ this.episodeWriter.createRunWriter(context?.request_id || 'unknown', context?.run_id || 'unknown');
532
+ // Explicitly type the category and severity to satisfy TypeScript
533
+ const category = this.getSecurityEventCategory(eventType);
534
+ const eventSeverity = severity;
535
+ await runEpisodeWriter.writeSecurityEvent({
536
+ episode_type: `security_event/${eventType}`,
537
+ security_event_type: eventType,
538
+ security_event_category: category,
539
+ severity: eventSeverity,
540
+ result_status: 'failed', // Security events typically represent failures
541
+ result_summary: `Security event: ${eventType}`,
542
+ detection_source: 'runtime_guard',
543
+ policy_profile_id: 'mova_security_default_v1',
544
+ security_model_version: '1.0.0',
545
+ // Include context information in meta_episode
546
+ meta_episode: {
547
+ request_id: context?.request_id || 'unknown',
548
+ run_id: context?.run_id || 'unknown',
549
+ step_id: details?.step_id,
550
+ },
551
+ });
552
+ }
553
+ /**
554
+ * Определить категорию события безопасности
555
+ */
556
+ getSecurityEventCategory(eventType) {
557
+ const categoryMap = {
558
+ validation_failed: 'policy_violation',
559
+ tool_not_allowlisted: 'authorization',
560
+ destination_not_allowlisted: 'authorization',
561
+ limits_not_specified: 'config',
562
+ input_validation_failed: 'policy_violation',
563
+ output_validation_failed: 'policy_violation',
564
+ handler_not_found: 'config',
565
+ execution_error: 'infrastructure',
566
+ timeout: 'rate_limit',
567
+ };
568
+ return categoryMap[eventType] || 'other';
569
+ }
570
+ /**
571
+ * Определить уровень серьезности события безопасности
572
+ */
573
+ getSecurityEventSeverity(eventType) {
574
+ const severityMap = {
575
+ validation_failed: 'high',
576
+ tool_not_allowlisted: 'high',
577
+ destination_not_allowlisted: 'high',
578
+ limits_not_specified: 'medium',
579
+ input_validation_failed: 'medium',
580
+ output_validation_failed: 'medium',
581
+ handler_not_found: 'high',
582
+ execution_error: 'high',
583
+ timeout: 'high',
584
+ };
585
+ return severityMap[eventType] || 'low';
586
+ }
587
+ /**
588
+ * Валидация профиля инструкций с политикой deny-by-default
589
+ */
590
+ validateInstructionProfile(profile) {
591
+ // Проверяем, что профиль не пустой
592
+ if (!profile) {
593
+ return { ok: false, errors: ['Instruction profile is required'] };
594
+ }
595
+ // Валидация лимитов
596
+ if (profile.caps) {
597
+ const errors = [];
598
+ if (profile.caps.max_timeout_ms && typeof profile.caps.max_timeout_ms !== 'number') {
599
+ errors.push('max_timeout_ms must be a number');
600
+ }
601
+ if (profile.caps.max_data_size && typeof profile.caps.max_data_size !== 'number') {
602
+ errors.push('max_data_size must be a number');
603
+ }
604
+ if (profile.caps.max_steps && typeof profile.caps.max_steps !== 'number') {
605
+ errors.push('max_steps must be a number');
606
+ }
607
+ if (errors.length > 0) {
608
+ return { ok: false, errors };
609
+ }
610
+ }
611
+ // Проверка правил маскировки
612
+ if (profile.redaction_rules && !Array.isArray(profile.redaction_rules)) {
613
+ return { ok: false, errors: ['redaction_rules must be an array'] };
614
+ }
615
+ return { ok: true };
616
+ }
617
+ /**
618
+ * Создать сводку выполнения
619
+ */
620
+ async createRunSummary(context, status, error) {
621
+ // Save token usage report
622
+ context.tokenMeter.saveReport();
623
+ return {
624
+ run_id: context.run_id,
625
+ request_id: context.request_id,
626
+ status,
627
+ timestamp_start: new Date().toISOString(), // в реальности это должно быть точное время начала
628
+ timestamp_end: new Date().toISOString(),
629
+ steps_executed: context.step_outputs.size,
630
+ steps_successful: status === 'completed' ? context.step_outputs.size : context.step_outputs.size - 1, // упрощённо
631
+ steps_failed: status === 'failed' ? 1 : 0, // упрощённо
632
+ total_duration_ms: 0, // в реальности нужно отслеживать время
633
+ error_summary: error,
634
+ token_budget: context.tokenBudgetEnforcer.getBudgetInfo(),
635
+ token_usage: context.tokenMeter.getBriefSummary(),
636
+ budget_status: context.budgetStatus,
637
+ budget_violations: context.budgetViolations,
638
+ };
639
+ }
640
+ /**
641
+ * Основной метод выполнения плана
642
+ */
643
+ async executePlan(plan) {
644
+ // Инициализируем контекст выполнения
645
+ const tokenMeter = new token_meter_1.TokenMeter();
646
+ const tokenBudgetEnforcer = new token_budget_enforcer_1.TokenBudgetEnforcer({ version: '1.0', limits: {}, policy: { on_budget_exceeded: 'warn' } }, tokenMeter);
647
+ const context = {
648
+ run_id: (0, crypto_1.randomUUID)(),
649
+ request_id: plan.request_id || (0, crypto_1.randomUUID)(),
650
+ evidence_dir: 'artifacts/mova_agent/evidence',
651
+ instructionProfile: plan.instruction_profile,
652
+ step_inputs: new Map(),
653
+ step_outputs: new Map(),
654
+ step_bindings: new Map(),
655
+ current_step_index: 0,
656
+ step_security_events: [],
657
+ has_fatal_security_event: false,
658
+ episodeWriter: this.episodeWriter.createRunWriter(plan.request_id || (0, crypto_1.randomUUID)(), (0, crypto_1.randomUUID)()),
659
+ tokenMeter,
660
+ tokenBudgetEnforcer,
661
+ budgetStatus: 'passed',
662
+ budgetViolations: [],
663
+ };
664
+ try {
665
+ // Валидация профиля инструкций
666
+ const profileValidation = this.validateInstructionProfile(plan.instruction_profile);
667
+ if (!profileValidation.ok) {
668
+ throw new Error(`Instruction profile validation failed: ${profileValidation.errors?.join(', ')}`);
669
+ }
670
+ (0, logger_1.getLogger)().info(`Starting execution for plan: ${plan.plan_id}`);
671
+ // Создадим минимальный тулпул для тестирования
672
+ const toolPool = {
673
+ tools: [],
674
+ };
675
+ // Выполняем каждый шаг плана
676
+ for (const step of plan.steps) {
677
+ // Адаптируем структуру шага для внутреннего формата
678
+ const internalStep = {
679
+ id: step.step_id,
680
+ verb: step.verb,
681
+ connector_id: '', // будет установлено из binding
682
+ input: step.input,
683
+ };
684
+ // Добавляем обработку binding в контекст для данного шага
685
+ if (step.tool_binding) {
686
+ context.step_bindings.set(step.step_id, step.tool_binding);
687
+ // Найдем соответствующий тул в тулпуле или создадим его
688
+ const toolId = `${step.verb}_tool`;
689
+ const toolExists = toolPool.tools.some((tool) => tool.id === toolId);
690
+ if (!toolExists) {
691
+ toolPool.tools.push({
692
+ id: toolId,
693
+ connector: { verb: step.verb }, // упрощенно
694
+ binding: step.tool_binding,
695
+ });
696
+ }
697
+ }
698
+ const stepResult = await this.executeStep(internalStep, context, toolPool);
699
+ if (stepResult.success) {
700
+ context.step_outputs.set(step.step_id, stepResult.output);
701
+ }
702
+ else {
703
+ throw new Error(`Step ${step.step_id} failed: ${stepResult.error}`);
704
+ }
705
+ context.current_step_index++;
706
+ }
707
+ // Создаем итоговую сводку
708
+ const summary = await this.createRunSummary(context, 'success');
709
+ return {
710
+ ok: true,
711
+ summary,
712
+ outputs: Object.fromEntries(context.step_outputs),
713
+ };
714
+ }
715
+ catch (error) {
716
+ // Регистрируем ошибку безопасности
717
+ await this.recordSecurityEvent('execution_failure', {
718
+ error: error.message,
719
+ plan_id: plan.plan_id,
720
+ });
721
+ // Создаем сводку с ошибкой
722
+ const summary = await this.createRunSummary(context, 'failure', error.message);
723
+ return {
724
+ ok: false,
725
+ error: error.message,
726
+ summary,
727
+ };
728
+ }
729
+ }
730
+ }
731
+ exports.Interpreter = Interpreter;
732
+ //# sourceMappingURL=interpreter.js.map