mixdog 0.7.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 (404) hide show
  1. package/.claude-plugin/marketplace.json +31 -0
  2. package/.claude-plugin/plugin.json +20 -0
  3. package/.gitattributes +34 -0
  4. package/.mcp.json +14 -0
  5. package/ARCHITECTURE.md +77 -0
  6. package/CHANGELOG.md +7 -0
  7. package/CONTRIBUTING.md +45 -0
  8. package/DATA-FLOW.md +79 -0
  9. package/LICENSE +21 -0
  10. package/README.md +389 -0
  11. package/SECURITY.md +138 -0
  12. package/UNINSTALL.md +112 -0
  13. package/agents/maintenance.md +5 -0
  14. package/agents/memory-classification.md +30 -0
  15. package/agents/scheduler-task.md +18 -0
  16. package/agents/webhook-handler.md +27 -0
  17. package/agents/worker.md +24 -0
  18. package/bin/bridge +133 -0
  19. package/bin/statusline-launcher.mjs +78 -0
  20. package/bin/statusline-lib.mjs +550 -0
  21. package/bin/statusline.mjs +607 -0
  22. package/bun.lock +802 -0
  23. package/commands/config.md +16 -0
  24. package/commands/doctor.md +13 -0
  25. package/commands/setup.md +17 -0
  26. package/defaults/cycle3-review-prompt.md +90 -0
  27. package/defaults/hidden-roles.json +65 -0
  28. package/defaults/memory-chunk-prompt.md +63 -0
  29. package/defaults/memory-promote-prompt.md +135 -0
  30. package/defaults/mixdog-config.template.json +27 -0
  31. package/defaults/user-workflow.json +8 -0
  32. package/defaults/user-workflow.md +12 -0
  33. package/hooks/hooks.json +73 -0
  34. package/hooks/lib/active-instance.cjs +77 -0
  35. package/hooks/lib/permission-evaluator.cjs +411 -0
  36. package/hooks/lib/permission-route.cjs +63 -0
  37. package/hooks/lib/permission-rules.cjs +170 -0
  38. package/hooks/lib/settings-loader.cjs +116 -0
  39. package/hooks/post-tool-use.cjs +84 -0
  40. package/hooks/pre-mcp-sandbox.cjs +158 -0
  41. package/hooks/pre-tool-subagent.cjs +253 -0
  42. package/hooks/session-start.cjs +1372 -0
  43. package/hooks/turn-timer.cjs +82 -0
  44. package/lib/claude-md-writer.cjs +386 -0
  45. package/lib/config-cjs.cjs +61 -0
  46. package/lib/hook-pipe-path.cjs +10 -0
  47. package/lib/keychain-cjs.cjs +263 -0
  48. package/lib/plugin-paths.cjs +61 -0
  49. package/lib/rules-builder.cjs +241 -0
  50. package/lib/text-utils.cjs +61 -0
  51. package/native/README.md +117 -0
  52. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  53. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  54. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  55. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  56. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  57. package/package.json +107 -0
  58. package/prompts/code-review.txt +16 -0
  59. package/prompts/security-audit.txt +17 -0
  60. package/rules/bridge/00-common.md +39 -0
  61. package/rules/bridge/20-skip-protocol.md +18 -0
  62. package/rules/bridge/30-explorer.md +33 -0
  63. package/rules/bridge/40-cycle1-agent.md +52 -0
  64. package/rules/bridge/41-cycle2-agent.md +62 -0
  65. package/rules/bridge/42-cycle3-agent.md +44 -0
  66. package/rules/lead/00-tool-lead.md +61 -0
  67. package/rules/lead/01-general.md +23 -0
  68. package/rules/lead/02-channels.md +49 -0
  69. package/rules/lead/03-team.md +27 -0
  70. package/rules/lead/04-workflow.md +20 -0
  71. package/rules/shared/00-language.md +14 -0
  72. package/rules/shared/01-tool.md +138 -0
  73. package/scripts/bootstrap.mjs +184 -0
  74. package/scripts/bridge-unify-smoke.mjs +308 -0
  75. package/scripts/build-runtime-linux.sh +348 -0
  76. package/scripts/build-runtime-macos.sh +217 -0
  77. package/scripts/build-runtime-windows.ps1 +242 -0
  78. package/scripts/builtin-utils-smoke.mjs +392 -0
  79. package/scripts/check-json.mjs +45 -0
  80. package/scripts/check-syntax-changed.mjs +102 -0
  81. package/scripts/check-syntax.mjs +58 -0
  82. package/scripts/code-graph-batch.test.mjs +33 -0
  83. package/scripts/config-preserve-smoke.mjs +180 -0
  84. package/scripts/doctor.mjs +484 -0
  85. package/scripts/edit-normalize-fuzz.mjs +130 -0
  86. package/scripts/edit-normalize-smoke.mjs +401 -0
  87. package/scripts/edit-operation-smoke.mjs +369 -0
  88. package/scripts/edit2-smoke.mjs +63 -0
  89. package/scripts/fuzzy-e2e.mjs +28 -0
  90. package/scripts/fuzzy-smoke.mjs +26 -0
  91. package/scripts/generate-runtime-manifest.mjs +166 -0
  92. package/scripts/guard-smoke.mjs +66 -0
  93. package/scripts/hidden-role-schema-smoke.mjs +162 -0
  94. package/scripts/hook-routing-smoke.mjs +29 -0
  95. package/scripts/inject-input.ps1 +204 -0
  96. package/scripts/io-complex-smoke.mjs +667 -0
  97. package/scripts/io-explore-bench.mjs +424 -0
  98. package/scripts/io-guardrails-smoke.mjs +205 -0
  99. package/scripts/io-mini-bench-baseline.json +11 -0
  100. package/scripts/io-mini-bench.mjs +216 -0
  101. package/scripts/io-route-harness.mjs +933 -0
  102. package/scripts/io-telemetry-report.mjs +691 -0
  103. package/scripts/mutation-bench.mjs +564 -0
  104. package/scripts/mutation-io-smoke.mjs +1081 -0
  105. package/scripts/native-patch-bridge-smoke.mjs +288 -0
  106. package/scripts/native-patch-smoke.mjs +304 -0
  107. package/scripts/patch-interior-context-smoke.mjs +49 -0
  108. package/scripts/patch-newline-utf8-smoke.mjs +157 -0
  109. package/scripts/perf-hook-smoke.mjs +71 -0
  110. package/scripts/permission-eval-smoke.mjs +426 -0
  111. package/scripts/prep-patch.mjs +53 -0
  112. package/scripts/prep-shim.mjs +96 -0
  113. package/scripts/provider-cache-smoke.mjs +687 -0
  114. package/scripts/report-runtime-health.mjs +132 -0
  115. package/scripts/run-mcp.mjs +1547 -0
  116. package/scripts/salvage-v4a-shatter.test.mjs +58 -0
  117. package/scripts/scoped-cache-io-smoke.mjs +103 -0
  118. package/scripts/shell-policy-round3-smoke.mjs +46 -0
  119. package/scripts/smoke-runtime-negative.ps1 +100 -0
  120. package/scripts/smoke-runtime-negative.sh +95 -0
  121. package/scripts/stall-policy-smoke.mjs +50 -0
  122. package/scripts/start-memory-worker.mjs +23 -0
  123. package/scripts/statusline-launcher-smoke.mjs +82 -0
  124. package/scripts/stress-atomic-write.mjs +1028 -0
  125. package/scripts/test-config-rmw-restore.mjs +122 -0
  126. package/scripts/test-fault-inject.mjs +164 -0
  127. package/scripts/test-large-file.mjs +174 -0
  128. package/scripts/tool-edge-smoke.mjs +209 -0
  129. package/scripts/uninstall.mjs +201 -0
  130. package/scripts/webhook-selfheal-smoke.mjs +29 -0
  131. package/scripts/write-overwrite-guard-smoke.mjs +56 -0
  132. package/server-main.mjs +3055 -0
  133. package/server.mjs +468 -0
  134. package/setup/config-merge.mjs +254 -0
  135. package/setup/install.mjs +120 -0
  136. package/setup/launch-core.mjs +507 -0
  137. package/setup/launch.mjs +101 -0
  138. package/setup/setup-server.mjs +3206 -0
  139. package/setup/setup.html +3693 -0
  140. package/skills/retro-skill-proposer/SKILL.md +92 -0
  141. package/skills/schedule-add/SKILL.md +77 -0
  142. package/skills/setup/SKILL.md +346 -0
  143. package/skills/webhook-add/SKILL.md +81 -0
  144. package/src/agent/bridge-stall-watchdog.mjs +337 -0
  145. package/src/agent/index.mjs +2138 -0
  146. package/src/agent/orchestrator/activity-bus.mjs +38 -0
  147. package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +1010 -0
  148. package/src/agent/orchestrator/bridge-retry.mjs +220 -0
  149. package/src/agent/orchestrator/bridge-trace.mjs +583 -0
  150. package/src/agent/orchestrator/cache-mtime.mjs +58 -0
  151. package/src/agent/orchestrator/config.mjs +358 -0
  152. package/src/agent/orchestrator/context/collect.mjs +651 -0
  153. package/src/agent/orchestrator/dispatch-persist.mjs +549 -0
  154. package/src/agent/orchestrator/drain-registry.mjs +50 -0
  155. package/src/agent/orchestrator/explore-validator.mjs +8 -0
  156. package/src/agent/orchestrator/internal-roles.mjs +118 -0
  157. package/src/agent/orchestrator/internal-tools.mjs +88 -0
  158. package/src/agent/orchestrator/jobs.mjs +116 -0
  159. package/src/agent/orchestrator/mcp/client.mjs +364 -0
  160. package/src/agent/orchestrator/providers/anthropic-betas.mjs +21 -0
  161. package/src/agent/orchestrator/providers/anthropic-oauth.mjs +1745 -0
  162. package/src/agent/orchestrator/providers/anthropic.mjs +437 -0
  163. package/src/agent/orchestrator/providers/gemini.mjs +1175 -0
  164. package/src/agent/orchestrator/providers/grok-oauth.mjs +782 -0
  165. package/src/agent/orchestrator/providers/model-catalog.mjs +241 -0
  166. package/src/agent/orchestrator/providers/openai-compat.mjs +1467 -0
  167. package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +1890 -0
  168. package/src/agent/orchestrator/providers/openai-oauth.mjs +1307 -0
  169. package/src/agent/orchestrator/providers/openai-ws.mjs +104 -0
  170. package/src/agent/orchestrator/providers/registry.mjs +192 -0
  171. package/src/agent/orchestrator/providers/retry-classifier.mjs +325 -0
  172. package/src/agent/orchestrator/session/abort-lookup.mjs +13 -0
  173. package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
  174. package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
  175. package/src/agent/orchestrator/session/cache/read-cache.mjs +319 -0
  176. package/src/agent/orchestrator/session/cache/scoped-cache-outcome.mjs +11 -0
  177. package/src/agent/orchestrator/session/cache/scoped-cache.mjs +361 -0
  178. package/src/agent/orchestrator/session/cache/util.mjs +49 -0
  179. package/src/agent/orchestrator/session/loop.mjs +1478 -0
  180. package/src/agent/orchestrator/session/manager.mjs +1975 -0
  181. package/src/agent/orchestrator/session/read-dedup.mjs +6 -0
  182. package/src/agent/orchestrator/session/result-classification.mjs +65 -0
  183. package/src/agent/orchestrator/session/save-session-worker.mjs +18 -0
  184. package/src/agent/orchestrator/session/store.mjs +624 -0
  185. package/src/agent/orchestrator/session/stream-watchdog.mjs +130 -0
  186. package/src/agent/orchestrator/session/tool-result-offload.mjs +166 -0
  187. package/src/agent/orchestrator/session/trim.mjs +491 -0
  188. package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +115 -0
  189. package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +327 -0
  190. package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +150 -0
  191. package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +228 -0
  192. package/src/agent/orchestrator/smart-bridge/index.mjs +215 -0
  193. package/src/agent/orchestrator/smart-bridge/profiles.mjs +37 -0
  194. package/src/agent/orchestrator/smart-bridge/registry.mjs +348 -0
  195. package/src/agent/orchestrator/smart-bridge/session-builder.mjs +116 -0
  196. package/src/agent/orchestrator/stall-policy.mjs +195 -0
  197. package/src/agent/orchestrator/tool-loop-guard.mjs +75 -0
  198. package/src/agent/orchestrator/tools/bash-policy-scan.mjs +77 -0
  199. package/src/agent/orchestrator/tools/bash-session.mjs +721 -0
  200. package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
  201. package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +455 -0
  202. package/src/agent/orchestrator/tools/builtin/atomic-write.mjs +236 -0
  203. package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +480 -0
  204. package/src/agent/orchestrator/tools/builtin/binary-file.mjs +76 -0
  205. package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +256 -0
  206. package/src/agent/orchestrator/tools/builtin/cache-layers.mjs +386 -0
  207. package/src/agent/orchestrator/tools/builtin/cwd-utils.mjs +37 -0
  208. package/src/agent/orchestrator/tools/builtin/device-paths.mjs +154 -0
  209. package/src/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +292 -0
  210. package/src/agent/orchestrator/tools/builtin/diff-utils.mjs +109 -0
  211. package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +58 -0
  212. package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +240 -0
  213. package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +113 -0
  214. package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +74 -0
  215. package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +242 -0
  216. package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +211 -0
  217. package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +1364 -0
  218. package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +126 -0
  219. package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +141 -0
  220. package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +194 -0
  221. package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +60 -0
  222. package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +168 -0
  223. package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +173 -0
  224. package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +48 -0
  225. package/src/agent/orchestrator/tools/builtin/fs-reachability.mjs +48 -0
  226. package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +99 -0
  227. package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +170 -0
  228. package/src/agent/orchestrator/tools/builtin/grep-formatting.mjs +113 -0
  229. package/src/agent/orchestrator/tools/builtin/hash-utils.mjs +6 -0
  230. package/src/agent/orchestrator/tools/builtin/list-formatting.mjs +7 -0
  231. package/src/agent/orchestrator/tools/builtin/list-tool.mjs +593 -0
  232. package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +89 -0
  233. package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +300 -0
  234. package/src/agent/orchestrator/tools/builtin/open-config-tool.mjs +26 -0
  235. package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +152 -0
  236. package/src/agent/orchestrator/tools/builtin/path-locks.mjs +35 -0
  237. package/src/agent/orchestrator/tools/builtin/path-utils.mjs +201 -0
  238. package/src/agent/orchestrator/tools/builtin/read-args.mjs +103 -0
  239. package/src/agent/orchestrator/tools/builtin/read-batch.mjs +172 -0
  240. package/src/agent/orchestrator/tools/builtin/read-constants.mjs +40 -0
  241. package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
  242. package/src/agent/orchestrator/tools/builtin/read-image-resize.mjs +189 -0
  243. package/src/agent/orchestrator/tools/builtin/read-image.mjs +88 -0
  244. package/src/agent/orchestrator/tools/builtin/read-lines.mjs +12 -0
  245. package/src/agent/orchestrator/tools/builtin/read-mode-tool.mjs +455 -0
  246. package/src/agent/orchestrator/tools/builtin/read-open.mjs +190 -0
  247. package/src/agent/orchestrator/tools/builtin/read-range-index.mjs +271 -0
  248. package/src/agent/orchestrator/tools/builtin/read-ranges.mjs +26 -0
  249. package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +728 -0
  250. package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +173 -0
  251. package/src/agent/orchestrator/tools/builtin/read-special-files.mjs +268 -0
  252. package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
  253. package/src/agent/orchestrator/tools/builtin/read-tool.mjs +530 -0
  254. package/src/agent/orchestrator/tools/builtin/read-windows.mjs +107 -0
  255. package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +196 -0
  256. package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +422 -0
  257. package/src/agent/orchestrator/tools/builtin/search-builders.mjs +158 -0
  258. package/src/agent/orchestrator/tools/builtin/search-tool.mjs +869 -0
  259. package/src/agent/orchestrator/tools/builtin/shell-analysis.mjs +653 -0
  260. package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +936 -0
  261. package/src/agent/orchestrator/tools/builtin/shell-output.mjs +36 -0
  262. package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +214 -0
  263. package/src/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +143 -0
  264. package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +206 -0
  265. package/src/agent/orchestrator/tools/builtin/snapshot-validation.mjs +98 -0
  266. package/src/agent/orchestrator/tools/builtin/text-stats.mjs +69 -0
  267. package/src/agent/orchestrator/tools/builtin/windows-roots.mjs +23 -0
  268. package/src/agent/orchestrator/tools/builtin/write-tool.mjs +401 -0
  269. package/src/agent/orchestrator/tools/builtin.mjs +500 -0
  270. package/src/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +39 -0
  271. package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
  272. package/src/agent/orchestrator/tools/code-graph.mjs +4095 -0
  273. package/src/agent/orchestrator/tools/cwd-tool.mjs +298 -0
  274. package/src/agent/orchestrator/tools/destructive-warning.mjs +323 -0
  275. package/src/agent/orchestrator/tools/edit-normalize.mjs +603 -0
  276. package/src/agent/orchestrator/tools/env-scrub.mjs +100 -0
  277. package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +144 -0
  278. package/src/agent/orchestrator/tools/graph-manifest.json +26 -0
  279. package/src/agent/orchestrator/tools/host-input.mjs +204 -0
  280. package/src/agent/orchestrator/tools/mutation-content-cache.mjs +67 -0
  281. package/src/agent/orchestrator/tools/mutation-planner.mjs +75 -0
  282. package/src/agent/orchestrator/tools/next-call-utils.mjs +48 -0
  283. package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +133 -0
  284. package/src/agent/orchestrator/tools/patch-manifest.json +26 -0
  285. package/src/agent/orchestrator/tools/patch-tool-defs.mjs +20 -0
  286. package/src/agent/orchestrator/tools/patch.mjs +2754 -0
  287. package/src/agent/orchestrator/tools/progress-message.mjs +118 -0
  288. package/src/agent/orchestrator/tools/result-compression.mjs +279 -0
  289. package/src/agent/orchestrator/tools/shell-command.mjs +865 -0
  290. package/src/agent/orchestrator/tools/shell-exec-policy.mjs +89 -0
  291. package/src/agent/orchestrator/tools/shell-policy-danger-target.mjs +27 -0
  292. package/src/agent/orchestrator/tools/shell-policy-imports.mjs +7 -0
  293. package/src/agent/orchestrator/tools/shell-policy.mjs +345 -0
  294. package/src/agent/orchestrator/tools/shell-snapshot.mjs +313 -0
  295. package/src/agent/orchestrator/workflow-store.mjs +93 -0
  296. package/src/agent/tool-defs.mjs +103 -0
  297. package/src/channels/backends/discord.mjs +784 -0
  298. package/src/channels/data/voice-runtime-manifest.json +138 -0
  299. package/src/channels/index.mjs +3229 -0
  300. package/src/channels/lib/cli-worker-host.mjs +12 -0
  301. package/src/channels/lib/config-lock.mjs +13 -0
  302. package/src/channels/lib/config.mjs +292 -0
  303. package/src/channels/lib/drop-trace.mjs +71 -0
  304. package/src/channels/lib/event-pipeline.mjs +81 -0
  305. package/src/channels/lib/event-queue.mjs +345 -0
  306. package/src/channels/lib/executor.mjs +168 -0
  307. package/src/channels/lib/format.mjs +188 -0
  308. package/src/channels/lib/holidays.mjs +138 -0
  309. package/src/channels/lib/hook-pipe-server.mjs +802 -0
  310. package/src/channels/lib/interaction-workflows.mjs +184 -0
  311. package/src/channels/lib/memory-client.mjs +149 -0
  312. package/src/channels/lib/output-forwarder.mjs +765 -0
  313. package/src/channels/lib/runtime-paths.mjs +479 -0
  314. package/src/channels/lib/scheduler.mjs +723 -0
  315. package/src/channels/lib/session-control.mjs +36 -0
  316. package/src/channels/lib/session-discovery.mjs +103 -0
  317. package/src/channels/lib/settings.mjs +11 -0
  318. package/src/channels/lib/state-file.mjs +68 -0
  319. package/src/channels/lib/status-snapshot.mjs +219 -0
  320. package/src/channels/lib/tool-format.mjs +140 -0
  321. package/src/channels/lib/transcript-discovery.mjs +195 -0
  322. package/src/channels/lib/voice-runtime-fetcher.mjs +734 -0
  323. package/src/channels/lib/webhook.mjs +1179 -0
  324. package/src/channels/lib/whisper-server.mjs +477 -0
  325. package/src/channels/tool-defs.mjs +170 -0
  326. package/src/daemon/host.mjs +118 -0
  327. package/src/daemon/mcp-transport.mjs +47 -0
  328. package/src/daemon/session.mjs +100 -0
  329. package/src/daemon/thin-client.mjs +71 -0
  330. package/src/daemon/transport.mjs +163 -0
  331. package/src/memory/data/runtime-manifest.json +40 -0
  332. package/src/memory/index.mjs +3305 -0
  333. package/src/memory/lib/agent-ipc.mjs +93 -0
  334. package/src/memory/lib/bridge-trace-queries.mjs +120 -0
  335. package/src/memory/lib/core-memory-store.mjs +330 -0
  336. package/src/memory/lib/embedding-provider.mjs +269 -0
  337. package/src/memory/lib/embedding-worker.mjs +323 -0
  338. package/src/memory/lib/llm-worker-host.mjs +17 -0
  339. package/src/memory/lib/memory-cycle.mjs +11 -0
  340. package/src/memory/lib/memory-cycle1.mjs +641 -0
  341. package/src/memory/lib/memory-cycle2.mjs +1284 -0
  342. package/src/memory/lib/memory-cycle3.mjs +540 -0
  343. package/src/memory/lib/memory-embed.mjs +299 -0
  344. package/src/memory/lib/memory-extraction.mjs +5 -0
  345. package/src/memory/lib/memory-maintenance-store.mjs +32 -0
  346. package/src/memory/lib/memory-ops-policy.mjs +190 -0
  347. package/src/memory/lib/memory-recall-id-patch.mjs +15 -0
  348. package/src/memory/lib/memory-recall-read-query.mjs +7 -0
  349. package/src/memory/lib/memory-recall-scope-filter.mjs +63 -0
  350. package/src/memory/lib/memory-recall-store.mjs +621 -0
  351. package/src/memory/lib/memory-retrievers.mjs +112 -0
  352. package/src/memory/lib/memory-score.mjs +71 -0
  353. package/src/memory/lib/memory-text-utils.mjs +58 -0
  354. package/src/memory/lib/memory.mjs +412 -0
  355. package/src/memory/lib/model-profile.mjs +85 -0
  356. package/src/memory/lib/pg/adapter.mjs +308 -0
  357. package/src/memory/lib/pg/process.mjs +360 -0
  358. package/src/memory/lib/pg/supervisor.mjs +396 -0
  359. package/src/memory/lib/project-id-resolver.mjs +86 -0
  360. package/src/memory/lib/runtime-fetcher.mjs +442 -0
  361. package/src/memory/lib/trace-store.mjs +728 -0
  362. package/src/memory/tool-defs.mjs +79 -0
  363. package/src/search/index.mjs +1173 -0
  364. package/src/search/lib/backends/anthropic-oauth.mjs +98 -0
  365. package/src/search/lib/backends/exa.mjs +50 -0
  366. package/src/search/lib/backends/firecrawl.mjs +61 -0
  367. package/src/search/lib/backends/gemini-api.mjs +83 -0
  368. package/src/search/lib/backends/grok-oauth.mjs +86 -0
  369. package/src/search/lib/backends/index.mjs +150 -0
  370. package/src/search/lib/backends/openai-api.mjs +144 -0
  371. package/src/search/lib/backends/openai-oauth.mjs +98 -0
  372. package/src/search/lib/backends/openai-web-search.mjs +76 -0
  373. package/src/search/lib/backends/tavily.mjs +55 -0
  374. package/src/search/lib/backends/xai-api.mjs +113 -0
  375. package/src/search/lib/cache.mjs +131 -0
  376. package/src/search/lib/config.mjs +192 -0
  377. package/src/search/lib/formatter.mjs +115 -0
  378. package/src/search/lib/provider-usage.mjs +67 -0
  379. package/src/search/lib/providers.mjs +47 -0
  380. package/src/search/lib/search-intent.mjs +109 -0
  381. package/src/search/lib/setup-handler.mjs +261 -0
  382. package/src/search/lib/state.mjs +201 -0
  383. package/src/search/lib/web-tools.mjs +1207 -0
  384. package/src/search/tool-defs.mjs +83 -0
  385. package/src/setup/defender-exclusion.mjs +183 -0
  386. package/src/shared/abort-controller.mjs +15 -0
  387. package/src/shared/atomic-file.mjs +420 -0
  388. package/src/shared/config.mjs +350 -0
  389. package/src/shared/daemon-recycle.mjs +108 -0
  390. package/src/shared/disable-claude-builtins.mjs +88 -0
  391. package/src/shared/err-text.mjs +12 -0
  392. package/src/shared/llm/cost.mjs +66 -0
  393. package/src/shared/llm/http-agent.mjs +123 -0
  394. package/src/shared/llm/index.mjs +41 -0
  395. package/src/shared/llm/pid-cleanup.mjs +27 -0
  396. package/src/shared/llm/usage-log.mjs +47 -0
  397. package/src/shared/plugin-paths.mjs +58 -0
  398. package/src/shared/schedules-store.mjs +70 -0
  399. package/src/shared/seed.mjs +119 -0
  400. package/src/shared/user-cwd.mjs +213 -0
  401. package/src/shared/user-data-guard.mjs +238 -0
  402. package/src/status/aggregator.mjs +584 -0
  403. package/src/status/server.mjs +413 -0
  404. package/tools.json +1653 -0
@@ -0,0 +1,66 @@
1
+ import { tmpdir } from 'os';
2
+ import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const ROOT = join(__dirname, '..');
7
+
8
+ process.env.CLAUDE_PLUGIN_ROOT ||= ROOT;
9
+ process.env.CLAUDE_PLUGIN_DATA ||= join(tmpdir(), 'mixdog-guard-smoke-data');
10
+
11
+ const { classifyBashFileLookupCommand, stripSoftWarns } = await import('../src/agent/orchestrator/tool-loop-guard.mjs');
12
+
13
+ // Case A: bash file-lookup classifier catches direct + common wrapper forms.
14
+ {
15
+ const cases = [
16
+ ['sed -n "1,40p" rules/bridge/40-cycle1-agent.md', 'sed'],
17
+ ['bash -lc "cat rules/shared/01-tool.md"', 'bash-wrapped'],
18
+ ['powershell.exe -NoProfile -Command "Get-Content rules/shared/01-tool.md"', 'pwsh-wrapped'],
19
+ ['cmd /c type rules\\shared\\01-tool.md', 'cmd-wrapped'],
20
+ ['node -e "const fs=require(\'fs\'); console.log(fs.readFileSync(\'rules/x.md\', \'utf8\'))"', 'node-fs-eval'],
21
+ ['python -c "from pathlib import Path; print(Path(\'rules/x.md\').read_text())"', 'python-open-eval'],
22
+ ['git grep "Bridge Worker" rules', 'git grep'],
23
+ ];
24
+ const failed = cases.filter(([cmd, expected]) => classifyBashFileLookupCommand(cmd) !== expected);
25
+ const pass = failed.length === 0;
26
+ process.stdout.write(`Case A: ${pass ? 'PASS' : 'FAIL'}\n`);
27
+ if (!pass) {
28
+ for (const [cmd, expected] of failed) {
29
+ process.stdout.write(` expected ${expected}, got ${classifyBashFileLookupCommand(cmd)} for ${cmd}\n`);
30
+ }
31
+ process.exitCode = 1;
32
+ }
33
+ }
34
+
35
+ // Case B: a genuine build/test/run/git command is NOT classified as a file lookup.
36
+ {
37
+ const cases = ['npm test', 'git commit -m "x"', 'node build.mjs', 'docker build .'];
38
+ const failed = cases.filter((cmd) => classifyBashFileLookupCommand(cmd) !== null);
39
+ const pass = failed.length === 0;
40
+ process.stdout.write(`Case B: ${pass ? 'PASS' : 'FAIL'}\n`);
41
+ if (!pass) {
42
+ for (const cmd of failed) {
43
+ process.stdout.write(` expected null, got ${classifyBashFileLookupCommand(cmd)} for ${cmd}\n`);
44
+ }
45
+ process.exitCode = 1;
46
+ }
47
+ }
48
+
49
+ // Case C: stripSoftWarns removes a legacy compact marker line and leaves body intact.
50
+ {
51
+ const body = 'real tool output line 1\nreal tool output line 2';
52
+ const withWarn = `⚠ Same-slice reads(src/x.mjs x2): identical params, body cached.\n${body}`;
53
+ const stripped = stripSoftWarns(withWarn);
54
+ const pass = stripped === body && stripSoftWarns(body) === body;
55
+ process.stdout.write(`Case C: ${pass ? 'PASS' : 'FAIL'}\n`);
56
+ if (!pass) {
57
+ process.stdout.write(` stripped=${JSON.stringify(stripped)}\n`);
58
+ process.exitCode = 1;
59
+ }
60
+ }
61
+
62
+ if (!process.exitCode) {
63
+ process.exit(0);
64
+ } else {
65
+ process.exit(1);
66
+ }
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+ import { tmpdir } from 'os';
3
+ import { join, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
7
+ process.env.CLAUDE_PLUGIN_ROOT = ROOT;
8
+ const SMOKE_DATA_DIR = process.env.MIXDOG_SCHEMA_SMOKE_DATA_DIR
9
+ || join(tmpdir(), `mixdog-hidden-role-schema-smoke-data-${process.pid}`);
10
+ if (process.env.MIXDOG_SCHEMA_SMOKE_USE_REAL_DATA !== '1') {
11
+ process.env.CLAUDE_PLUGIN_DATA = SMOKE_DATA_DIR;
12
+ } else {
13
+ process.env.CLAUDE_PLUGIN_DATA ||= SMOKE_DATA_DIR;
14
+ }
15
+
16
+ const { loadConfig, resolveRuntimeSpec } = await import('../src/agent/orchestrator/config.mjs');
17
+ const { getHiddenRole, listHiddenRoleNames } = await import('../src/agent/orchestrator/internal-roles.mjs');
18
+ const {
19
+ resolvePresetName,
20
+ resolveHiddenRoleSchemaAllowedTools,
21
+ } = await import('../src/agent/orchestrator/smart-bridge/bridge-llm.mjs');
22
+ const { prepareBridgeSession } = await import('../src/agent/orchestrator/smart-bridge/session-builder.mjs');
23
+ const { preDispatchDenyForSession } = await import('../src/agent/orchestrator/session/loop.mjs');
24
+ const { initProviders } = await import('../src/agent/orchestrator/providers/registry.mjs');
25
+
26
+ const config = loadConfig();
27
+
28
+ // CI runs in a clean environment with no OAuth credentials, so the default
29
+ // presets' provider (anthropic-oauth) is never registered and createSession
30
+ // would throw `Provider "anthropic-oauth" not found or not enabled`. This
31
+ // smoke only inspects resolved tool schemas — it never issues an LLM call —
32
+ // so register a credential-free provider stub. The provider constructor loads
33
+ // credentials lazily (null when absent); only ensureAuth() touches the network.
34
+ await initProviders({ 'anthropic-oauth': { enabled: true } });
35
+
36
+ let failed = 0;
37
+ const KNOWN_PROFILES = new Set([
38
+ 'unified',
39
+ 'llm-only',
40
+ 'filesystem-read',
41
+ ]);
42
+
43
+ function fail(message) {
44
+ failed += 1;
45
+ process.stderr.write(`FAIL ${message}\n`);
46
+ }
47
+
48
+ function equalArray(a, b) {
49
+ return Array.isArray(a)
50
+ && Array.isArray(b)
51
+ && a.length === b.length
52
+ && a.every((v, i) => v === b[i]);
53
+ }
54
+
55
+ function buildSession(role, presetOverride = null) {
56
+ const hidden = getHiddenRole(role);
57
+ if (!hidden) throw new Error(`hidden role not found: ${role}`);
58
+ const presetName = presetOverride || resolvePresetName({ role, config });
59
+ const preset = config.presets?.find((p) => p.id === presetName || p.name === presetName);
60
+ if (!preset) throw new Error(`preset not found for ${role}: ${presetName}`);
61
+ const runtimeSpec = resolveRuntimeSpec(preset, { lane: 'bridge', agentId: role });
62
+ const { session } = prepareBridgeSession({
63
+ role,
64
+ presetName,
65
+ preset,
66
+ runtimeSpec,
67
+ permission: hidden.permission || undefined,
68
+ cwd: null,
69
+ skipRoleReminder: true,
70
+ schemaAllowedTools: resolveHiddenRoleSchemaAllowedTools(hidden),
71
+ });
72
+ return (session.tools || []).map((t) => t?.name).filter(Boolean);
73
+ }
74
+
75
+ function buildWorkerToolNames() {
76
+ // Tool surface parity: compare explorer against bridge `worker` on the
77
+ // same resolved preset (CI has no user-workflow.json worker entry).
78
+ const presetName = resolvePresetName({ role: 'worker', config })
79
+ || resolvePresetName({ role: 'explorer', config })
80
+ || null;
81
+ if (!presetName) throw new Error('preset not found for worker baseline');
82
+ const preset = config.presets?.find((p) => p.id === presetName || p.name === presetName);
83
+ if (!preset) throw new Error(`preset not found for worker: ${presetName}`);
84
+ const runtimeSpec = resolveRuntimeSpec(preset, { lane: 'bridge', agentId: 'worker' });
85
+ const { session } = prepareBridgeSession({
86
+ role: 'worker',
87
+ presetName,
88
+ preset,
89
+ runtimeSpec,
90
+ permission: 'read',
91
+ cwd: null,
92
+ });
93
+ return (session.tools || []).map((t) => t?.name).filter(Boolean);
94
+ }
95
+
96
+ let workerTools = [];
97
+ try {
98
+ workerTools = buildWorkerToolNames();
99
+ } catch (err) {
100
+ fail(`worker baseline: ${err?.message || err}`);
101
+ }
102
+
103
+ const cases = [
104
+ ['explorer', null, workerTools],
105
+ ['cycle1-agent', null, []],
106
+ ['cycle2-agent', null, []],
107
+ ];
108
+
109
+ for (const role of listHiddenRoleNames().sort()) {
110
+ const hidden = getHiddenRole(role);
111
+ const profile = String(hidden?.toolSchemaProfile || '').trim();
112
+ if (!profile) {
113
+ fail(`${role}: missing toolSchemaProfile`);
114
+ } else if (!KNOWN_PROFILES.has(profile)) {
115
+ fail(`${role}: unknown toolSchemaProfile ${profile}`);
116
+ }
117
+ }
118
+
119
+ for (const [role, preset, expected] of cases) {
120
+ let actual = [];
121
+ try {
122
+ actual = buildSession(role, preset);
123
+ } catch (err) {
124
+ fail(`${role}: ${err?.message || err}`);
125
+ continue;
126
+ }
127
+ const pass = equalArray(actual, expected);
128
+ process.stdout.write(`${role}: ${pass ? 'PASS' : 'FAIL'} tools=${actual.join(',') || '(none)'}\n`);
129
+ if (!pass) fail(`${role}: expected ${expected.join(',') || '(none)'}, got ${actual.join(',') || '(none)'}`);
130
+ }
131
+
132
+ // Read-locked hidden roles: caller cannot upgrade permission to read-write.
133
+ {
134
+ const presetName = resolvePresetName({ role: 'explorer', config });
135
+ const preset = config.presets?.find((p) => p.id === presetName || p.name === presetName);
136
+ const runtimeSpec = resolveRuntimeSpec(preset, { lane: 'bridge', agentId: 'explorer' });
137
+ const { session } = prepareBridgeSession({
138
+ role: 'explorer',
139
+ presetName,
140
+ preset,
141
+ runtimeSpec,
142
+ permission: 'read-write',
143
+ cwd: null,
144
+ owner: 'bridge',
145
+ skipRoleReminder: true,
146
+ schemaAllowedTools: resolveHiddenRoleSchemaAllowedTools(getHiddenRole('explorer')),
147
+ });
148
+ const permOk = session.permission === 'read' && session.toolPermission === 'read';
149
+ const writeDeny = preDispatchDenyForSession(session, { name: 'write' }, 'builtin');
150
+ const pass = permOk && typeof writeDeny === 'string' && writeDeny.includes('permission=read');
151
+ process.stdout.write(`explorer-read-lock: ${pass ? 'PASS' : 'FAIL'}\n`);
152
+ if (!pass) {
153
+ failed += 1;
154
+ process.stderr.write(`FAIL explorer-read-lock: perm=${session.permission}/${session.toolPermission} deny=${writeDeny}\n`);
155
+ }
156
+ }
157
+
158
+ if (failed) process.exit(1);
159
+ // Explicit exit: the imported bridge/provider graph opens keep-alive HTTP
160
+ // agent handles (src/shared/llm/http-agent.mjs) that block natural exit —
161
+ // in CI this kept the process alive until the 6h job timeout.
162
+ process.stdout.write('hidden-role-schema-smoke: pass\n', () => process.exit(0));
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import assert from 'assert';
3
+ import { readFileSync } from 'fs';
4
+ import { dirname, join } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+
7
+ const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
8
+ const hooks = JSON.parse(readFileSync(join(ROOT, 'hooks', 'hooks.json'), 'utf8'));
9
+ const preToolUse = hooks?.hooks?.PreToolUse || [];
10
+
11
+ function matched(toolName) {
12
+ return preToolUse
13
+ .filter((entry) => new RegExp(entry.matcher).test(toolName))
14
+ .map((entry) => entry.matcher);
15
+ }
16
+
17
+ for (const toolName of ['Read', 'Grep', 'Glob']) {
18
+ assert.deepStrictEqual(matched(toolName), ['^(Read|Grep|Glob)$'], `${toolName} native mirror must be blocked`);
19
+ }
20
+
21
+ for (const toolName of ['mcp__plugin_mixdog_mixdog__edit', 'mcp__plugin_mixdog_trib-plugin__edit']) {
22
+ assert.strictEqual(matched(toolName).length, 1, `${toolName} must enter MCP sandbox hook`);
23
+ }
24
+
25
+ for (const toolName of ['mcp__plugin_mixdog_mixdog__read', 'mcp__plugin_mixdog_trib-plugin__read']) {
26
+ assert.deepStrictEqual(matched(toolName), [], `${toolName} read-only MCP tool must stay fast-path`);
27
+ }
28
+
29
+ console.log('hook-routing-smoke passed');
@@ -0,0 +1,204 @@
1
+ #requires -Version 5.1
2
+ <#
3
+ .SYNOPSIS
4
+ Inject keystrokes into another console process via AttachConsole + WriteConsoleInputW.
5
+
6
+ .DESCRIPTION
7
+ Detaches from current console, attaches to target PID's console, writes a sequence of
8
+ KEY_EVENT INPUT_RECORDs (one keydown + one keyup per char), then detaches.
9
+
10
+ No focus dependency, no SendInput, no UI. Works only when the target owns a real
11
+ console (conhost/Windows Terminal). May not work for ConPTY-only hosted children.
12
+
13
+ .PARAMETER TargetPid
14
+ PID of the target console process.
15
+
16
+ .PARAMETER Text
17
+ Text to inject. Literal "\r" or actual CR (0x0D) is treated as Enter.
18
+
19
+ .PARAMETER UseVk
20
+ Diagnostic: also fill VirtualKeyCode/ScanCode via VkKeyScan + MapVirtualKey.
21
+ #>
22
+ [CmdletBinding()]
23
+ param(
24
+ [Parameter(Mandatory=$true)][int]$TargetPid,
25
+ [Parameter(Mandatory=$true)][string]$Text,
26
+ [switch]$UseVk
27
+ )
28
+
29
+ $ErrorActionPreference = 'Stop'
30
+
31
+ # Normalize: literal "\r" -> CR. Also collapse \r\n / lone \n to CR (Windows console Enter).
32
+ $normalized = $Text -replace '\\r', "`r"
33
+ $normalized = $normalized -replace "`r`n", "`r"
34
+ $normalized = $normalized -replace "`n", "`r"
35
+
36
+ $typeDef = @'
37
+ using System;
38
+ using System.Runtime.InteropServices;
39
+
40
+ public static class ConIO {
41
+ [DllImport("kernel32.dll", SetLastError=true)]
42
+ public static extern bool AttachConsole(uint dwProcessId);
43
+
44
+ [DllImport("kernel32.dll", SetLastError=true)]
45
+ public static extern bool FreeConsole();
46
+
47
+ [DllImport("kernel32.dll", SetLastError=true)]
48
+ public static extern IntPtr GetConsoleWindow();
49
+
50
+ [DllImport("kernel32.dll", SetLastError=true)]
51
+ public static extern IntPtr GetStdHandle(int nStdHandle);
52
+
53
+ [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode, EntryPoint="CreateFileW")]
54
+ public static extern IntPtr CreateFileW(
55
+ [MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
56
+ uint dwDesiredAccess,
57
+ uint dwShareMode,
58
+ IntPtr lpSecurityAttributes,
59
+ uint dwCreationDisposition,
60
+ uint dwFlagsAndAttributes,
61
+ IntPtr hTemplateFile);
62
+
63
+ [DllImport("kernel32.dll", SetLastError=true)]
64
+ public static extern bool CloseHandle(IntPtr hObject);
65
+
66
+ [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode, EntryPoint="WriteConsoleInputW")]
67
+ public static extern bool WriteConsoleInputW(
68
+ IntPtr hConsoleInput,
69
+ [MarshalAs(UnmanagedType.LPArray), In] INPUT_RECORD[] lpBuffer,
70
+ uint nLength,
71
+ out uint lpNumberOfEventsWritten);
72
+
73
+ [DllImport("user32.dll", SetLastError=true)]
74
+ public static extern short VkKeyScanW(char ch);
75
+
76
+ [DllImport("user32.dll", SetLastError=true)]
77
+ public static extern uint MapVirtualKeyW(uint uCode, uint uMapType);
78
+
79
+ public const int STD_INPUT_HANDLE = -10;
80
+ public const ushort KEY_EVENT = 0x0001;
81
+ public const uint MAPVK_VK_TO_VSC = 0;
82
+ public const uint GENERIC_READ = 0x80000000;
83
+ public const uint GENERIC_WRITE = 0x40000000;
84
+ public const uint FILE_SHARE_READ = 0x1;
85
+ public const uint FILE_SHARE_WRITE = 0x2;
86
+ public const uint OPEN_EXISTING = 3;
87
+ public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
88
+
89
+ [StructLayout(LayoutKind.Sequential)]
90
+ public struct KEY_EVENT_RECORD {
91
+ [MarshalAs(UnmanagedType.Bool)] public bool bKeyDown;
92
+ public ushort wRepeatCount;
93
+ public ushort wVirtualKeyCode;
94
+ public ushort wVirtualScanCode;
95
+ public ushort UnicodeChar;
96
+ public uint dwControlKeyState;
97
+ }
98
+
99
+ [StructLayout(LayoutKind.Explicit)]
100
+ public struct INPUT_RECORD {
101
+ [FieldOffset(0)] public ushort EventType;
102
+ [FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent;
103
+ }
104
+ }
105
+ '@
106
+
107
+ if (-not ('ConIO' -as [type])) {
108
+ Add-Type -TypeDefinition $typeDef -Language CSharp
109
+ }
110
+
111
+ function Write-Err([string]$msg) {
112
+ [Console]::Error.WriteLine($msg)
113
+ }
114
+
115
+ # Detach from any current console first (safe even if none attached).
116
+ [void][ConIO]::FreeConsole()
117
+
118
+ if (-not [ConIO]::AttachConsole([uint32]$TargetPid)) {
119
+ $err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
120
+ Write-Err "AttachConsole($TargetPid) failed. Win32 error=$err"
121
+ exit 1
122
+ }
123
+
124
+ $hStdIn = [IntPtr]::Zero
125
+ try {
126
+ # AttachConsole does NOT refresh the cached std handles. Open CONIN$ explicitly.
127
+ $access = [uint32]([ConIO]::GENERIC_READ -bor [ConIO]::GENERIC_WRITE)
128
+ $share = [uint32]([ConIO]::FILE_SHARE_READ -bor [ConIO]::FILE_SHARE_WRITE)
129
+ $hStdIn = [ConIO]::CreateFileW('CONIN$', $access, $share, [IntPtr]::Zero, [ConIO]::OPEN_EXISTING, 0, [IntPtr]::Zero)
130
+ if ($hStdIn -eq [ConIO]::INVALID_HANDLE_VALUE -or $hStdIn -eq [IntPtr]::Zero) {
131
+ $err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
132
+ Write-Err "CreateFileW(CONIN$) returned invalid handle. Win32 error=$err"
133
+ exit 1
134
+ }
135
+
136
+ $chars = $normalized.ToCharArray()
137
+ if ($chars.Length -eq 0) {
138
+ Write-Err "Empty text after normalization."
139
+ exit 1
140
+ }
141
+
142
+ $records = New-Object 'ConIO+INPUT_RECORD[]' ($chars.Length * 2)
143
+ for ($i = 0; $i -lt $chars.Length; $i++) {
144
+ $vk = [uint16]0
145
+ $sc = [uint16]0
146
+ if ($UseVk) {
147
+ $scan = [ConIO]::VkKeyScanW($chars[$i])
148
+ if ($scan -ne -1) {
149
+ $vk = [uint16]($scan -band 0xFF)
150
+ $sc = [uint16]([ConIO]::MapVirtualKeyW([uint32]$vk, [ConIO]::MAPVK_VK_TO_VSC) -band 0xFFFF)
151
+ }
152
+ # Special-case CR -> VK_RETURN
153
+ if ([int]$chars[$i] -eq 0x0D) {
154
+ $vk = [uint16]0x0D
155
+ $sc = [uint16]([ConIO]::MapVirtualKeyW([uint32]$vk, [ConIO]::MAPVK_VK_TO_VSC) -band 0xFFFF)
156
+ }
157
+ }
158
+
159
+ $down = New-Object 'ConIO+INPUT_RECORD'
160
+ $down.EventType = [ConIO]::KEY_EVENT
161
+ $kd = New-Object 'ConIO+KEY_EVENT_RECORD'
162
+ $kd.bKeyDown = $true
163
+ $kd.wRepeatCount = 1
164
+ $kd.wVirtualKeyCode = $vk
165
+ $kd.wVirtualScanCode = $sc
166
+ $kd.UnicodeChar = [uint16][int]$chars[$i]
167
+ $kd.dwControlKeyState = 0
168
+ $down.KeyEvent = $kd
169
+
170
+ $up = New-Object 'ConIO+INPUT_RECORD'
171
+ $up.EventType = [ConIO]::KEY_EVENT
172
+ $ku = New-Object 'ConIO+KEY_EVENT_RECORD'
173
+ $ku.bKeyDown = $false
174
+ $ku.wRepeatCount = 1
175
+ $ku.wVirtualKeyCode = $vk
176
+ $ku.wVirtualScanCode = $sc
177
+ $ku.UnicodeChar = [uint16][int]$chars[$i]
178
+ $ku.dwControlKeyState = 0
179
+ $up.KeyEvent = $ku
180
+
181
+ $records[$i*2] = $down
182
+ $records[$i*2+1] = $up
183
+ }
184
+
185
+ [uint32]$written = 0
186
+ $ok = [ConIO]::WriteConsoleInputW($hStdIn, $records, [uint32]$records.Length, [ref]$written)
187
+ if (-not $ok) {
188
+ $err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
189
+ Write-Err "WriteConsoleInputW failed. Win32 error=$err written=$written expected=$($records.Length)"
190
+ exit 1
191
+ }
192
+ if ($written -ne [uint32]$records.Length) {
193
+ Write-Err "WriteConsoleInputW partial write: written=$written expected=$($records.Length)"
194
+ exit 1
195
+ }
196
+ }
197
+ finally {
198
+ if ($hStdIn -ne [IntPtr]::Zero -and $hStdIn -ne [ConIO]::INVALID_HANDLE_VALUE) {
199
+ [void][ConIO]::CloseHandle($hStdIn)
200
+ }
201
+ [void][ConIO]::FreeConsole()
202
+ }
203
+
204
+ exit 0