open-multi-agent-kit 0.98.3 → 0.98.4

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 (262) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +11 -2
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +14 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/help.d.ts.map +1 -1
  8. package/dist/cli/help.js +3 -0
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/mcp-attach.d.ts +3 -3
  11. package/dist/cli/mcp-attach.d.ts.map +1 -1
  12. package/dist/cli/mcp-attach.js +5 -4
  13. package/dist/cli/mcp-attach.js.map +1 -1
  14. package/dist/cli/model-contract.d.ts +5 -0
  15. package/dist/cli/model-contract.d.ts.map +1 -0
  16. package/dist/cli/model-contract.js +45 -0
  17. package/dist/cli/model-contract.js.map +1 -0
  18. package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -1
  19. package/dist/commands/adaptorch-doctor-cli.js +32 -10
  20. package/dist/commands/adaptorch-doctor-cli.js.map +1 -1
  21. package/dist/commands/init-cli.d.ts +12 -0
  22. package/dist/commands/init-cli.d.ts.map +1 -0
  23. package/dist/commands/init-cli.js +76 -0
  24. package/dist/commands/init-cli.js.map +1 -0
  25. package/dist/commands/provider-sync-cli.d.ts +27 -0
  26. package/dist/commands/provider-sync-cli.d.ts.map +1 -0
  27. package/dist/commands/provider-sync-cli.js +177 -0
  28. package/dist/commands/provider-sync-cli.js.map +1 -0
  29. package/dist/commands/run-command.d.ts +8 -0
  30. package/dist/commands/run-command.d.ts.map +1 -0
  31. package/dist/commands/run-command.js +26 -0
  32. package/dist/commands/run-command.js.map +1 -0
  33. package/dist/core/active-skill-state.d.ts +7 -0
  34. package/dist/core/active-skill-state.d.ts.map +1 -0
  35. package/dist/core/active-skill-state.js +25 -0
  36. package/dist/core/active-skill-state.js.map +1 -0
  37. package/dist/core/agent-session-services.d.ts +2 -0
  38. package/dist/core/agent-session-services.d.ts.map +1 -1
  39. package/dist/core/agent-session-services.js +2 -0
  40. package/dist/core/agent-session-services.js.map +1 -1
  41. package/dist/core/agent-session.d.ts +0 -1
  42. package/dist/core/agent-session.d.ts.map +1 -1
  43. package/dist/core/agent-session.js +30 -85
  44. package/dist/core/agent-session.js.map +1 -1
  45. package/dist/core/codex-chatgpt-web-bridge.d.ts +99 -0
  46. package/dist/core/codex-chatgpt-web-bridge.d.ts.map +1 -0
  47. package/dist/core/codex-chatgpt-web-bridge.js +192 -0
  48. package/dist/core/codex-chatgpt-web-bridge.js.map +1 -0
  49. package/dist/core/codex-chatgpt-web-sync.d.ts +50 -0
  50. package/dist/core/codex-chatgpt-web-sync.d.ts.map +1 -0
  51. package/dist/core/codex-chatgpt-web-sync.js +119 -0
  52. package/dist/core/codex-chatgpt-web-sync.js.map +1 -0
  53. package/dist/core/compaction/compaction-headroom.d.ts +30 -0
  54. package/dist/core/compaction/compaction-headroom.d.ts.map +1 -0
  55. package/dist/core/compaction/compaction-headroom.js +48 -0
  56. package/dist/core/compaction/compaction-headroom.js.map +1 -0
  57. package/dist/core/compaction/compaction.d.ts +2 -29
  58. package/dist/core/compaction/compaction.d.ts.map +1 -1
  59. package/dist/core/compaction/compaction.js +19 -47
  60. package/dist/core/compaction/compaction.js.map +1 -1
  61. package/dist/core/compaction/overflow-retry-guard.d.ts +20 -0
  62. package/dist/core/compaction/overflow-retry-guard.d.ts.map +1 -0
  63. package/dist/core/compaction/overflow-retry-guard.js +38 -0
  64. package/dist/core/compaction/overflow-retry-guard.js.map +1 -0
  65. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  66. package/dist/core/context-budget-headroom-types.js +1 -1
  67. package/dist/core/context-budget-headroom-types.js.map +1 -1
  68. package/dist/core/context-budget-token-counter-types.d.ts +27 -0
  69. package/dist/core/context-budget-token-counter-types.d.ts.map +1 -0
  70. package/dist/core/context-budget-token-counter-types.js +2 -0
  71. package/dist/core/context-budget-token-counter-types.js.map +1 -0
  72. package/dist/core/context-budget-token-counter.d.ts +2 -26
  73. package/dist/core/context-budget-token-counter.d.ts.map +1 -1
  74. package/dist/core/context-budget-token-counter.js +2 -0
  75. package/dist/core/context-budget-token-counter.js.map +1 -1
  76. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  77. package/dist/core/context-budget-v2-scoring.js +14 -10
  78. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  79. package/dist/core/domain-router.d.ts.map +1 -1
  80. package/dist/core/domain-router.js +1 -1
  81. package/dist/core/domain-router.js.map +1 -1
  82. package/dist/core/grok-harness-dispatch.d.ts +4 -0
  83. package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
  84. package/dist/core/grok-harness-dispatch.js +20 -3
  85. package/dist/core/grok-harness-dispatch.js.map +1 -1
  86. package/dist/core/grok-harness.d.ts +15 -9
  87. package/dist/core/grok-harness.d.ts.map +1 -1
  88. package/dist/core/grok-harness.js +34 -8
  89. package/dist/core/grok-harness.js.map +1 -1
  90. package/dist/core/mcp/tools.d.ts +2 -2
  91. package/dist/core/mcp/tools.d.ts.map +1 -1
  92. package/dist/core/mcp/tools.js +29 -3
  93. package/dist/core/mcp/tools.js.map +1 -1
  94. package/dist/core/model-registry-schema.d.ts +1081 -0
  95. package/dist/core/model-registry-schema.d.ts.map +1 -0
  96. package/dist/core/model-registry-schema.js +148 -0
  97. package/dist/core/model-registry-schema.js.map +1 -0
  98. package/dist/core/model-registry.d.ts.map +1 -1
  99. package/dist/core/model-registry.js +1 -146
  100. package/dist/core/model-registry.js.map +1 -1
  101. package/dist/core/model-resolver.d.ts +2 -1
  102. package/dist/core/model-resolver.d.ts.map +1 -1
  103. package/dist/core/model-resolver.js +2 -1
  104. package/dist/core/model-resolver.js.map +1 -1
  105. package/dist/core/prompt-preset.d.ts +1 -1
  106. package/dist/core/prompt-preset.d.ts.map +1 -1
  107. package/dist/core/prompt-preset.js +16 -1
  108. package/dist/core/prompt-preset.js.map +1 -1
  109. package/dist/core/provider-display-names.d.ts.map +1 -1
  110. package/dist/core/provider-display-names.js +1 -0
  111. package/dist/core/provider-display-names.js.map +1 -1
  112. package/dist/core/provider-resilience.d.ts +8 -0
  113. package/dist/core/provider-resilience.d.ts.map +1 -1
  114. package/dist/core/provider-resilience.js +20 -3
  115. package/dist/core/provider-resilience.js.map +1 -1
  116. package/dist/core/provider-usage-types.d.ts +42 -0
  117. package/dist/core/provider-usage-types.d.ts.map +1 -0
  118. package/dist/core/provider-usage-types.js +2 -0
  119. package/dist/core/provider-usage-types.js.map +1 -0
  120. package/dist/core/provider-usage.d.ts +2 -31
  121. package/dist/core/provider-usage.d.ts.map +1 -1
  122. package/dist/core/provider-usage.js +4 -0
  123. package/dist/core/provider-usage.js.map +1 -1
  124. package/dist/core/redaction.d.ts.map +1 -1
  125. package/dist/core/redaction.js +18 -2
  126. package/dist/core/redaction.js.map +1 -1
  127. package/dist/core/sandbox/policy-merge.d.ts +6 -0
  128. package/dist/core/sandbox/policy-merge.d.ts.map +1 -0
  129. package/dist/core/sandbox/policy-merge.js +74 -0
  130. package/dist/core/sandbox/policy-merge.js.map +1 -0
  131. package/dist/core/sandbox/policy-paths.d.ts +4 -0
  132. package/dist/core/sandbox/policy-paths.d.ts.map +1 -0
  133. package/dist/core/sandbox/policy-paths.js +21 -0
  134. package/dist/core/sandbox/policy-paths.js.map +1 -0
  135. package/dist/core/sandbox/policy-types.d.ts +75 -0
  136. package/dist/core/sandbox/policy-types.d.ts.map +1 -0
  137. package/dist/core/sandbox/policy-types.js +2 -0
  138. package/dist/core/sandbox/policy-types.js.map +1 -0
  139. package/dist/core/sandbox/policy.d.ts +3 -77
  140. package/dist/core/sandbox/policy.d.ts.map +1 -1
  141. package/dist/core/sandbox/policy.js +3 -98
  142. package/dist/core/sandbox/policy.js.map +1 -1
  143. package/dist/core/sdk-provider-stream.d.ts +14 -0
  144. package/dist/core/sdk-provider-stream.d.ts.map +1 -0
  145. package/dist/core/sdk-provider-stream.js +38 -0
  146. package/dist/core/sdk-provider-stream.js.map +1 -0
  147. package/dist/core/sdk.d.ts +5 -1
  148. package/dist/core/sdk.d.ts.map +1 -1
  149. package/dist/core/sdk.js +17 -33
  150. package/dist/core/sdk.js.map +1 -1
  151. package/dist/core/session-failure-cause.d.ts.map +1 -1
  152. package/dist/core/session-failure-cause.js +10 -3
  153. package/dist/core/session-failure-cause.js.map +1 -1
  154. package/dist/core/session-run-termination.d.ts +18 -0
  155. package/dist/core/session-run-termination.d.ts.map +1 -0
  156. package/dist/core/session-run-termination.js +61 -0
  157. package/dist/core/session-run-termination.js.map +1 -0
  158. package/dist/core/session-termination.d.ts.map +1 -1
  159. package/dist/core/session-termination.js +1 -1
  160. package/dist/core/session-termination.js.map +1 -1
  161. package/dist/core/skill-selector.d.ts +40 -0
  162. package/dist/core/skill-selector.d.ts.map +1 -0
  163. package/dist/core/skill-selector.js +102 -0
  164. package/dist/core/skill-selector.js.map +1 -0
  165. package/dist/core/tools/render-utils.d.ts.map +1 -1
  166. package/dist/core/tools/render-utils.js +2 -4
  167. package/dist/core/tools/render-utils.js.map +1 -1
  168. package/dist/core/turn-metrics-record.d.ts +55 -0
  169. package/dist/core/turn-metrics-record.d.ts.map +1 -0
  170. package/dist/core/turn-metrics-record.js +149 -0
  171. package/dist/core/turn-metrics-record.js.map +1 -0
  172. package/dist/core/turn-metrics.d.ts +4 -56
  173. package/dist/core/turn-metrics.d.ts.map +1 -1
  174. package/dist/core/turn-metrics.js +12 -60
  175. package/dist/core/turn-metrics.js.map +1 -1
  176. package/dist/guardrails/evidence-system.d.ts +1 -1
  177. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  178. package/dist/guardrails/evidence-system.js +18 -29
  179. package/dist/guardrails/evidence-system.js.map +1 -1
  180. package/dist/guardrails/merge-gate-result.d.ts +4 -0
  181. package/dist/guardrails/merge-gate-result.d.ts.map +1 -0
  182. package/dist/guardrails/merge-gate-result.js +32 -0
  183. package/dist/guardrails/merge-gate-result.js.map +1 -0
  184. package/dist/main.d.ts.map +1 -1
  185. package/dist/main.js +22 -22
  186. package/dist/main.js.map +1 -1
  187. package/dist/modes/interactive/interactive-login-options.d.ts +27 -0
  188. package/dist/modes/interactive/interactive-login-options.d.ts.map +1 -0
  189. package/dist/modes/interactive/interactive-login-options.js +54 -0
  190. package/dist/modes/interactive/interactive-login-options.js.map +1 -0
  191. package/dist/modes/interactive/interactive-mode.d.ts +7 -4
  192. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.js +138 -140
  194. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/dist/modes/interactive/interactive-resume-command.d.ts +3 -0
  196. package/dist/modes/interactive/interactive-resume-command.d.ts.map +1 -0
  197. package/dist/modes/interactive/interactive-resume-command.js +24 -0
  198. package/dist/modes/interactive/interactive-resume-command.js.map +1 -0
  199. package/dist/modes/interactive/interactive-tool-result.d.ts +32 -0
  200. package/dist/modes/interactive/interactive-tool-result.d.ts.map +1 -0
  201. package/dist/modes/interactive/interactive-tool-result.js +59 -0
  202. package/dist/modes/interactive/interactive-tool-result.js.map +1 -0
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +22 -0
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/utils/clipboard-image.d.ts.map +1 -1
  207. package/dist/utils/clipboard-image.js +10 -60
  208. package/dist/utils/clipboard-image.js.map +1 -1
  209. package/dist/utils/terminal-links.d.ts +13 -0
  210. package/dist/utils/terminal-links.d.ts.map +1 -0
  211. package/dist/utils/terminal-links.js +68 -0
  212. package/dist/utils/terminal-links.js.map +1 -0
  213. package/dist/utils/windows-clipboard-image.d.ts +16 -0
  214. package/dist/utils/windows-clipboard-image.d.ts.map +1 -0
  215. package/dist/utils/windows-clipboard-image.js +87 -0
  216. package/dist/utils/windows-clipboard-image.js.map +1 -0
  217. package/docs/adaptorch-onboarding.md +80 -0
  218. package/docs/containerization.md +12 -0
  219. package/docs/context-files.md +97 -0
  220. package/docs/correctness-wall.md +8 -0
  221. package/docs/custom-provider.md +35 -0
  222. package/docs/development.md +18 -3
  223. package/docs/environment-variables.md +2 -0
  224. package/docs/grok-harness.md +4 -0
  225. package/docs/harness-boundaries.md +154 -0
  226. package/docs/harness-improvements.md +90 -0
  227. package/docs/json.md +19 -0
  228. package/docs/keybindings.md +1 -1
  229. package/docs/mcp.md +22 -2
  230. package/docs/metrics.md +66 -16
  231. package/docs/model-catalog-refresh.md +190 -0
  232. package/docs/model-contract.md +168 -0
  233. package/docs/models.md +21 -4
  234. package/docs/provider-resilience.md +5 -3
  235. package/docs/providers.md +68 -1
  236. package/docs/quickstart.md +4 -0
  237. package/docs/release-audit-0.98.4.md +112 -0
  238. package/docs/review-bundle-followup.md +195 -0
  239. package/docs/runtime-algorithms.md +19 -0
  240. package/docs/sdk.md +11 -2
  241. package/docs/sessions.md +1 -1
  242. package/docs/settings.md +17 -1
  243. package/docs/skills.md +2 -0
  244. package/docs/tb21-audit.md +131 -0
  245. package/docs/terminal-setup.md +20 -0
  246. package/docs/usage.md +23 -1
  247. package/docs/windows.md +48 -0
  248. package/examples/README.md +4 -0
  249. package/examples/context/AGENTS.md +64 -0
  250. package/examples/context/CLAUDE.md +17 -0
  251. package/examples/context/INTERNET.md +42 -0
  252. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  253. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  254. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  255. package/examples/extensions/gondolin/package-lock.json +2 -2
  256. package/examples/extensions/gondolin/package.json +1 -1
  257. package/examples/extensions/sandbox/package-lock.json +2 -2
  258. package/examples/extensions/sandbox/package.json +1 -1
  259. package/examples/extensions/with-deps/package-lock.json +2 -2
  260. package/examples/extensions/with-deps/package.json +1 -1
  261. package/npm-shrinkwrap.json +18 -18
  262. package/package.json +6 -6
@@ -0,0 +1,68 @@
1
+ import { existsSync } from "node:fs";
2
+ import { win32 } from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import { normalizePath, resolvePath } from "./paths.js";
5
+ /** File URLs are opened by the host terminal, not by a Linux process inside WSL. */
6
+ export function terminalFileUrl(path, cwd, options = {}) {
7
+ const env = options.env ?? process.env;
8
+ const platform = options.platform ?? process.platform;
9
+ if (/^[a-z]:[\\/]|^\\\\/i.test(path))
10
+ return pathToFileURL(path, { windows: true }).href;
11
+ const absolute = platform === "win32" ? win32.resolve(cwd, normalizePath(path)) : resolvePath(path, cwd);
12
+ const distro = env.WSL_DISTRO_NAME;
13
+ if (platform === "linux" && distro && !env.SSH_CONNECTION && !env.SSH_TTY && !/[\\/\x00-\x1f]/.test(distro)) {
14
+ const drive = /^\/mnt\/([a-z])(?:\/|$)/i.exec(absolute);
15
+ const windowsPath = drive
16
+ ? `${drive[1].toUpperCase()}:\\${absolute.slice(drive[0].length).replaceAll("/", "\\")}`
17
+ : `\\\\wsl.localhost\\${distro}${absolute.replaceAll("/", "\\")}`;
18
+ return pathToFileURL(windowsPath, { windows: true }).href;
19
+ }
20
+ return pathToFileURL(absolute, { windows: platform === "win32" }).href;
21
+ }
22
+ /** Bind destinations to the active project so resumed sessions do not use the launch cwd. */
23
+ export function terminalMarkdownLinks(cwd, options = {}) {
24
+ return {
25
+ resolveLink(href) {
26
+ if (/[\x00-\x1f\x7f]/.test(href))
27
+ return undefined;
28
+ if (/^[a-z]:[\\/]|^\\\\/i.test(href))
29
+ return terminalFileUrl(href, cwd, options);
30
+ if (href.startsWith("#"))
31
+ return href;
32
+ if (/^file:/i.test(href)) {
33
+ try {
34
+ const url = new URL(href);
35
+ if (url.hostname && url.hostname !== "localhost")
36
+ return href;
37
+ const windows = /^\/[a-z]:\//i.test(url.pathname);
38
+ return terminalFileUrl(fileURLToPath(url, { windows }), cwd, options) + url.search + url.hash;
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
44
+ if (/^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith("//"))
45
+ return href;
46
+ const boundary = href.search(/[?#]/);
47
+ const pathname = boundary < 0 ? href : href.slice(0, boundary);
48
+ const suffix = boundary < 0 ? "" : href.slice(boundary);
49
+ try {
50
+ return terminalFileUrl(decodeURIComponent(pathname), cwd, options) + suffix;
51
+ }
52
+ catch (error) {
53
+ if (error instanceof URIError)
54
+ return terminalFileUrl(pathname, cwd, options) + suffix;
55
+ throw error;
56
+ }
57
+ },
58
+ resolveFileLink(text) {
59
+ if (/^[a-z][a-z\d+.-]*:/i.test(text) && !/^[a-z]:[\\/]/i.test(text))
60
+ return undefined;
61
+ if (/[\x00-\x1f\x7f]/.test(text) || (!/[\\/]/.test(text) && !/\.[a-z\d]{1,10}$/i.test(text)))
62
+ return undefined;
63
+ const path = resolvePath(text, cwd);
64
+ return existsSync(path) ? terminalFileUrl(text, cwd, options) : undefined;
65
+ },
66
+ };
67
+ }
68
+ //# sourceMappingURL=terminal-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-links.js","sourceRoot":"","sources":["../../src/utils/terminal-links.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { win32 } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { normalizePath, resolvePath } from \"./paths.ts\";\n\ninterface TerminalLinkEnvironment {\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly platform?: NodeJS.Platform;\n}\n\n/** File URLs are opened by the host terminal, not by a Linux process inside WSL. */\nexport function terminalFileUrl(path: string, cwd: string, options: TerminalLinkEnvironment = {}): string {\n\tconst env = options.env ?? process.env;\n\tconst platform = options.platform ?? process.platform;\n\tif (/^[a-z]:[\\\\/]|^\\\\\\\\/i.test(path)) return pathToFileURL(path, { windows: true }).href;\n\tconst absolute = platform === \"win32\" ? win32.resolve(cwd, normalizePath(path)) : resolvePath(path, cwd);\n\tconst distro = env.WSL_DISTRO_NAME;\n\tif (platform === \"linux\" && distro && !env.SSH_CONNECTION && !env.SSH_TTY && !/[\\\\/\\x00-\\x1f]/.test(distro)) {\n\t\tconst drive = /^\\/mnt\\/([a-z])(?:\\/|$)/i.exec(absolute);\n\t\tconst windowsPath = drive\n\t\t\t? `${drive[1].toUpperCase()}:\\\\${absolute.slice(drive[0].length).replaceAll(\"/\", \"\\\\\")}`\n\t\t\t: `\\\\\\\\wsl.localhost\\\\${distro}${absolute.replaceAll(\"/\", \"\\\\\")}`;\n\t\treturn pathToFileURL(windowsPath, { windows: true }).href;\n\t}\n\treturn pathToFileURL(absolute, { windows: platform === \"win32\" }).href;\n}\n\n/** Bind destinations to the active project so resumed sessions do not use the launch cwd. */\nexport function terminalMarkdownLinks(cwd: string, options: TerminalLinkEnvironment = {}) {\n\treturn {\n\t\tresolveLink(href: string): string | undefined {\n\t\t\tif (/[\\x00-\\x1f\\x7f]/.test(href)) return undefined;\n\t\t\tif (/^[a-z]:[\\\\/]|^\\\\\\\\/i.test(href)) return terminalFileUrl(href, cwd, options);\n\t\t\tif (href.startsWith(\"#\")) return href;\n\t\t\tif (/^file:/i.test(href)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = new URL(href);\n\t\t\t\t\tif (url.hostname && url.hostname !== \"localhost\") return href;\n\t\t\t\t\tconst windows = /^\\/[a-z]:\\//i.test(url.pathname);\n\t\t\t\t\treturn terminalFileUrl(fileURLToPath(url, { windows }), cwd, options) + url.search + url.hash;\n\t\t\t\t} catch {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (/^[a-z][a-z\\d+.-]*:/i.test(href) || href.startsWith(\"//\")) return href;\n\t\t\tconst boundary = href.search(/[?#]/);\n\t\t\tconst pathname = boundary < 0 ? href : href.slice(0, boundary);\n\t\t\tconst suffix = boundary < 0 ? \"\" : href.slice(boundary);\n\t\t\ttry {\n\t\t\t\treturn terminalFileUrl(decodeURIComponent(pathname), cwd, options) + suffix;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof URIError) return terminalFileUrl(pathname, cwd, options) + suffix;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tresolveFileLink(text: string): string | undefined {\n\t\t\tif (/^[a-z][a-z\\d+.-]*:/i.test(text) && !/^[a-z]:[\\\\/]/i.test(text)) return undefined;\n\t\t\tif (/[\\x00-\\x1f\\x7f]/.test(text) || (!/[\\\\/]/.test(text) && !/\\.[a-z\\d]{1,10}$/i.test(text))) return undefined;\n\t\t\tconst path = resolvePath(text, cwd);\n\t\t\treturn existsSync(path) ? terminalFileUrl(text, cwd, options) : undefined;\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,16 @@
1
+ export type WindowsClipboardResult = {
2
+ readonly kind: "image";
3
+ readonly bytes: Uint8Array;
4
+ readonly mimeType: "image/png";
5
+ } | {
6
+ readonly kind: "empty";
7
+ } | {
8
+ readonly kind: "unavailable";
9
+ readonly reason: "not-found" | "timeout" | "failed";
10
+ };
11
+ export declare class WindowsClipboardError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ /** Read only image data. No clipboard writes, temporary screenshots, profiles, or policy bypass. */
15
+ export declare function readWindowsClipboardImage(env?: NodeJS.ProcessEnv): Promise<WindowsClipboardResult>;
16
+ //# sourceMappingURL=windows-clipboard-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-clipboard-image.d.ts","sourceRoot":"","sources":["../../src/utils/windows-clipboard-image.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,sBAAsB,GAC/B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,GACtF;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;CAAE,CAAC;AAEzF,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACD;AA2DD,oGAAoG;AACpG,wBAAsB,yBAAyB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAqBrH","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { dirname, isAbsolute } from \"node:path\";\nimport { PROMPT_ATTACHMENT_LIMITS, sniffImageMimeType } from \"../core/prompt-attachment.ts\";\n\nexport type WindowsClipboardResult =\n\t| { readonly kind: \"image\"; readonly bytes: Uint8Array; readonly mimeType: \"image/png\" }\n\t| { readonly kind: \"empty\" }\n\t| { readonly kind: \"unavailable\"; readonly reason: \"not-found\" | \"timeout\" | \"failed\" };\n\nexport class WindowsClipboardError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"WindowsClipboardError\";\n\t}\n}\n\nconst PREFIX = \"OMK_CLIPBOARD_PNG:\";\nconst SCRIPT = [\n\t\"$ErrorActionPreference = 'Stop'\",\n\t\"Add-Type -AssemblyName System.Windows.Forms\",\n\t\"Add-Type -AssemblyName System.Drawing\",\n\t\"$image = [System.Windows.Forms.Clipboard]::GetImage()\",\n\t\"if ($null -eq $image) { [Console]::Write('OMK_CLIPBOARD_EMPTY'); exit 0 }\",\n\t\"$stream = New-Object System.IO.MemoryStream\",\n\t\"try {\",\n\t`if ([long]$image.Width * $image.Height -gt ${PROMPT_ATTACHMENT_LIMITS.maxPixels}) { [Console]::Write('OMK_CLIPBOARD_TOO_LARGE'); exit 0 };`,\n\t\"$image.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png);\",\n\t`if ($stream.Length -gt ${PROMPT_ATTACHMENT_LIMITS.maxImageBytes}) { [Console]::Write('OMK_CLIPBOARD_TOO_LARGE'); exit 0 };`,\n\t`[Console]::Write('${PREFIX}' + [Convert]::ToBase64String($stream.ToArray()))`,\n\t\"} finally { $stream.Dispose(); $image.Dispose() }\",\n].join(\"\\n\");\n\nfunction readCommand(command: string, env: NodeJS.ProcessEnv): Promise<string | WindowsClipboardResult> {\n\tconst childEnv: NodeJS.ProcessEnv = {};\n\tfor (const key of [\n\t\t\"PATH\",\n\t\t\"Path\",\n\t\t\"SystemRoot\",\n\t\t\"SYSTEMROOT\",\n\t\t\"WINDIR\",\n\t\t\"TEMP\",\n\t\t\"TMP\",\n\t\t\"USERPROFILE\",\n\t\t\"WSL_INTEROP\",\n\t\t\"WSL_DISTRO_NAME\",\n\t]) {\n\t\tif (env[key] !== undefined) childEnv[key] = env[key];\n\t}\n\treturn new Promise((resolve) => {\n\t\texecFile(\n\t\t\tcommand,\n\t\t\t[\"-NoProfile\", \"-NonInteractive\", \"-STA\", \"-Command\", SCRIPT],\n\t\t\t{\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\twindowsHide: true,\n\t\t\t\t// Avoid launching Windows in a project UNC directory across the WSL filesystem bridge.\n\t\t\t\tcwd: isAbsolute(command) ? dirname(command) : undefined,\n\t\t\t\tenv: childEnv,\n\t\t\t\ttimeout: 5000,\n\t\t\t\tmaxBuffer: Math.ceil(PROMPT_ATTACHMENT_LIMITS.maxImageBytes / 3) * 4 + 1024,\n\t\t\t},\n\t\t\t(error, stdout) => {\n\t\t\t\tif (!error) resolve(stdout.trim());\n\t\t\t\telse\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tkind: \"unavailable\",\n\t\t\t\t\t\treason: error.code === \"ENOENT\" ? \"not-found\" : error.killed ? \"timeout\" : \"failed\",\n\t\t\t\t\t});\n\t\t\t},\n\t\t);\n\t});\n}\n\n/** Read only image data. No clipboard writes, temporary screenshots, profiles, or policy bypass. */\nexport async function readWindowsClipboardImage(env: NodeJS.ProcessEnv = process.env): Promise<WindowsClipboardResult> {\n\tfor (const command of [\"/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe\", \"powershell.exe\"]) {\n\t\tconst result = await readCommand(command, env);\n\t\tif (typeof result !== \"string\") {\n\t\t\tif (result.kind === \"unavailable\" && result.reason === \"not-found\") continue;\n\t\t\treturn result;\n\t\t}\n\t\tif (result === \"OMK_CLIPBOARD_EMPTY\") return { kind: \"empty\" };\n\t\tif (result === \"OMK_CLIPBOARD_TOO_LARGE\")\n\t\t\tthrow new WindowsClipboardError(\"Windows clipboard image exceeds the prompt image size limit.\");\n\t\tconst encoded = result.startsWith(PREFIX) ? result.slice(PREFIX.length) : \"\";\n\t\tif (!encoded || encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {\n\t\t\tthrow new WindowsClipboardError(\"Windows clipboard returned invalid PNG data.\");\n\t\t}\n\t\tconst bytes = Buffer.from(encoded, \"base64\");\n\t\tif (bytes.length > PROMPT_ATTACHMENT_LIMITS.maxImageBytes || sniffImageMimeType(bytes) !== \"image/png\") {\n\t\t\tthrow new WindowsClipboardError(\"Windows clipboard returned invalid or oversized PNG data.\");\n\t\t}\n\t\treturn { kind: \"image\", bytes, mimeType: \"image/png\" };\n\t}\n\treturn { kind: \"unavailable\", reason: \"not-found\" };\n}\n"]}
@@ -0,0 +1,87 @@
1
+ import { execFile } from "node:child_process";
2
+ import { dirname, isAbsolute } from "node:path";
3
+ import { PROMPT_ATTACHMENT_LIMITS, sniffImageMimeType } from "../core/prompt-attachment.js";
4
+ export class WindowsClipboardError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "WindowsClipboardError";
8
+ }
9
+ }
10
+ const PREFIX = "OMK_CLIPBOARD_PNG:";
11
+ const SCRIPT = [
12
+ "$ErrorActionPreference = 'Stop'",
13
+ "Add-Type -AssemblyName System.Windows.Forms",
14
+ "Add-Type -AssemblyName System.Drawing",
15
+ "$image = [System.Windows.Forms.Clipboard]::GetImage()",
16
+ "if ($null -eq $image) { [Console]::Write('OMK_CLIPBOARD_EMPTY'); exit 0 }",
17
+ "$stream = New-Object System.IO.MemoryStream",
18
+ "try {",
19
+ `if ([long]$image.Width * $image.Height -gt ${PROMPT_ATTACHMENT_LIMITS.maxPixels}) { [Console]::Write('OMK_CLIPBOARD_TOO_LARGE'); exit 0 };`,
20
+ "$image.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png);",
21
+ `if ($stream.Length -gt ${PROMPT_ATTACHMENT_LIMITS.maxImageBytes}) { [Console]::Write('OMK_CLIPBOARD_TOO_LARGE'); exit 0 };`,
22
+ `[Console]::Write('${PREFIX}' + [Convert]::ToBase64String($stream.ToArray()))`,
23
+ "} finally { $stream.Dispose(); $image.Dispose() }",
24
+ ].join("\n");
25
+ function readCommand(command, env) {
26
+ const childEnv = {};
27
+ for (const key of [
28
+ "PATH",
29
+ "Path",
30
+ "SystemRoot",
31
+ "SYSTEMROOT",
32
+ "WINDIR",
33
+ "TEMP",
34
+ "TMP",
35
+ "USERPROFILE",
36
+ "WSL_INTEROP",
37
+ "WSL_DISTRO_NAME",
38
+ ]) {
39
+ if (env[key] !== undefined)
40
+ childEnv[key] = env[key];
41
+ }
42
+ return new Promise((resolve) => {
43
+ execFile(command, ["-NoProfile", "-NonInteractive", "-STA", "-Command", SCRIPT], {
44
+ encoding: "utf8",
45
+ windowsHide: true,
46
+ // Avoid launching Windows in a project UNC directory across the WSL filesystem bridge.
47
+ cwd: isAbsolute(command) ? dirname(command) : undefined,
48
+ env: childEnv,
49
+ timeout: 5000,
50
+ maxBuffer: Math.ceil(PROMPT_ATTACHMENT_LIMITS.maxImageBytes / 3) * 4 + 1024,
51
+ }, (error, stdout) => {
52
+ if (!error)
53
+ resolve(stdout.trim());
54
+ else
55
+ resolve({
56
+ kind: "unavailable",
57
+ reason: error.code === "ENOENT" ? "not-found" : error.killed ? "timeout" : "failed",
58
+ });
59
+ });
60
+ });
61
+ }
62
+ /** Read only image data. No clipboard writes, temporary screenshots, profiles, or policy bypass. */
63
+ export async function readWindowsClipboardImage(env = process.env) {
64
+ for (const command of ["/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe", "powershell.exe"]) {
65
+ const result = await readCommand(command, env);
66
+ if (typeof result !== "string") {
67
+ if (result.kind === "unavailable" && result.reason === "not-found")
68
+ continue;
69
+ return result;
70
+ }
71
+ if (result === "OMK_CLIPBOARD_EMPTY")
72
+ return { kind: "empty" };
73
+ if (result === "OMK_CLIPBOARD_TOO_LARGE")
74
+ throw new WindowsClipboardError("Windows clipboard image exceeds the prompt image size limit.");
75
+ const encoded = result.startsWith(PREFIX) ? result.slice(PREFIX.length) : "";
76
+ if (!encoded || encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {
77
+ throw new WindowsClipboardError("Windows clipboard returned invalid PNG data.");
78
+ }
79
+ const bytes = Buffer.from(encoded, "base64");
80
+ if (bytes.length > PROMPT_ATTACHMENT_LIMITS.maxImageBytes || sniffImageMimeType(bytes) !== "image/png") {
81
+ throw new WindowsClipboardError("Windows clipboard returned invalid or oversized PNG data.");
82
+ }
83
+ return { kind: "image", bytes, mimeType: "image/png" };
84
+ }
85
+ return { kind: "unavailable", reason: "not-found" };
86
+ }
87
+ //# sourceMappingURL=windows-clipboard-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-clipboard-image.js","sourceRoot":"","sources":["../../src/utils/windows-clipboard-image.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { dirname, isAbsolute } from \"node:path\";\nimport { PROMPT_ATTACHMENT_LIMITS, sniffImageMimeType } from \"../core/prompt-attachment.ts\";\n\nexport type WindowsClipboardResult =\n\t| { readonly kind: \"image\"; readonly bytes: Uint8Array; readonly mimeType: \"image/png\" }\n\t| { readonly kind: \"empty\" }\n\t| { readonly kind: \"unavailable\"; readonly reason: \"not-found\" | \"timeout\" | \"failed\" };\n\nexport class WindowsClipboardError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"WindowsClipboardError\";\n\t}\n}\n\nconst PREFIX = \"OMK_CLIPBOARD_PNG:\";\nconst SCRIPT = [\n\t\"$ErrorActionPreference = 'Stop'\",\n\t\"Add-Type -AssemblyName System.Windows.Forms\",\n\t\"Add-Type -AssemblyName System.Drawing\",\n\t\"$image = [System.Windows.Forms.Clipboard]::GetImage()\",\n\t\"if ($null -eq $image) { [Console]::Write('OMK_CLIPBOARD_EMPTY'); exit 0 }\",\n\t\"$stream = New-Object System.IO.MemoryStream\",\n\t\"try {\",\n\t`if ([long]$image.Width * $image.Height -gt ${PROMPT_ATTACHMENT_LIMITS.maxPixels}) { [Console]::Write('OMK_CLIPBOARD_TOO_LARGE'); exit 0 };`,\n\t\"$image.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png);\",\n\t`if ($stream.Length -gt ${PROMPT_ATTACHMENT_LIMITS.maxImageBytes}) { [Console]::Write('OMK_CLIPBOARD_TOO_LARGE'); exit 0 };`,\n\t`[Console]::Write('${PREFIX}' + [Convert]::ToBase64String($stream.ToArray()))`,\n\t\"} finally { $stream.Dispose(); $image.Dispose() }\",\n].join(\"\\n\");\n\nfunction readCommand(command: string, env: NodeJS.ProcessEnv): Promise<string | WindowsClipboardResult> {\n\tconst childEnv: NodeJS.ProcessEnv = {};\n\tfor (const key of [\n\t\t\"PATH\",\n\t\t\"Path\",\n\t\t\"SystemRoot\",\n\t\t\"SYSTEMROOT\",\n\t\t\"WINDIR\",\n\t\t\"TEMP\",\n\t\t\"TMP\",\n\t\t\"USERPROFILE\",\n\t\t\"WSL_INTEROP\",\n\t\t\"WSL_DISTRO_NAME\",\n\t]) {\n\t\tif (env[key] !== undefined) childEnv[key] = env[key];\n\t}\n\treturn new Promise((resolve) => {\n\t\texecFile(\n\t\t\tcommand,\n\t\t\t[\"-NoProfile\", \"-NonInteractive\", \"-STA\", \"-Command\", SCRIPT],\n\t\t\t{\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\twindowsHide: true,\n\t\t\t\t// Avoid launching Windows in a project UNC directory across the WSL filesystem bridge.\n\t\t\t\tcwd: isAbsolute(command) ? dirname(command) : undefined,\n\t\t\t\tenv: childEnv,\n\t\t\t\ttimeout: 5000,\n\t\t\t\tmaxBuffer: Math.ceil(PROMPT_ATTACHMENT_LIMITS.maxImageBytes / 3) * 4 + 1024,\n\t\t\t},\n\t\t\t(error, stdout) => {\n\t\t\t\tif (!error) resolve(stdout.trim());\n\t\t\t\telse\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tkind: \"unavailable\",\n\t\t\t\t\t\treason: error.code === \"ENOENT\" ? \"not-found\" : error.killed ? \"timeout\" : \"failed\",\n\t\t\t\t\t});\n\t\t\t},\n\t\t);\n\t});\n}\n\n/** Read only image data. No clipboard writes, temporary screenshots, profiles, or policy bypass. */\nexport async function readWindowsClipboardImage(env: NodeJS.ProcessEnv = process.env): Promise<WindowsClipboardResult> {\n\tfor (const command of [\"/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe\", \"powershell.exe\"]) {\n\t\tconst result = await readCommand(command, env);\n\t\tif (typeof result !== \"string\") {\n\t\t\tif (result.kind === \"unavailable\" && result.reason === \"not-found\") continue;\n\t\t\treturn result;\n\t\t}\n\t\tif (result === \"OMK_CLIPBOARD_EMPTY\") return { kind: \"empty\" };\n\t\tif (result === \"OMK_CLIPBOARD_TOO_LARGE\")\n\t\t\tthrow new WindowsClipboardError(\"Windows clipboard image exceeds the prompt image size limit.\");\n\t\tconst encoded = result.startsWith(PREFIX) ? result.slice(PREFIX.length) : \"\";\n\t\tif (!encoded || encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {\n\t\t\tthrow new WindowsClipboardError(\"Windows clipboard returned invalid PNG data.\");\n\t\t}\n\t\tconst bytes = Buffer.from(encoded, \"base64\");\n\t\tif (bytes.length > PROMPT_ATTACHMENT_LIMITS.maxImageBytes || sniffImageMimeType(bytes) !== \"image/png\") {\n\t\t\tthrow new WindowsClipboardError(\"Windows clipboard returned invalid or oversized PNG data.\");\n\t\t}\n\t\treturn { kind: \"image\", bytes, mimeType: \"image/png\" };\n\t}\n\treturn { kind: \"unavailable\", reason: \"not-found\" };\n}\n"]}
@@ -0,0 +1,80 @@
1
+ # OMK / WPL → AdaptOrch 안내
2
+
3
+ AdaptOrch는 OMK와 별개의 선택적 서비스입니다. OMK와 MIT 라이선스의
4
+ `omk-adaptorch-wpl` 사용에 가입이나 유료 플랜은 필요하지 않습니다.
5
+ 이 경로는 웹사이트 방문을 돕는 CRM 유입 경로이며, 계정 생성이나 리드 저장을
6
+ 대신 수행하는 CRM 클라이언트가 아닙니다.
7
+
8
+ ## CLI에서 시작
9
+
10
+ ```bash
11
+ omk doctor adaptorch --links
12
+ omk doctor adaptorch --links --json
13
+ ```
14
+
15
+ `--links`는 API 키 없이 작동합니다. 환경의 API 키나 API URL을 읽거나 검증하지
16
+ 않으며, HTTP 요청·브라우저 열기·파일 저장·run 제출을 하지 않습니다.
17
+ JSON 출력의 `mode: "links"`, `networkAccess: false`, `accountRequired: false`는
18
+ 이 **로컬 안내 명령**의 상태입니다. 웹사이트의 요금이나 가입 조건을 뜻하지 않습니다.
19
+
20
+ | 행동 | 목적지 | 용도 |
21
+ | --- | --- | --- |
22
+ | Plans / local Starter | `https://adaptorch.com/#pricing` | 로컬 평가와 호스티드 플랜 비교 |
23
+ | Sign up | `https://adaptorch.com/app/signup` | 사용자가 직접 가입 |
24
+ | Team / private-runner contact | `https://adaptorch.com/#bookDemo` | 팀·사설 러너 상담 |
25
+ | Claim boundary | `https://adaptorch.com/claim-boundary` | 검증 범위와 한계 확인 |
26
+
27
+ 실제 출력 URL에는 아래의 고정 UTM 태그가 붙습니다. 사용자가 링크를 열면 해당
28
+ 태그가 웹사이트로 전달됩니다. OMK 자체는 클릭을 관찰하거나 추적 요청을 보내지 않습니다.
29
+
30
+ 계정을 만든 뒤 API 연결을 확인하려면 키를 안전하게 설정하고 별도로 실행합니다.
31
+
32
+ ```bash
33
+ omk doctor adaptorch
34
+ omk doctor adaptorch --json
35
+ ```
36
+
37
+ 이 명령은 설정된 API의 `GET /v1/whoami`에 인증 요청을 보냅니다.
38
+ 종료 코드 `0`은 API 인증 성공, `1`은 미설정, `2`는 잘못된 설정이나 연결 실패입니다.
39
+ 인증 성공은 코드 검증, WPL 자동 실행, 배포 승인을 뜻하지 않습니다.
40
+ `--links`의 성공 종료 코드는 API 연결 여부와 무관합니다.
41
+
42
+ ## WPL 소비자에서 사용
43
+
44
+ ```typescript
45
+ import { getAdaptOrchLinks } from "omk-adaptorch-wpl";
46
+
47
+ const links = getAdaptOrchLinks(); // 기본 표면: wpl
48
+ // 사용자가 요청한 도움말이나 별도 제품 안내 화면에서 렌더링합니다.
49
+ console.log(links.plans, links.signup, links.contact, links.claimBoundary);
50
+ ```
51
+
52
+ `getAdaptOrchLinks("doctor")`는 CLI 유입용입니다. 함수는 매번 독립적인 링크 객체를
53
+ 반환하고 네트워크·환경 변수·사용자 파일에 접근하지 않습니다.
54
+ 링크를 판정 카드의 `next_actions`나 서명된 receipt에 삽입하지 마세요.
55
+ 가입·결제 여부는 `canApply`, `shouldSubmit`, 사람 검토 요구를 바꾸지 않습니다.
56
+
57
+ ## CRM 유입 구분과 개인정보 경계
58
+
59
+ - `utm_source=omk`
60
+ - `utm_campaign=omk-adaptorch-wpl`
61
+ - CLI: `utm_medium=cli`, `utm_content=doctor-{action}`
62
+ - WPL: `utm_medium=library`, `utm_content=wpl-{action}`
63
+ - `{action}`: `plans`, `signup`, `contact`, `claim-boundary`
64
+
65
+ 허용된 값만 사용합니다. 이메일, API 키, 프롬프트, diff, 저장소 경로, 세션 ID,
66
+ run ID를 URL에 추가하지 않습니다. 가격은 코드에 고정하지 않고 웹사이트가 소유합니다.
67
+
68
+ 사이트 운영 측에서는 사용자 동의와 개인정보 처리 정책에 따라 UTM 보존,
69
+ 가입 완료·상담 제출·활성화 이벤트를 연결해야 합니다. 이 변경은 해당 서버의
70
+ CRM 저장, 이메일 발송, 결제, 전환율을 구현하거나 검증하지 않습니다.
71
+ 단순 링크 생성 횟수를 방문자 수나 가입 전환으로 집계하면 안 됩니다.
72
+
73
+ ## 검증과 관련 문서
74
+
75
+ - `test/adaptorch-onboarding.test.ts`: 키 미접근, HTTP 미호출, 옵션 순서, JSON 계약
76
+ - `test/adaptorch-doctor-cli.test.ts`: 기존 연결 검사와 종료 코드 회귀
77
+ - `packages/adaptorch-wpl/test/service-links.test.ts`: 공개 export, 고정 목적지·UTM, 임의 입력 거부
78
+ - [Correctness Wall](correctness-wall.md): 적용·제출 게이트
79
+ - [AdaptOrch Preview](adaptorch-preview.md): 계획과 실제 실행 구분
80
+ - [하네스 개선 우선순위](harness-improvements.md): 이번 점검 범위와 후속 과제
@@ -22,6 +22,18 @@ There are two general isolation options:
22
22
  1. run the whole `omk` process inside an isolated environment, or
23
23
  2. run `omk` on the host and route tool execution into an isolated environment.
24
24
 
25
+ ### Policy composition
26
+
27
+ `mergeSandboxPolicy(base, override)` keeps the stronger enforcement mode and accepts
28
+ only a root inside the base root. An override cannot silently turn `enforce` into
29
+ `audit`/`off` or move the workspace elsewhere. Broader mode/root changes require the
30
+ trusted caller's explicit `{ allowBroaden: true }`; the flag is not user authentication.
31
+ These pure policy checks do not replace backend enforcement or isolate extension code.
32
+
33
+ Evidence configuration also fails closed: `FailClosedMergeGate` rejects empty,
34
+ sparse, or invalid gate lists and snapshots the supplied array. Later changes to
35
+ that array cannot remove the checks. This does not authenticate arbitrary gate code.
36
+
25
37
  ## Choose a pattern
26
38
 
27
39
  | Pattern | What is isolated | Best for | Notes |
@@ -0,0 +1,97 @@
1
+ # User context setup
2
+
3
+ OMK's shared defaults are provider-neutral, editable markdown. They do not ship
4
+ an operator's personal configuration, install skills, or enable external services.
5
+
6
+ ## Initialize an installed OMK
7
+
8
+ ```bash
9
+ omk init --global --dry-run
10
+ omk init --global
11
+ ```
12
+
13
+ The first command previews the operation without creating even the target directory.
14
+ The second creates missing documents in `~/.omk/agent/`. Both are offline and return
15
+ before migrations, settings, credentials, sessions, extensions, and model startup.
16
+ There is no install hook: installing or updating the npm package does not alter
17
+ user instructions, including when installed with `--ignore-scripts`.
18
+
19
+ Choose another user config directory with the existing environment override:
20
+
21
+ ```bash
22
+ OMK_CODING_AGENT_DIR="/path/to/omk-config" omk init --global --dry-run
23
+ OMK_CODING_AGENT_DIR="/path/to/omk-config" omk init --global
24
+ ```
25
+
26
+ Use the same override when starting OMK. PowerShell users can set
27
+ `$env:OMK_CODING_AGENT_DIR` before running the commands. Paths with spaces and
28
+ non-ASCII characters are supported. The destination must be a real directory,
29
+ not a file or symlink; parent directories should be trusted and user-controlled.
30
+ New files use owner-only permissions on POSIX. Existing directory modes are unchanged.
31
+
32
+ `--global` is required; `init` without a scope or with unsupported flags exits `2`.
33
+ `--help` exits `0`. Setup and preservation succeed with `0`; file or template errors
34
+ exit `1`. `--offline` is accepted but not needed for this command.
35
+
36
+ ## Documents and loading
37
+
38
+ | File | Purpose | Loading |
39
+ | --- | --- | --- |
40
+ | `AGENTS.md` | Work, verification, permissions, skills, runtime identity | Preferred global context entry point |
41
+ | `INTERNET.md` | Source selection, freshness, citations, network permissions | Read on demand when web work is needed |
42
+ | `CLAUDE.md` | Thin interoperability entry point referring to `AGENTS.md` | OMK fallback; another host needs explicit configuration |
43
+
44
+ OMK's entry-point search order within each directory is `AGENTS.md`, `AGENTS.MD`,
45
+ `CLAUDE.md`, then `CLAUDE.MD`; only the first readable file is used. Global context
46
+ loads before ancestor and working-directory context. Markdown links and Claude Code
47
+ `@` imports are not expanded by OMK. `INTERNET.md` and `SOUL.md` are not automatically
48
+ loaded by filename. The starter `AGENTS.md` tells the agent to read `INTERNET.md`
49
+ when relevant, so ordinary coding tasks do not carry the whole web guide.
50
+
51
+ Existing compatibility files `AGENTS.override.md`, `AGENTS.GODMODE.md`, `GODMODE.md`,
52
+ and `ENI.override.md` are also discovered in global and ancestor directories.
53
+ Setup does not generate, import, modify, or delete them. Review old files yourself
54
+ when migrating: installing a new guide does not retire an old override.
55
+
56
+ `--no-context-files` disables discovery. Claude models inside OMK omit discovered
57
+ context by default; `OMK_CLAUDE_CONTEXT_FILES=1` restores it. Setup does not change
58
+ that provider behavior or write the environment override. See [Usage](usage.md#context-files)
59
+ and [Environment variables](environment-variables.md).
60
+
61
+ ## Preserve and customize
62
+
63
+ - No `--force` or automatic overwrite mode is provided. Re-running setup preserves
64
+ existing files, including symlinks and directories at a document filename.
65
+ - If any case variant of `AGENTS.md` or `CLAUDE.md` already exists, setup skips both
66
+ entry-point templates. This avoids shadowing a Claude-only or uppercase setup,
67
+ and avoids a new compatibility import pointing to the wrong filename.
68
+ - A missing `INTERNET.md` can still be created. Any existing case variant is preserved.
69
+ - `settings.json`, authentication, models, MCP configuration, installed packages,
70
+ skills, shell profiles, other hosts' directories, and project files are untouched.
71
+ - Required templates are read before writing. An I/O failure while writing can leave
72
+ earlier files created; setup is not a multi-file transaction. Review the output
73
+ before retrying. Exclusive file creation prevents overwriting a concurrent file.
74
+
75
+ Back up existing documents before manually merging the defaults. Put project commands
76
+ in the project's `AGENTS.md`, local preferences in your global file or
77
+ `AGENTS.override.md`, and no credentials in either. Keep changes small and reload
78
+ with `/reload` or restart OMK. Already-recorded conversation text is not erased by reload.
79
+
80
+ For optional user-installed skills and `defaultActiveSkills`, see [Skills](skills.md)
81
+ and [Settings](settings.md). Neither a skill nor a markdown policy grants tool access.
82
+
83
+ ## Distribution and interoperability
84
+
85
+ The templates live in [`examples/context/`](../examples/context/) inside the package.
86
+ Existing npm `files` and binary asset-copy rules include `examples/`; the initializer
87
+ resolves that directory from the installed package, not from a developer's checkout.
88
+ `OMK_PACKAGE_DIR` retains its documented package-root override.
89
+
90
+ The same templates can be reviewed and copied manually from a source checkout.
91
+ `CLAUDE.md` uses a sibling `@AGENTS.md` import for Claude Code, but OMK does not install
92
+ it into `~/.claude/`. Opt into sharing from that host with an import to the actual
93
+ file path. Other hosts retain their own tool names, hooks, permission model, and
94
+ configuration; using a Claude model in OMK is not running Claude Code.
95
+
96
+ Public defaults are authored in the repository. Do not create a distribution by
97
+ copying a maintainer's agent home, credentials, private skills, or session history.
@@ -25,6 +25,14 @@ Structured next steps on the verdict card: **Apply**, **Deep Check**, **Regenera
25
25
 
26
26
  **Can apply** vs **should submit** are separate gates on the verification receipt: mechanical apply safety is not the same as trusting downstream submission.
27
27
 
28
+ `shouldSubmit` is fail-closed: it requires `canApply`, non-preview evaluation,
29
+ non-empty run IDs, and `CONFIRMED` outcome adjudication. Missing evidence,
30
+ verifier errors, corroborated failures, and previews never authorize submission.
31
+ If a deep check was requested, it must also complete. Its evidence must carry
32
+ non-blank digest and command values and exit code `0`; completion cannot clear
33
+ an existing policy requirement for human review. Local apply policy is unchanged.
34
+ These are evidence gates, not release, merge, or deployment authorization.
35
+
28
36
  ## Fast wall vs deep wall
29
37
 
30
38
  - **Fast wall (default):** Pure policy — diff paths, scope globs, secret-shaped lines, preview-only limits (`BATCH1_NO_DOCKER_RUNNER`). No Docker runner in batch 1.
@@ -238,6 +238,37 @@ For Anthropic-compatible providers using `api: "anthropic-messages"`, set `compa
238
238
  > Use `mistral-conversations` for native Mistral models.
239
239
  > If you intentionally route Mistral-compatible/custom endpoints through `openai-completions`, set `compat` flags explicitly as needed.
240
240
 
241
+ ### ChatGPT Web through codex-chatgpt-web
242
+
243
+ [codex-chatgpt-web](https://github.com/miuuyy/codex-chatgpt-web) runs a loopback Responses bridge (`http://127.0.0.1:17841/v1`) that drives a signed-in ChatGPT Web session from its own launcher. It was written for the Codex CLI, so it refuses a turn that lacks Codex's `client_metadata["x-codex-turn-metadata"]` (`thread_id`, `turn_id`) and the matching `turn_id` on the current user item. Set `compat.sendCodexTurnMetadata: true` on an `openai-responses` provider and OMK sends both: `thread_id` is the OMK session id and `turn_id` is derived from the latest user message, so tool rounds replay the same id and the next prompt starts a new browser turn.
244
+
245
+ ```json
246
+ {
247
+ "providers": {
248
+ "codex-chatgpt-web": {
249
+ "baseUrl": "http://127.0.0.1:17841/v1",
250
+ "api": "openai-responses",
251
+ "apiKey": "codex-chatgpt-web",
252
+ "compat": { "sendCodexTurnMetadata": true },
253
+ "models": [
254
+ { "id": "chatgpt-web/high", "name": "ChatGPT Web — High", "reasoning": true, "input": ["text", "image"], "contextWindow": 80000, "maxTokens": 32768 },
255
+ { "id": "chatgpt-web/pro", "name": "ChatGPT Web — Pro", "reasoning": true, "input": ["text", "image"], "contextWindow": 95000, "maxTokens": 32768, "thinkingLevelMap": { "max": "max" } }
256
+ ]
257
+ }
258
+ }
259
+ }
260
+ ```
261
+
262
+ The bridge ignores the bearer value for `chatgpt-web/*` models (the browser session is the credential), so any placeholder key satisfies OMK's key check. Each `chatgpt-web/*` id pins one ChatGPT mode (`luna`, `think`, `light`, `medium`, `high`, `extra-high`, `pro`, plus `zero-risk` / `zero-risk-pro` for the launcher's manual mode); the bridge fixes the effort per id and ignores the request's `reasoning.effort`, and `pro`/`extra-high` fail explicitly unless the signed-in account exposes them. In the launcher's browser-only mode the model cannot call OMK tools; full mode routes tool calls back through the bridge's MCP connector.
263
+
264
+ OMK's coding-agent supplies its resolved session cwd as a trusted `workspace-write` Codex environment when this compatibility flag is enabled. Direct `omk-ai` callers must pass an absolute `options.cwd` to enable Full harness tools; an absent or relative cwd deliberately carries no filesystem authority, so Full mode fails closed. Bridge 5.0.x binds that environment to the turn metadata (`sandbox`, `workspaces`) and the adjacent `<environment_context>` item; OMK emits exactly that pair, verified against launcher 5.0.4 in full mode with a tool round trip.
265
+
266
+ **Keep the rows in step with the launcher.** The bridge's `/v1/models` document is the only account-aware source, and it publishes two numbers per row: `context_window` is the ceiling past which the bridge rejects a turn, and `auto_compact_token_limit` is the budget it expects a client to compact within (Codex's effective window, 85% of the ceiling). OMK's `contextWindow` drives OMK's own compaction policy (`compaction.maxUsageRatio`, default 0.9, plus output reserves), so the row carries the **budget**: `contextWindow: 80000` above is the launcher's Plus High budget under a 90,000 ceiling, `95000` the Pro budget (ceiling 111,193, or 112,193 for `chatgpt-web/pro`), and a Pro account with Bigger Context advertises 285,000 under 333,579 / 336,579. With the budget in place OMK compacts at about 90% of it, comfortably inside what the bridge accepts. `omk provider sync codex-chatgpt-web` reads the document and rewrites the provider's `chatgpt-web/*` rows (`name`, `contextWindow`, `reasoning`, `input`), preserving `maxTokens`, `cost`, `thinkingLevelMap`, other keys, other providers, and the file's indentation, and records where the numbers came from as `bridgeCatalog` on the provider (`bridgeVersion`, `clientVersion`, `syncedAt`, and each row's `contextCeilings`). `--dry-run` reports the drift without writing and `--json` emits one document; a launcher upgrade or a changed ceiling is recorded even when no row moves. The bridge forwards `/v1/models` to the Codex backend, so the command authenticates with OMK's `openai-codex` OAuth (`/login openai-codex`) and sends a `client_version` (`--client-version`, `OMK_CODEX_CLIENT_VERSION`, `codex --version`, then OMK's last verified version): the backend hides models from clients it considers too old. `omk provider doctor codex-chatgpt-web --level 1` reports the `models-endpoint` probe as failed for this bridge because it probes with the placeholder bearer; use `provider sync --dry-run` as the bridge health check instead.
267
+
268
+ Effort is chosen by the slug, not by OMK's thinking level: `chatgpt-web/pro` runs every turn at ChatGPT's Pro effort (verified on launcher 5.0.4: the browser trace records the effort control switching to a distinct label for medium, high, and pro turns), so pick the `pro` row when you want the maximum. The response length is not capped by OMK either: the bridge accepts `max_output_tokens` but never applies it to a browser turn, so `maxTokens` only sizes OMK's own compaction-summary and context-governor budgets.
269
+
270
+ When the launcher is not running, a turn on a bridge model fails with a message that names the launcher instead of the SDK's generic connection error.
271
+
241
272
  ### Auth Header
242
273
 
243
274
  If your provider expects `Authorization: Bearer <key>` but doesn't use a standard API, set `authHeader: true`:
@@ -721,6 +752,10 @@ interface ProviderModelConfig {
721
752
  thinkingFormat?: "openai" | "openrouter" | "deepseek" | "together" | "zai" | "qwen" | "qwen-chat-template";
722
753
  cacheControlFormat?: "anthropic";
723
754
 
755
+ // openai-responses
756
+ sendSessionIdHeader?: boolean;
757
+ sendCodexTurnMetadata?: boolean;
758
+
724
759
  // anthropic-messages
725
760
  supportsEagerToolInputStreaming?: boolean;
726
761
  supportsLongCacheRetention?: boolean;
@@ -56,11 +56,26 @@ Never use `__dirname` directly for package assets.
56
56
  ## Testing
57
57
 
58
58
  ```bash
59
- ./test.sh # Run non-LLM tests (no API keys needed)
60
- npm test # Run all tests
61
- npm test -- test/specific.test.ts # Run specific test
59
+ ./test.sh # Run the non-LLM suite when a full run is intended
60
+ # Narrow, offline regression from the repository root:
61
+ LIVE_E2E=0 node node_modules/vitest/dist/cli.js --run packages/coding-agent/test/adaptorch-onboarding.test.ts
62
62
  ```
63
63
 
64
+ The root `vitest.config.ts` delegates to each package's Vitest project. This
65
+ preserves package-local setup files and source aliases; a root invocation must
66
+ not silently test stale `dist` dependencies. The coding-agent project resolves
67
+ `omk-adaptorch-wpl` to its source entrypoint during tests.
68
+
69
+ Package-local targeted commands continue to work, for example from
70
+ `packages/coding-agent`:
71
+
72
+ ```bash
73
+ LIVE_E2E=0 node ../../node_modules/vitest/dist/cli.js --run test/adaptorch-onboarding.test.ts
74
+ ```
75
+
76
+ Keep explicit file filters for routine work. A keyless regression pass is not a
77
+ live-provider or release verification, and unfiltered suites may include e2e tests.
78
+
64
79
  ## Project Structure
65
80
 
66
81
  ```
@@ -82,6 +82,8 @@ These variables are read by OMK itself. The four built-in harness flags below ar
82
82
  | `OMK_SKIP_VERSION_CHECK` | Disable the latest-version request |
83
83
  | `OMK_TELEMETRY` | Override install/update telemetry and provider attribution headers: `1`/`true`/`yes` or `0`/`false`/`no` |
84
84
  | `OMK_SHARE_VIEWER_URL` | Override the base URL used by `/share` |
85
+ | `PI_DISABLE_INPUT_REDACTION` | Stop masking credentials on the way to the model and the session. Persistence and report boundaries still mask |
86
+ | `OMK_DISABLE_REDACTION` | Alias for the input-redaction opt-out when `PI_DISABLE_INPUT_REDACTION` is unset. Only `1`/`true`/`yes`/`on` enable it. Forced persistence/report redaction remains active; this does not disable masking everywhere |
85
87
  | `OMK_HARDWARE_CURSOR` | Set to `1` to show the hardware cursor; see [Terminal setup](terminal-setup.md) |
86
88
  | `OMK_CONTEXT_GOVERNOR` | Context Budget V2 process override: `1` forces it on and `0` forces it off; otherwise the global `contextBudget.enabled` setting applies |
87
89
  | `OMK_CONTEXT_GOVERNOR_CACHE` | Set to `memory` to keep representations, negative results, and plans in session memory instead of persisting representations per workspace |
@@ -68,6 +68,10 @@ Do not select `grok-imagine-image`, `grok-imagine-image-quality`, `grok-imagine-
68
68
 
69
69
  Use the normal OMK lane grant model: grant the smallest skill and MCP surface that matches the task, and keep media exceptions explicit.
70
70
 
71
+ For each non-queued native `xai` request started through `AgentSession.prompt()`, OMK calls `selectGrokHarnessSkills()` against the live discovered skill descriptions after ordinary prompt-template expansion. It merges up to three matches with explicit/settings selections and rebuilds that turn's `<active_skills>` marker.
72
+
73
+ The pure `selectSkills()` scorer uses the task plus independent camelCase-aware path-to-skill-name signals, weak 0.35 / strong 0.7 thresholds, deterministic input-order ties, and first-name-wins deduplication. Explicit-only skills are never auto-selected. `headroom` is added only for lexical pressure cues or the session's measured context-pressure bucket. A task with no signals yields an empty automatic grant rather than the full allowlist. Messages queued through `steer`, `followUp`, or `prompt(..., { streamingBehavior })` retain the active run's system prompt; they do not trigger a second skill-selection rebuild.
74
+
71
75
  | Task class | Skills | MCP |
72
76
  | --- | --- | --- |
73
77
  | Multi-package or repo-context work | `packages`; add `headroom` only under context pressure | none by default |