open-multi-agent-kit 0.98.2 → 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 (286) hide show
  1. package/CHANGELOG.md +45 -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/advisory-judge-model.d.ts.map +1 -1
  38. package/dist/core/advisory-judge-model.js +8 -1
  39. package/dist/core/advisory-judge-model.js.map +1 -1
  40. package/dist/core/advisory-judge-types.d.ts +18 -1
  41. package/dist/core/advisory-judge-types.d.ts.map +1 -1
  42. package/dist/core/advisory-judge-types.js.map +1 -1
  43. package/dist/core/advisory-judge.d.ts.map +1 -1
  44. package/dist/core/advisory-judge.js +41 -6
  45. package/dist/core/advisory-judge.js.map +1 -1
  46. package/dist/core/agent-session-services.d.ts +2 -0
  47. package/dist/core/agent-session-services.d.ts.map +1 -1
  48. package/dist/core/agent-session-services.js +2 -0
  49. package/dist/core/agent-session-services.js.map +1 -1
  50. package/dist/core/agent-session.d.ts +0 -1
  51. package/dist/core/agent-session.d.ts.map +1 -1
  52. package/dist/core/agent-session.js +30 -85
  53. package/dist/core/agent-session.js.map +1 -1
  54. package/dist/core/codex-chatgpt-web-bridge.d.ts +99 -0
  55. package/dist/core/codex-chatgpt-web-bridge.d.ts.map +1 -0
  56. package/dist/core/codex-chatgpt-web-bridge.js +192 -0
  57. package/dist/core/codex-chatgpt-web-bridge.js.map +1 -0
  58. package/dist/core/codex-chatgpt-web-sync.d.ts +50 -0
  59. package/dist/core/codex-chatgpt-web-sync.d.ts.map +1 -0
  60. package/dist/core/codex-chatgpt-web-sync.js +119 -0
  61. package/dist/core/codex-chatgpt-web-sync.js.map +1 -0
  62. package/dist/core/compaction/compaction-headroom.d.ts +30 -0
  63. package/dist/core/compaction/compaction-headroom.d.ts.map +1 -0
  64. package/dist/core/compaction/compaction-headroom.js +48 -0
  65. package/dist/core/compaction/compaction-headroom.js.map +1 -0
  66. package/dist/core/compaction/compaction.d.ts +2 -29
  67. package/dist/core/compaction/compaction.d.ts.map +1 -1
  68. package/dist/core/compaction/compaction.js +19 -47
  69. package/dist/core/compaction/compaction.js.map +1 -1
  70. package/dist/core/compaction/overflow-retry-guard.d.ts +20 -0
  71. package/dist/core/compaction/overflow-retry-guard.d.ts.map +1 -0
  72. package/dist/core/compaction/overflow-retry-guard.js +38 -0
  73. package/dist/core/compaction/overflow-retry-guard.js.map +1 -0
  74. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  75. package/dist/core/context-budget-headroom-types.js +1 -1
  76. package/dist/core/context-budget-headroom-types.js.map +1 -1
  77. package/dist/core/context-budget-token-counter-types.d.ts +27 -0
  78. package/dist/core/context-budget-token-counter-types.d.ts.map +1 -0
  79. package/dist/core/context-budget-token-counter-types.js +2 -0
  80. package/dist/core/context-budget-token-counter-types.js.map +1 -0
  81. package/dist/core/context-budget-token-counter.d.ts +2 -26
  82. package/dist/core/context-budget-token-counter.d.ts.map +1 -1
  83. package/dist/core/context-budget-token-counter.js +2 -0
  84. package/dist/core/context-budget-token-counter.js.map +1 -1
  85. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  86. package/dist/core/context-budget-v2-scoring.js +14 -10
  87. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  88. package/dist/core/domain-router.d.ts.map +1 -1
  89. package/dist/core/domain-router.js +1 -1
  90. package/dist/core/domain-router.js.map +1 -1
  91. package/dist/core/grok-harness-dispatch.d.ts +4 -0
  92. package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
  93. package/dist/core/grok-harness-dispatch.js +20 -3
  94. package/dist/core/grok-harness-dispatch.js.map +1 -1
  95. package/dist/core/grok-harness.d.ts +15 -9
  96. package/dist/core/grok-harness.d.ts.map +1 -1
  97. package/dist/core/grok-harness.js +34 -8
  98. package/dist/core/grok-harness.js.map +1 -1
  99. package/dist/core/mcp/tools.d.ts +2 -2
  100. package/dist/core/mcp/tools.d.ts.map +1 -1
  101. package/dist/core/mcp/tools.js +29 -3
  102. package/dist/core/mcp/tools.js.map +1 -1
  103. package/dist/core/model-registry-schema.d.ts +1081 -0
  104. package/dist/core/model-registry-schema.d.ts.map +1 -0
  105. package/dist/core/model-registry-schema.js +148 -0
  106. package/dist/core/model-registry-schema.js.map +1 -0
  107. package/dist/core/model-registry.d.ts.map +1 -1
  108. package/dist/core/model-registry.js +1 -146
  109. package/dist/core/model-registry.js.map +1 -1
  110. package/dist/core/model-resolver.d.ts +2 -1
  111. package/dist/core/model-resolver.d.ts.map +1 -1
  112. package/dist/core/model-resolver.js +2 -1
  113. package/dist/core/model-resolver.js.map +1 -1
  114. package/dist/core/prompt-preset.d.ts +1 -1
  115. package/dist/core/prompt-preset.d.ts.map +1 -1
  116. package/dist/core/prompt-preset.js +16 -1
  117. package/dist/core/prompt-preset.js.map +1 -1
  118. package/dist/core/provider-display-names.d.ts.map +1 -1
  119. package/dist/core/provider-display-names.js +1 -0
  120. package/dist/core/provider-display-names.js.map +1 -1
  121. package/dist/core/provider-resilience.d.ts +8 -0
  122. package/dist/core/provider-resilience.d.ts.map +1 -1
  123. package/dist/core/provider-resilience.js +20 -3
  124. package/dist/core/provider-resilience.js.map +1 -1
  125. package/dist/core/provider-usage-types.d.ts +42 -0
  126. package/dist/core/provider-usage-types.d.ts.map +1 -0
  127. package/dist/core/provider-usage-types.js +2 -0
  128. package/dist/core/provider-usage-types.js.map +1 -0
  129. package/dist/core/provider-usage.d.ts +2 -31
  130. package/dist/core/provider-usage.d.ts.map +1 -1
  131. package/dist/core/provider-usage.js +4 -0
  132. package/dist/core/provider-usage.js.map +1 -1
  133. package/dist/core/redaction.d.ts.map +1 -1
  134. package/dist/core/redaction.js +18 -2
  135. package/dist/core/redaction.js.map +1 -1
  136. package/dist/core/sandbox/policy-merge.d.ts +6 -0
  137. package/dist/core/sandbox/policy-merge.d.ts.map +1 -0
  138. package/dist/core/sandbox/policy-merge.js +74 -0
  139. package/dist/core/sandbox/policy-merge.js.map +1 -0
  140. package/dist/core/sandbox/policy-paths.d.ts +4 -0
  141. package/dist/core/sandbox/policy-paths.d.ts.map +1 -0
  142. package/dist/core/sandbox/policy-paths.js +21 -0
  143. package/dist/core/sandbox/policy-paths.js.map +1 -0
  144. package/dist/core/sandbox/policy-types.d.ts +75 -0
  145. package/dist/core/sandbox/policy-types.d.ts.map +1 -0
  146. package/dist/core/sandbox/policy-types.js +2 -0
  147. package/dist/core/sandbox/policy-types.js.map +1 -0
  148. package/dist/core/sandbox/policy.d.ts +3 -77
  149. package/dist/core/sandbox/policy.d.ts.map +1 -1
  150. package/dist/core/sandbox/policy.js +3 -98
  151. package/dist/core/sandbox/policy.js.map +1 -1
  152. package/dist/core/sdk-provider-stream.d.ts +14 -0
  153. package/dist/core/sdk-provider-stream.d.ts.map +1 -0
  154. package/dist/core/sdk-provider-stream.js +38 -0
  155. package/dist/core/sdk-provider-stream.js.map +1 -0
  156. package/dist/core/sdk.d.ts +5 -1
  157. package/dist/core/sdk.d.ts.map +1 -1
  158. package/dist/core/sdk.js +17 -33
  159. package/dist/core/sdk.js.map +1 -1
  160. package/dist/core/session-bash-runtime.d.ts +7 -0
  161. package/dist/core/session-bash-runtime.d.ts.map +1 -1
  162. package/dist/core/session-bash-runtime.js +10 -1
  163. package/dist/core/session-bash-runtime.js.map +1 -1
  164. package/dist/core/session-failure-cause.d.ts.map +1 -1
  165. package/dist/core/session-failure-cause.js +10 -3
  166. package/dist/core/session-failure-cause.js.map +1 -1
  167. package/dist/core/session-run-termination.d.ts +18 -0
  168. package/dist/core/session-run-termination.d.ts.map +1 -0
  169. package/dist/core/session-run-termination.js +61 -0
  170. package/dist/core/session-run-termination.js.map +1 -0
  171. package/dist/core/session-termination.d.ts.map +1 -1
  172. package/dist/core/session-termination.js +1 -1
  173. package/dist/core/session-termination.js.map +1 -1
  174. package/dist/core/skill-selector.d.ts +40 -0
  175. package/dist/core/skill-selector.d.ts.map +1 -0
  176. package/dist/core/skill-selector.js +102 -0
  177. package/dist/core/skill-selector.js.map +1 -0
  178. package/dist/core/tools/render-utils.d.ts.map +1 -1
  179. package/dist/core/tools/render-utils.js +2 -4
  180. package/dist/core/tools/render-utils.js.map +1 -1
  181. package/dist/core/turn-metrics-record.d.ts +55 -0
  182. package/dist/core/turn-metrics-record.d.ts.map +1 -0
  183. package/dist/core/turn-metrics-record.js +149 -0
  184. package/dist/core/turn-metrics-record.js.map +1 -0
  185. package/dist/core/turn-metrics.d.ts +4 -56
  186. package/dist/core/turn-metrics.d.ts.map +1 -1
  187. package/dist/core/turn-metrics.js +12 -60
  188. package/dist/core/turn-metrics.js.map +1 -1
  189. package/dist/core/verified-bash-runtime.d.ts +40 -0
  190. package/dist/core/verified-bash-runtime.d.ts.map +1 -1
  191. package/dist/core/verified-bash-runtime.js +60 -13
  192. package/dist/core/verified-bash-runtime.js.map +1 -1
  193. package/dist/guardrails/evidence-system.d.ts +1 -1
  194. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  195. package/dist/guardrails/evidence-system.js +18 -29
  196. package/dist/guardrails/evidence-system.js.map +1 -1
  197. package/dist/guardrails/merge-gate-result.d.ts +4 -0
  198. package/dist/guardrails/merge-gate-result.d.ts.map +1 -0
  199. package/dist/guardrails/merge-gate-result.js +32 -0
  200. package/dist/guardrails/merge-gate-result.js.map +1 -0
  201. package/dist/index.d.ts +2 -0
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +1 -0
  204. package/dist/index.js.map +1 -1
  205. package/dist/main.d.ts.map +1 -1
  206. package/dist/main.js +22 -22
  207. package/dist/main.js.map +1 -1
  208. package/dist/modes/interactive/interactive-login-options.d.ts +27 -0
  209. package/dist/modes/interactive/interactive-login-options.d.ts.map +1 -0
  210. package/dist/modes/interactive/interactive-login-options.js +54 -0
  211. package/dist/modes/interactive/interactive-login-options.js.map +1 -0
  212. package/dist/modes/interactive/interactive-mode.d.ts +7 -4
  213. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  214. package/dist/modes/interactive/interactive-mode.js +138 -140
  215. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  216. package/dist/modes/interactive/interactive-resume-command.d.ts +3 -0
  217. package/dist/modes/interactive/interactive-resume-command.d.ts.map +1 -0
  218. package/dist/modes/interactive/interactive-resume-command.js +24 -0
  219. package/dist/modes/interactive/interactive-resume-command.js.map +1 -0
  220. package/dist/modes/interactive/interactive-tool-result.d.ts +32 -0
  221. package/dist/modes/interactive/interactive-tool-result.d.ts.map +1 -0
  222. package/dist/modes/interactive/interactive-tool-result.js +59 -0
  223. package/dist/modes/interactive/interactive-tool-result.js.map +1 -0
  224. package/dist/modes/print-mode.d.ts.map +1 -1
  225. package/dist/modes/print-mode.js +22 -0
  226. package/dist/modes/print-mode.js.map +1 -1
  227. package/dist/utils/clipboard-image.d.ts.map +1 -1
  228. package/dist/utils/clipboard-image.js +10 -60
  229. package/dist/utils/clipboard-image.js.map +1 -1
  230. package/dist/utils/terminal-links.d.ts +13 -0
  231. package/dist/utils/terminal-links.d.ts.map +1 -0
  232. package/dist/utils/terminal-links.js +68 -0
  233. package/dist/utils/terminal-links.js.map +1 -0
  234. package/dist/utils/windows-clipboard-image.d.ts +16 -0
  235. package/dist/utils/windows-clipboard-image.d.ts.map +1 -0
  236. package/dist/utils/windows-clipboard-image.js +87 -0
  237. package/dist/utils/windows-clipboard-image.js.map +1 -0
  238. package/docs/adaptorch-onboarding.md +80 -0
  239. package/docs/advisory-selection.md +112 -0
  240. package/docs/containerization.md +12 -0
  241. package/docs/context-files.md +97 -0
  242. package/docs/correctness-wall.md +8 -0
  243. package/docs/custom-provider.md +35 -0
  244. package/docs/development.md +18 -3
  245. package/docs/environment-variables.md +2 -0
  246. package/docs/grok-harness.md +4 -0
  247. package/docs/harness-boundaries.md +154 -0
  248. package/docs/harness-improvements.md +90 -0
  249. package/docs/json.md +19 -0
  250. package/docs/keybindings.md +1 -1
  251. package/docs/mcp.md +22 -2
  252. package/docs/metrics.md +66 -16
  253. package/docs/model-catalog-refresh.md +190 -0
  254. package/docs/model-contract.md +168 -0
  255. package/docs/models.md +21 -4
  256. package/docs/provider-resilience.md +5 -3
  257. package/docs/providers.md +68 -1
  258. package/docs/quickstart.md +4 -0
  259. package/docs/release-audit-0.98.3.md +97 -0
  260. package/docs/release-audit-0.98.4.md +112 -0
  261. package/docs/review-bundle-followup.md +195 -0
  262. package/docs/run-protocol.md +3 -1
  263. package/docs/runtime-algorithms.md +38 -2
  264. package/docs/sdk.md +35 -3
  265. package/docs/sessions.md +1 -1
  266. package/docs/settings.md +17 -1
  267. package/docs/skills.md +2 -0
  268. package/docs/tb21-audit.md +131 -0
  269. package/docs/terminal-setup.md +20 -0
  270. package/docs/usage.md +23 -1
  271. package/docs/windows.md +48 -0
  272. package/examples/README.md +4 -0
  273. package/examples/context/AGENTS.md +64 -0
  274. package/examples/context/CLAUDE.md +17 -0
  275. package/examples/context/INTERNET.md +42 -0
  276. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  277. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  278. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  279. package/examples/extensions/gondolin/package-lock.json +2 -2
  280. package/examples/extensions/gondolin/package.json +1 -1
  281. package/examples/extensions/sandbox/package-lock.json +2 -2
  282. package/examples/extensions/sandbox/package.json +1 -1
  283. package/examples/extensions/with-deps/package-lock.json +2 -2
  284. package/examples/extensions/with-deps/package.json +1 -1
  285. package/npm-shrinkwrap.json +18 -18
  286. package/package.json +6 -6
@@ -1,4 +1,4 @@
1
- import { AdaptOrchApiError, createAdaptOrchApiClientFromEnv, } from "omk-adaptorch-wpl";
1
+ import { AdaptOrchApiError, createAdaptOrchApiClientFromEnv, getAdaptOrchLinks, } from "omk-adaptorch-wpl";
2
2
  /**
3
3
  * Headless AdaptOrch connectivity check:
4
4
  *
@@ -17,20 +17,14 @@ import { AdaptOrchApiError, createAdaptOrchApiClientFromEnv, } from "omk-adaptor
17
17
  * The credential is never printed. `omk-adaptorch-wpl` already scrubs it from
18
18
  * its own errors; this command additionally never echoes the configured value.
19
19
  */
20
- const USAGE = "Usage: omk doctor adaptorch [--json]";
21
- /**
22
- * Where to obtain a key. This is the one moment in the CLI where the reader has
23
- * explicitly asked about AdaptOrch, so answering "which key, from where" here
24
- * is help rather than promotion. It carries its own attribution so this
25
- * touchpoint stays distinguishable from the README links.
26
- */
27
- const ADAPTORCH_SIGNUP_URL = "https://adaptorch.com/?utm_source=omk-cli&utm_medium=doctor&utm_campaign=omk#pricing";
20
+ const USAGE = "Usage: omk doctor adaptorch [--links] [--json]\n --links Show signup, plans, and contact links offline (no API key or network).";
28
21
  function describe(report) {
29
22
  if (!report.configured) {
30
23
  return [
31
24
  "AdaptOrch: not configured",
32
25
  " Set ADAPTORCH_API_KEY to enable it. Optionally set ADAPTORCH_API_URL.",
33
- ` Get a key: ${ADAPTORCH_SIGNUP_URL}`,
26
+ ` Create an account: ${getAdaptOrchLinks("doctor").signup}`,
27
+ " Plans and contact (offline): omk doctor adaptorch --links",
34
28
  " AdaptOrch is a separate product; OMK does not require it.",
35
29
  ];
36
30
  }
@@ -74,7 +68,12 @@ export async function runAdaptOrchDoctorCli(args, overrides = {}) {
74
68
  }
75
69
  const writeLine = overrides.writeLine ?? ((line) => console.log(line));
76
70
  let json = false;
71
+ let links = false;
77
72
  for (const arg of args.slice(2)) {
73
+ if (arg === "--links") {
74
+ links = true;
75
+ continue;
76
+ }
78
77
  if (arg === "--json") {
79
78
  json = true;
80
79
  continue;
@@ -87,6 +86,29 @@ export async function runAdaptOrchDoctorCli(args, overrides = {}) {
87
86
  writeLine(USAGE);
88
87
  return { handled: true, exitCode: 2 };
89
88
  }
89
+ if (links) {
90
+ const report = {
91
+ mode: "links",
92
+ networkAccess: false,
93
+ accountRequired: false,
94
+ links: getAdaptOrchLinks("doctor"),
95
+ };
96
+ if (json)
97
+ writeLine(JSON.stringify(report, null, 2));
98
+ else {
99
+ for (const line of [
100
+ "AdaptOrch — optional service, not required by OMK or WPL",
101
+ ` Plans / local Starter: ${report.links.plans}`,
102
+ ` Sign up: ${report.links.signup}`,
103
+ ` Team / private-runner contact: ${report.links.contact}`,
104
+ ` Claim boundary: ${report.links.claimBoundary}`,
105
+ " Next: configure ADAPTORCH_API_KEY, then run omk doctor adaptorch to check API connectivity.",
106
+ " Offline links only: no account created, data sent, browser opened, or verification run submitted.",
107
+ ])
108
+ writeLine(line);
109
+ }
110
+ return { handled: true, exitCode: 0 };
111
+ }
90
112
  const env = overrides.env ?? process.env;
91
113
  const fetchImpl = overrides.fetch ?? globalThis.fetch;
92
114
  let report;
@@ -1 +1 @@
1
- {"version":3,"file":"adaptorch-doctor-cli.js","sourceRoot":"","sources":["../../src/commands/adaptorch-doctor-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AdaptOrchApiClient,\n\tAdaptOrchApiError,\n\ttype AdaptOrchFetch,\n\tcreateAdaptOrchApiClientFromEnv,\n} from \"omk-adaptorch-wpl\";\n\n/**\n * Headless AdaptOrch connectivity check:\n *\n * omk doctor adaptorch [--json]\n *\n * One command answers the only question that blocks getting started: does the\n * configured key reach the hosted API? It calls `GET /v1/whoami`, which is the\n * cheapest authenticated read in the contract, and reports the principal it\n * resolved to.\n *\n * The exit code carries the verdict so a script can branch without parsing\n * prose: 0 verified, 1 not configured, 2 configured but unreachable. Those are\n * genuinely different states — \"no key\" is a setup step, while \"key rejected\"\n * is a broken setup, and collapsing them would make the command useless in CI.\n *\n * The credential is never printed. `omk-adaptorch-wpl` already scrubs it from\n * its own errors; this command additionally never echoes the configured value.\n */\n\nconst USAGE = \"Usage: omk doctor adaptorch [--json]\";\n\n/**\n * Where to obtain a key. This is the one moment in the CLI where the reader has\n * explicitly asked about AdaptOrch, so answering \"which key, from where\" here\n * is help rather than promotion. It carries its own attribution so this\n * touchpoint stays distinguishable from the README links.\n */\nconst ADAPTORCH_SIGNUP_URL = \"https://adaptorch.com/?utm_source=omk-cli&utm_medium=doctor&utm_campaign=omk#pricing\";\n\nexport interface AdaptOrchDoctorCliOverrides {\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly writeLine?: (line: string) => void;\n\t/** Test seam: replaces the injected HTTP boundary (defaults to global fetch). */\n\treadonly fetch?: AdaptOrchFetch;\n}\n\nexport interface AdaptOrchDoctorCliOutcome {\n\treadonly handled: boolean;\n\treadonly exitCode: number;\n}\n\n/** Bounded report shape. Carries no credential, URL credentials, or raw error bodies. */\ninterface AdaptOrchDoctorReport {\n\treadonly configured: boolean;\n\treadonly reachable: boolean;\n\treadonly subjectId?: string;\n\treadonly projectId?: string;\n\treadonly status?: number;\n\treadonly code?: string;\n\treadonly error?: string;\n}\n\nfunction describe(report: AdaptOrchDoctorReport): string[] {\n\tif (!report.configured) {\n\t\treturn [\n\t\t\t\"AdaptOrch: not configured\",\n\t\t\t\" Set ADAPTORCH_API_KEY to enable it. Optionally set ADAPTORCH_API_URL.\",\n\t\t\t` Get a key: ${ADAPTORCH_SIGNUP_URL}`,\n\t\t\t\" AdaptOrch is a separate product; OMK does not require it.\",\n\t\t];\n\t}\n\tif (!report.reachable) {\n\t\tconst detail =\n\t\t\treport.status === undefined ? \"\" : ` (HTTP ${report.status}${report.code ? ` ${report.code}` : \"\"})`;\n\t\treturn [`AdaptOrch: unreachable${detail}`, ` ${report.error ?? \"the request did not complete\"}`];\n\t}\n\tconst scope = report.projectId ? `, project ${report.projectId}` : \"\";\n\treturn [`AdaptOrch: verified`, ` Authenticated as ${report.subjectId ?? \"(unknown subject)\"}${scope}`];\n}\n\nasync function probe(client: AdaptOrchApiClient): Promise<AdaptOrchDoctorReport> {\n\ttry {\n\t\tconst principal = await client.whoami();\n\t\treturn {\n\t\t\tconfigured: true,\n\t\t\treachable: true,\n\t\t\tsubjectId: principal.subject_id,\n\t\t\t...(principal.project_id === undefined ? {} : { projectId: principal.project_id }),\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof AdaptOrchApiError) {\n\t\t\treturn {\n\t\t\t\tconfigured: true,\n\t\t\t\treachable: false,\n\t\t\t\tstatus: error.status,\n\t\t\t\t...(error.code === undefined ? {} : { code: error.code }),\n\t\t\t\terror: error.message,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tconfigured: true,\n\t\t\treachable: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t}\n}\n\nexport async function runAdaptOrchDoctorCli(\n\targs: readonly string[],\n\toverrides: AdaptOrchDoctorCliOverrides = {},\n): Promise<AdaptOrchDoctorCliOutcome> {\n\tif (args[0] !== \"doctor\" || args[1] !== \"adaptorch\") {\n\t\treturn { handled: false, exitCode: 0 };\n\t}\n\tconst writeLine = overrides.writeLine ?? ((line: string) => console.log(line));\n\n\tlet json = false;\n\tfor (const arg of args.slice(2)) {\n\t\tif (arg === \"--json\") {\n\t\t\tjson = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\twriteLine(USAGE);\n\t\t\treturn { handled: true, exitCode: 0 };\n\t\t}\n\t\twriteLine(`Unknown option: ${arg}`);\n\t\twriteLine(USAGE);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\n\tconst env = overrides.env ?? process.env;\n\tconst fetchImpl = overrides.fetch ?? (globalThis.fetch as unknown as AdaptOrchFetch);\n\n\tlet report: AdaptOrchDoctorReport;\n\ttry {\n\t\tconst client = createAdaptOrchApiClientFromEnv(fetchImpl, env);\n\t\treport = client ? await probe(client) : { configured: false, reachable: false };\n\t} catch (error) {\n\t\t// A configured but invalid setup (an unsafe ADAPTORCH_API_URL, for\n\t\t// example) is a broken setup, not an absent one.\n\t\treport = {\n\t\t\tconfigured: true,\n\t\t\treachable: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t}\n\n\tif (json) writeLine(JSON.stringify(report, null, 2));\n\telse for (const line of describe(report)) writeLine(line);\n\n\tif (!report.configured) return { handled: true, exitCode: 1 };\n\treturn { handled: true, exitCode: report.reachable ? 0 : 2 };\n}\n"]}
1
+ {"version":3,"file":"adaptorch-doctor-cli.js","sourceRoot":"","sources":["../../src/commands/adaptorch-doctor-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AdaptOrchApiClient,\n\tAdaptOrchApiError,\n\ttype AdaptOrchFetch,\n\tcreateAdaptOrchApiClientFromEnv,\n\tgetAdaptOrchLinks,\n} from \"omk-adaptorch-wpl\";\n\n/**\n * Headless AdaptOrch connectivity check:\n *\n * omk doctor adaptorch [--json]\n *\n * One command answers the only question that blocks getting started: does the\n * configured key reach the hosted API? It calls `GET /v1/whoami`, which is the\n * cheapest authenticated read in the contract, and reports the principal it\n * resolved to.\n *\n * The exit code carries the verdict so a script can branch without parsing\n * prose: 0 verified, 1 not configured, 2 configured but unreachable. Those are\n * genuinely different states — \"no key\" is a setup step, while \"key rejected\"\n * is a broken setup, and collapsing them would make the command useless in CI.\n *\n * The credential is never printed. `omk-adaptorch-wpl` already scrubs it from\n * its own errors; this command additionally never echoes the configured value.\n */\n\nconst USAGE =\n\t\"Usage: omk doctor adaptorch [--links] [--json]\\n --links Show signup, plans, and contact links offline (no API key or network).\";\n\nexport interface AdaptOrchDoctorCliOverrides {\n\treadonly env?: NodeJS.ProcessEnv;\n\treadonly writeLine?: (line: string) => void;\n\t/** Test seam: replaces the injected HTTP boundary (defaults to global fetch). */\n\treadonly fetch?: AdaptOrchFetch;\n}\n\nexport interface AdaptOrchDoctorCliOutcome {\n\treadonly handled: boolean;\n\treadonly exitCode: number;\n}\n\n/** Bounded report shape. Carries no credential, URL credentials, or raw error bodies. */\ninterface AdaptOrchDoctorReport {\n\treadonly configured: boolean;\n\treadonly reachable: boolean;\n\treadonly subjectId?: string;\n\treadonly projectId?: string;\n\treadonly status?: number;\n\treadonly code?: string;\n\treadonly error?: string;\n}\n\nfunction describe(report: AdaptOrchDoctorReport): string[] {\n\tif (!report.configured) {\n\t\treturn [\n\t\t\t\"AdaptOrch: not configured\",\n\t\t\t\" Set ADAPTORCH_API_KEY to enable it. Optionally set ADAPTORCH_API_URL.\",\n\t\t\t` Create an account: ${getAdaptOrchLinks(\"doctor\").signup}`,\n\t\t\t\" Plans and contact (offline): omk doctor adaptorch --links\",\n\t\t\t\" AdaptOrch is a separate product; OMK does not require it.\",\n\t\t];\n\t}\n\tif (!report.reachable) {\n\t\tconst detail =\n\t\t\treport.status === undefined ? \"\" : ` (HTTP ${report.status}${report.code ? ` ${report.code}` : \"\"})`;\n\t\treturn [`AdaptOrch: unreachable${detail}`, ` ${report.error ?? \"the request did not complete\"}`];\n\t}\n\tconst scope = report.projectId ? `, project ${report.projectId}` : \"\";\n\treturn [`AdaptOrch: verified`, ` Authenticated as ${report.subjectId ?? \"(unknown subject)\"}${scope}`];\n}\n\nasync function probe(client: AdaptOrchApiClient): Promise<AdaptOrchDoctorReport> {\n\ttry {\n\t\tconst principal = await client.whoami();\n\t\treturn {\n\t\t\tconfigured: true,\n\t\t\treachable: true,\n\t\t\tsubjectId: principal.subject_id,\n\t\t\t...(principal.project_id === undefined ? {} : { projectId: principal.project_id }),\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof AdaptOrchApiError) {\n\t\t\treturn {\n\t\t\t\tconfigured: true,\n\t\t\t\treachable: false,\n\t\t\t\tstatus: error.status,\n\t\t\t\t...(error.code === undefined ? {} : { code: error.code }),\n\t\t\t\terror: error.message,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tconfigured: true,\n\t\t\treachable: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t}\n}\n\nexport async function runAdaptOrchDoctorCli(\n\targs: readonly string[],\n\toverrides: AdaptOrchDoctorCliOverrides = {},\n): Promise<AdaptOrchDoctorCliOutcome> {\n\tif (args[0] !== \"doctor\" || args[1] !== \"adaptorch\") {\n\t\treturn { handled: false, exitCode: 0 };\n\t}\n\tconst writeLine = overrides.writeLine ?? ((line: string) => console.log(line));\n\n\tlet json = false;\n\tlet links = false;\n\tfor (const arg of args.slice(2)) {\n\t\tif (arg === \"--links\") {\n\t\t\tlinks = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--json\") {\n\t\t\tjson = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\twriteLine(USAGE);\n\t\t\treturn { handled: true, exitCode: 0 };\n\t\t}\n\t\twriteLine(`Unknown option: ${arg}`);\n\t\twriteLine(USAGE);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\n\tif (links) {\n\t\tconst report = {\n\t\t\tmode: \"links\",\n\t\t\tnetworkAccess: false,\n\t\t\taccountRequired: false,\n\t\t\tlinks: getAdaptOrchLinks(\"doctor\"),\n\t\t};\n\t\tif (json) writeLine(JSON.stringify(report, null, 2));\n\t\telse {\n\t\t\tfor (const line of [\n\t\t\t\t\"AdaptOrch — optional service, not required by OMK or WPL\",\n\t\t\t\t` Plans / local Starter: ${report.links.plans}`,\n\t\t\t\t` Sign up: ${report.links.signup}`,\n\t\t\t\t` Team / private-runner contact: ${report.links.contact}`,\n\t\t\t\t` Claim boundary: ${report.links.claimBoundary}`,\n\t\t\t\t\" Next: configure ADAPTORCH_API_KEY, then run omk doctor adaptorch to check API connectivity.\",\n\t\t\t\t\" Offline links only: no account created, data sent, browser opened, or verification run submitted.\",\n\t\t\t])\n\t\t\t\twriteLine(line);\n\t\t}\n\t\treturn { handled: true, exitCode: 0 };\n\t}\n\n\tconst env = overrides.env ?? process.env;\n\tconst fetchImpl = overrides.fetch ?? (globalThis.fetch as unknown as AdaptOrchFetch);\n\n\tlet report: AdaptOrchDoctorReport;\n\ttry {\n\t\tconst client = createAdaptOrchApiClientFromEnv(fetchImpl, env);\n\t\treport = client ? await probe(client) : { configured: false, reachable: false };\n\t} catch (error) {\n\t\t// A configured but invalid setup (an unsafe ADAPTORCH_API_URL, for\n\t\t// example) is a broken setup, not an absent one.\n\t\treport = {\n\t\t\tconfigured: true,\n\t\t\treachable: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t}\n\n\tif (json) writeLine(JSON.stringify(report, null, 2));\n\telse for (const line of describe(report)) writeLine(line);\n\n\tif (!report.configured) return { handled: true, exitCode: 1 };\n\treturn { handled: true, exitCode: report.reachable ? 0 : 2 };\n}\n"]}
@@ -0,0 +1,12 @@
1
+ type InitOptions = {
2
+ readonly agentDir?: string;
3
+ readonly templatesDir?: string;
4
+ readonly writeLine?: (line: string) => void;
5
+ };
6
+ /** Explicit, offline initialization. Existing context entry points are never replaced or shadowed. */
7
+ export declare function runInitCli(args: readonly string[], options?: InitOptions): {
8
+ readonly handled: boolean;
9
+ readonly exitCode: number;
10
+ };
11
+ export {};
12
+ //# sourceMappingURL=init-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-cli.d.ts","sourceRoot":"","sources":["../../src/commands/init-cli.ts"],"names":[],"mappings":"AAQA,KAAK,WAAW,GAAG;IAClB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C,CAAC;AAEF,sGAAsG;AACtG,wBAAgB,UAAU,CACzB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,WAAgB,GACvB;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAmE1D","sourcesContent":["import { lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { getAgentDir, getExamplesPath } from \"../config.ts\";\n\nconst DOCUMENTS = [\"AGENTS.md\", \"INTERNET.md\", \"CLAUDE.md\"] as const;\nconst USAGE = \"Usage: omk init --global [--dry-run] [--offline]\";\nconst FLAGS = new Set([\"--global\", \"--dry-run\", \"--offline\", \"--help\", \"-h\"]);\n\ntype InitOptions = {\n\treadonly agentDir?: string;\n\treadonly templatesDir?: string;\n\treadonly writeLine?: (line: string) => void;\n};\n\n/** Explicit, offline initialization. Existing context entry points are never replaced or shadowed. */\nexport function runInitCli(\n\targs: readonly string[],\n\toptions: InitOptions = {},\n): { readonly handled: boolean; readonly exitCode: number } {\n\tif (args[0] !== \"init\") return { handled: false, exitCode: 0 };\n\tconst writeLine = options.writeLine ?? ((line: string) => process.stdout.write(`${line}\\n`));\n\tconst flags = args.slice(1);\n\tif (flags.some((flag) => !FLAGS.has(flag))) {\n\t\twriteLine(`Unsupported init argument. ${USAGE}`);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\tif (flags.includes(\"--help\") || flags.includes(\"-h\")) {\n\t\twriteLine(`${USAGE}\\nCreate portable context documents only when missing. Existing instructions are preserved.`);\n\t\treturn { handled: true, exitCode: 0 };\n\t}\n\tif (!flags.includes(\"--global\")) {\n\t\twriteLine(USAGE);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\n\ttry {\n\t\tconst agentDir = resolve(options.agentDir ?? getAgentDir());\n\t\tconst directory = lstatSync(agentDir, { throwIfNoEntry: false });\n\t\tif (directory && !directory.isDirectory()) {\n\t\t\twriteLine(\"Cannot initialize context: the agent directory must be a real directory, not a file or symlink.\");\n\t\t\treturn { handled: true, exitCode: 1 };\n\t\t}\n\t\tconst existing = directory ? readdirSync(agentDir) : [];\n\t\tconst hasEntryPoint = existing.some((name) => /^(?:agents|claude)\\.md$/i.test(name));\n\t\tconst templatesDir = options.templatesDir ?? join(getExamplesPath(), \"context\");\n\t\tconst plan = DOCUMENTS.map((name) => {\n\t\t\tconst preserved =\n\t\t\t\texisting.some((entry) => entry.toLowerCase() === name.toLowerCase()) ||\n\t\t\t\t(hasEntryPoint && name !== \"INTERNET.md\");\n\t\t\treturn {\n\t\t\t\tpath: join(agentDir, name),\n\t\t\t\t// Read all required templates before creating anything, including in dry-run mode.\n\t\t\t\tcontent: preserved ? undefined : readFileSync(join(templatesDir, name), \"utf8\"),\n\t\t\t};\n\t\t});\n\t\tconst dryRun = flags.includes(\"--dry-run\");\n\t\tfor (const document of plan) {\n\t\t\tif (document.content === undefined) {\n\t\t\t\twriteLine(`Preserved context: ${JSON.stringify(document.path)} (existing file or entry point)`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (dryRun) {\n\t\t\t\twriteLine(`Would create: ${JSON.stringify(document.path)}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmkdirSync(agentDir, { recursive: true, mode: 0o700 });\n\t\t\ttry {\n\t\t\t\twriteFileSync(document.path, document.content, { flag: \"wx\", mode: 0o600 });\n\t\t\t\twriteLine(`Created: ${JSON.stringify(document.path)}`);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof Error) || !(\"code\" in error) || error.code !== \"EEXIST\") throw error;\n\t\t\t\twriteLine(`Preserved concurrent file: ${JSON.stringify(document.path)}`);\n\t\t\t}\n\t\t}\n\t\twriteLine(\n\t\t\tdryRun\n\t\t\t\t? \"Dry run: no files written.\"\n\t\t\t\t: \"Context setup complete. Existing files were not changed. Restart OMK or run /reload to reload context.\",\n\t\t);\n\t\treturn { handled: true, exitCode: 0 };\n\t} catch (error) {\n\t\tconst code = error instanceof Error && \"code\" in error && typeof error.code === \"string\" ? error.code : \"unknown\";\n\t\twriteLine(`Context setup failed (${code}). Check the agent directory and bundled examples/context files.`);\n\t\treturn { handled: true, exitCode: 1 };\n\t}\n}\n"]}
@@ -0,0 +1,76 @@
1
+ import { lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { getAgentDir, getExamplesPath } from "../config.js";
4
+ const DOCUMENTS = ["AGENTS.md", "INTERNET.md", "CLAUDE.md"];
5
+ const USAGE = "Usage: omk init --global [--dry-run] [--offline]";
6
+ const FLAGS = new Set(["--global", "--dry-run", "--offline", "--help", "-h"]);
7
+ /** Explicit, offline initialization. Existing context entry points are never replaced or shadowed. */
8
+ export function runInitCli(args, options = {}) {
9
+ if (args[0] !== "init")
10
+ return { handled: false, exitCode: 0 };
11
+ const writeLine = options.writeLine ?? ((line) => process.stdout.write(`${line}\n`));
12
+ const flags = args.slice(1);
13
+ if (flags.some((flag) => !FLAGS.has(flag))) {
14
+ writeLine(`Unsupported init argument. ${USAGE}`);
15
+ return { handled: true, exitCode: 2 };
16
+ }
17
+ if (flags.includes("--help") || flags.includes("-h")) {
18
+ writeLine(`${USAGE}\nCreate portable context documents only when missing. Existing instructions are preserved.`);
19
+ return { handled: true, exitCode: 0 };
20
+ }
21
+ if (!flags.includes("--global")) {
22
+ writeLine(USAGE);
23
+ return { handled: true, exitCode: 2 };
24
+ }
25
+ try {
26
+ const agentDir = resolve(options.agentDir ?? getAgentDir());
27
+ const directory = lstatSync(agentDir, { throwIfNoEntry: false });
28
+ if (directory && !directory.isDirectory()) {
29
+ writeLine("Cannot initialize context: the agent directory must be a real directory, not a file or symlink.");
30
+ return { handled: true, exitCode: 1 };
31
+ }
32
+ const existing = directory ? readdirSync(agentDir) : [];
33
+ const hasEntryPoint = existing.some((name) => /^(?:agents|claude)\.md$/i.test(name));
34
+ const templatesDir = options.templatesDir ?? join(getExamplesPath(), "context");
35
+ const plan = DOCUMENTS.map((name) => {
36
+ const preserved = existing.some((entry) => entry.toLowerCase() === name.toLowerCase()) ||
37
+ (hasEntryPoint && name !== "INTERNET.md");
38
+ return {
39
+ path: join(agentDir, name),
40
+ // Read all required templates before creating anything, including in dry-run mode.
41
+ content: preserved ? undefined : readFileSync(join(templatesDir, name), "utf8"),
42
+ };
43
+ });
44
+ const dryRun = flags.includes("--dry-run");
45
+ for (const document of plan) {
46
+ if (document.content === undefined) {
47
+ writeLine(`Preserved context: ${JSON.stringify(document.path)} (existing file or entry point)`);
48
+ continue;
49
+ }
50
+ if (dryRun) {
51
+ writeLine(`Would create: ${JSON.stringify(document.path)}`);
52
+ continue;
53
+ }
54
+ mkdirSync(agentDir, { recursive: true, mode: 0o700 });
55
+ try {
56
+ writeFileSync(document.path, document.content, { flag: "wx", mode: 0o600 });
57
+ writeLine(`Created: ${JSON.stringify(document.path)}`);
58
+ }
59
+ catch (error) {
60
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST")
61
+ throw error;
62
+ writeLine(`Preserved concurrent file: ${JSON.stringify(document.path)}`);
63
+ }
64
+ }
65
+ writeLine(dryRun
66
+ ? "Dry run: no files written."
67
+ : "Context setup complete. Existing files were not changed. Restart OMK or run /reload to reload context.");
68
+ return { handled: true, exitCode: 0 };
69
+ }
70
+ catch (error) {
71
+ const code = error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : "unknown";
72
+ writeLine(`Context setup failed (${code}). Check the agent directory and bundled examples/context files.`);
73
+ return { handled: true, exitCode: 1 };
74
+ }
75
+ }
76
+ //# sourceMappingURL=init-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-cli.js","sourceRoot":"","sources":["../../src/commands/init-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { getAgentDir, getExamplesPath } from \"../config.ts\";\n\nconst DOCUMENTS = [\"AGENTS.md\", \"INTERNET.md\", \"CLAUDE.md\"] as const;\nconst USAGE = \"Usage: omk init --global [--dry-run] [--offline]\";\nconst FLAGS = new Set([\"--global\", \"--dry-run\", \"--offline\", \"--help\", \"-h\"]);\n\ntype InitOptions = {\n\treadonly agentDir?: string;\n\treadonly templatesDir?: string;\n\treadonly writeLine?: (line: string) => void;\n};\n\n/** Explicit, offline initialization. Existing context entry points are never replaced or shadowed. */\nexport function runInitCli(\n\targs: readonly string[],\n\toptions: InitOptions = {},\n): { readonly handled: boolean; readonly exitCode: number } {\n\tif (args[0] !== \"init\") return { handled: false, exitCode: 0 };\n\tconst writeLine = options.writeLine ?? ((line: string) => process.stdout.write(`${line}\\n`));\n\tconst flags = args.slice(1);\n\tif (flags.some((flag) => !FLAGS.has(flag))) {\n\t\twriteLine(`Unsupported init argument. ${USAGE}`);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\tif (flags.includes(\"--help\") || flags.includes(\"-h\")) {\n\t\twriteLine(`${USAGE}\\nCreate portable context documents only when missing. Existing instructions are preserved.`);\n\t\treturn { handled: true, exitCode: 0 };\n\t}\n\tif (!flags.includes(\"--global\")) {\n\t\twriteLine(USAGE);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\n\ttry {\n\t\tconst agentDir = resolve(options.agentDir ?? getAgentDir());\n\t\tconst directory = lstatSync(agentDir, { throwIfNoEntry: false });\n\t\tif (directory && !directory.isDirectory()) {\n\t\t\twriteLine(\"Cannot initialize context: the agent directory must be a real directory, not a file or symlink.\");\n\t\t\treturn { handled: true, exitCode: 1 };\n\t\t}\n\t\tconst existing = directory ? readdirSync(agentDir) : [];\n\t\tconst hasEntryPoint = existing.some((name) => /^(?:agents|claude)\\.md$/i.test(name));\n\t\tconst templatesDir = options.templatesDir ?? join(getExamplesPath(), \"context\");\n\t\tconst plan = DOCUMENTS.map((name) => {\n\t\t\tconst preserved =\n\t\t\t\texisting.some((entry) => entry.toLowerCase() === name.toLowerCase()) ||\n\t\t\t\t(hasEntryPoint && name !== \"INTERNET.md\");\n\t\t\treturn {\n\t\t\t\tpath: join(agentDir, name),\n\t\t\t\t// Read all required templates before creating anything, including in dry-run mode.\n\t\t\t\tcontent: preserved ? undefined : readFileSync(join(templatesDir, name), \"utf8\"),\n\t\t\t};\n\t\t});\n\t\tconst dryRun = flags.includes(\"--dry-run\");\n\t\tfor (const document of plan) {\n\t\t\tif (document.content === undefined) {\n\t\t\t\twriteLine(`Preserved context: ${JSON.stringify(document.path)} (existing file or entry point)`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (dryRun) {\n\t\t\t\twriteLine(`Would create: ${JSON.stringify(document.path)}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmkdirSync(agentDir, { recursive: true, mode: 0o700 });\n\t\t\ttry {\n\t\t\t\twriteFileSync(document.path, document.content, { flag: \"wx\", mode: 0o600 });\n\t\t\t\twriteLine(`Created: ${JSON.stringify(document.path)}`);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof Error) || !(\"code\" in error) || error.code !== \"EEXIST\") throw error;\n\t\t\t\twriteLine(`Preserved concurrent file: ${JSON.stringify(document.path)}`);\n\t\t\t}\n\t\t}\n\t\twriteLine(\n\t\t\tdryRun\n\t\t\t\t? \"Dry run: no files written.\"\n\t\t\t\t: \"Context setup complete. Existing files were not changed. Restart OMK or run /reload to reload context.\",\n\t\t);\n\t\treturn { handled: true, exitCode: 0 };\n\t} catch (error) {\n\t\tconst code = error instanceof Error && \"code\" in error && typeof error.code === \"string\" ? error.code : \"unknown\";\n\t\twriteLine(`Context setup failed (${code}). Check the agent directory and bundled examples/context files.`);\n\t\treturn { handled: true, exitCode: 1 };\n\t}\n}\n"]}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `omk provider sync <provider-id>`: refresh a codex-chatgpt-web provider's models.json rows from
3
+ * the launcher's live catalog.
4
+ *
5
+ * The bridge's `/v1/models` is forwarded to the Codex backend, so the request carries OMK's own
6
+ * Codex OAuth and a `client_version`; the placeholder bearer in models.json cannot authenticate
7
+ * there. Prints a change report (or one JSON document with `--json`) and exits 0 = synced or
8
+ * already current, 1 = sync failed, 2 = usage error. Usage errors never echo argument values.
9
+ */
10
+ import { type BridgeSyncIo } from "../core/codex-chatgpt-web-sync.ts";
11
+ export interface ProviderSyncCliDependencies {
12
+ readonly agentDir?: string;
13
+ readonly env?: Readonly<Record<string, string | undefined>>;
14
+ readonly readFile?: BridgeSyncIo["readFile"];
15
+ readonly writeFile?: BridgeSyncIo["writeFile"];
16
+ readonly fetch?: BridgeSyncIo["fetch"];
17
+ readonly getCodexAccessToken?: BridgeSyncIo["getCodexAccessToken"];
18
+ readonly detectCodexVersion?: () => string | undefined;
19
+ readonly now?: BridgeSyncIo["now"];
20
+ readonly writeLine?: (line: string) => void;
21
+ }
22
+ export interface ProviderSyncCliOutcome {
23
+ readonly handled: boolean;
24
+ readonly exitCode: number;
25
+ }
26
+ export declare function runProviderSyncCli(args: readonly string[], overrides?: ProviderSyncCliDependencies): Promise<ProviderSyncCliOutcome>;
27
+ //# sourceMappingURL=provider-sync-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-sync-cli.d.ts","sourceRoot":"","sources":["../../src/commands/provider-sync-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,OAAO,EAEN,KAAK,YAAY,EAIjB,MAAM,mCAAmC,CAAC;AAqB3C,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,YAAY,CAAC,qBAAqB,CAAC,CAAC;IACnE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AA6GD,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,SAAS,GAAE,2BAAgC,GACzC,OAAO,CAAC,sBAAsB,CAAC,CA2CjC","sourcesContent":["/**\n * `omk provider sync <provider-id>`: refresh a codex-chatgpt-web provider's models.json rows from\n * the launcher's live catalog.\n *\n * The bridge's `/v1/models` is forwarded to the Codex backend, so the request carries OMK's own\n * Codex OAuth and a `client_version`; the placeholder bearer in models.json cannot authenticate\n * there. Prints a change report (or one JSON document with `--json`) and exits 0 = synced or\n * already current, 1 = sync failed, 2 = usage error. Usage errors never echo argument values.\n */\n\nimport { existsSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { APP_NAME, getAgentDir } from \"../config.ts\";\nimport { AuthStorage } from \"../core/auth-storage.ts\";\nimport {\n\ttype BridgeSyncPlan,\n\tCODEX_CHATGPT_WEB_FALLBACK_CLIENT_VERSION,\n\tCODEX_CHATGPT_WEB_MODEL_PREFIX,\n} from \"../core/codex-chatgpt-web-bridge.ts\";\nimport {\n\tBridgeSyncFailure,\n\ttype BridgeSyncIo,\n\ttype BridgeSyncReport,\n\thasBridgeSyncChanges,\n\tsyncCodexChatGptWebProvider,\n} from \"../core/codex-chatgpt-web-sync.ts\";\nimport { spawnProcessSync } from \"../utils/child-process.ts\";\n\nconst USAGE = `Usage: ${APP_NAME} provider sync <provider-id> [--dry-run] [--json] [--timeout <ms>] [--client-version <x.y.z>]`;\nconst HELP = [\n\t\"Provider sync: rewrite a codex-chatgpt-web provider's models.json rows from the launcher's live catalog.\",\n\t\"\",\n\tUSAGE,\n\t\"\",\n\t\" --dry-run report the changes without writing models.json\",\n\t\" --json print one JSON document instead of the text report\",\n\t\" --timeout <ms> network timeout per request (default 15000)\",\n\t\" --client-version <x.y.z> Codex client version sent to the catalog (default: OMK_CODEX_CLIENT_VERSION,\",\n\t\" then `codex --version`, then the version OMK last verified)\",\n\t\"\",\n\t\"The bridge forwards /v1/models to the Codex backend with OMK's openai-codex OAuth (/login openai-codex).\",\n\t\"Exit codes: 0 = synced or already current, 1 = sync failed, 2 = usage error.\",\n].join(\"\\n\");\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst CODEX_VERSION_PROBE_TIMEOUT_MS = 5_000;\n\nexport interface ProviderSyncCliDependencies {\n\treadonly agentDir?: string;\n\treadonly env?: Readonly<Record<string, string | undefined>>;\n\treadonly readFile?: BridgeSyncIo[\"readFile\"];\n\treadonly writeFile?: BridgeSyncIo[\"writeFile\"];\n\treadonly fetch?: BridgeSyncIo[\"fetch\"];\n\treadonly getCodexAccessToken?: BridgeSyncIo[\"getCodexAccessToken\"];\n\treadonly detectCodexVersion?: () => string | undefined;\n\treadonly now?: BridgeSyncIo[\"now\"];\n\treadonly writeLine?: (line: string) => void;\n}\n\nexport interface ProviderSyncCliOutcome {\n\treadonly handled: boolean;\n\treadonly exitCode: number;\n}\n\ninterface ParsedSyncArgs {\n\treadonly providerId: string;\n\treadonly dryRun: boolean;\n\treadonly json: boolean;\n\treadonly timeoutMs: number;\n\treadonly clientVersion: string | undefined;\n}\n\ntype ParseOutcome =\n\t| { readonly kind: \"absent\" }\n\t| { readonly kind: \"help\" }\n\t| { readonly kind: \"error\"; readonly message: string }\n\t| { readonly kind: \"ok\"; readonly parsed: ParsedSyncArgs };\n\nfunction parseOption(arg: string, value: string | undefined): { kind: \"error\"; message: string } | undefined {\n\tif (value === undefined || value.startsWith(\"-\")) return { kind: \"error\", message: `Missing value for ${arg}.` };\n\tif (arg === \"--timeout\" && !/^[1-9]\\d*$/.test(value)) {\n\t\treturn { kind: \"error\", message: \"--timeout must be a positive integer of milliseconds.\" };\n\t}\n\treturn undefined;\n}\n\nfunction parseArgs(args: readonly string[]): ParseOutcome {\n\tif (args[0] !== \"provider\" || args[1] !== \"sync\") return { kind: \"absent\" };\n\tlet providerId: string | undefined;\n\tlet dryRun = false;\n\tlet json = false;\n\tlet timeoutMs = DEFAULT_TIMEOUT_MS;\n\tlet clientVersion: string | undefined;\n\tfor (let index = 2; index < args.length; index += 1) {\n\t\tconst arg = args[index] ?? \"\";\n\t\tif (arg === \"--help\" || arg === \"-h\") return { kind: \"help\" };\n\t\tif (arg === \"--dry-run\") dryRun = true;\n\t\telse if (arg === \"--json\") json = true;\n\t\telse if (arg === \"--timeout\" || arg === \"--client-version\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tconst invalid = parseOption(arg, value);\n\t\t\tif (invalid) return invalid;\n\t\t\tif (arg === \"--timeout\") timeoutMs = Number(value);\n\t\t\telse clientVersion = value;\n\t\t\tindex += 1;\n\t\t} else if (arg.startsWith(\"-\")) return { kind: \"error\", message: \"Unknown option for provider sync.\" };\n\t\telse if (providerId === undefined) providerId = arg;\n\t\telse return { kind: \"error\", message: \"Unexpected extra argument.\" };\n\t}\n\tif (providerId === undefined) return { kind: \"error\", message: \"Missing provider id.\" };\n\treturn { kind: \"ok\", parsed: { providerId, dryRun, json, timeoutMs, clientVersion } };\n}\n\nfunction detectCodexVersion(): string | undefined {\n\tconst result = spawnProcessSync(\"codex\", [\"--version\"], {\n\t\tencoding: \"utf8\",\n\t\tstdio: \"pipe\",\n\t\tshell: false,\n\t\twindowsHide: true,\n\t\ttimeout: CODEX_VERSION_PROBE_TIMEOUT_MS,\n\t});\n\tif (result.error !== undefined || result.status !== 0) return undefined;\n\treturn /\\d+\\.\\d+\\.\\d+/.exec(result.stdout)?.[0];\n}\n\nfunction writeFileAtomically(path: string, text: string): void {\n\tconst staging = `${path}.${process.pid}.tmp`;\n\twriteFileSync(staging, text, \"utf8\");\n\trenameSync(staging, path);\n}\n\nfunction planLines(plan: BridgeSyncPlan): readonly string[] {\n\treturn [\n\t\t...plan.changes.map(\n\t\t\t(change) => ` ~ ${change.id} ${change.field} ${JSON.stringify(change.from)} -> ${JSON.stringify(change.to)}`,\n\t\t),\n\t\t...plan.added.map((id) => ` + ${id} (added)`),\n\t\t...plan.removed.map((id) => ` - ${id} (removed: the bridge no longer serves it)`),\n\t];\n}\n\nfunction printReport(parsed: ParsedSyncArgs, report: BridgeSyncReport, writeLine: (line: string) => void): void {\n\tconst { modelsPath, baseUrl, health, clientVersion, plan, bridgeCatalog, written } = report;\n\tif (parsed.json) {\n\t\tconst { models: _models, ...delta } = plan;\n\t\tconst bridge = { ...health, baseUrl };\n\t\tconst document = {\n\t\t\tprovider: parsed.providerId,\n\t\t\tbridge,\n\t\t\tclientVersion,\n\t\t\tbridgeCatalog,\n\t\t\t...delta,\n\t\t\twritten,\n\t\t\tmodelsPath,\n\t\t};\n\t\twriteLine(JSON.stringify(document, null, 2));\n\t\treturn;\n\t}\n\tconst turns = health.acceptingTurns ? \"accepting turns\" : \"draining\";\n\tconst served = plan.models.filter((model) => model.id.startsWith(CODEX_CHATGPT_WEB_MODEL_PREFIX)).length;\n\tconst ceilings = Object.entries(bridgeCatalog.contextCeilings)\n\t\t.map(([id, ceiling]) => `${id.slice(CODEX_CHATGPT_WEB_MODEL_PREFIX.length)}=${ceiling}`)\n\t\t.join(\" \");\n\twriteLine(`codex-chatgpt-web bridge ${health.version} (${health.mode} mode, ${turns}) at ${baseUrl}`);\n\twriteLine(`catalog: ${served} chatgpt-web/* models (client_version ${clientVersion})`);\n\twriteLine(`contextWindow follows the bridge's auto_compact_token_limit; rejection ceilings: ${ceilings}`);\n\tfor (const line of planLines(plan)) writeLine(line);\n\tif (!hasBridgeSyncChanges(plan) && !written) writeLine(`${modelsPath} already matches the bridge.`);\n\telse writeLine(written ? `wrote ${modelsPath}` : `dry run: ${modelsPath} not written`);\n}\n\nexport async function runProviderSyncCli(\n\targs: readonly string[],\n\toverrides: ProviderSyncCliDependencies = {},\n): Promise<ProviderSyncCliOutcome> {\n\tconst outcome = parseArgs(args);\n\tif (outcome.kind === \"absent\") return { handled: false, exitCode: 0 };\n\tconst agentDir = overrides.agentDir ?? getAgentDir();\n\tconst env = overrides.env ?? process.env;\n\tconst writeLine = overrides.writeLine ?? ((line: string) => process.stdout.write(`${line}\\n`));\n\tif (outcome.kind === \"help\") {\n\t\twriteLine(HELP);\n\t\treturn { handled: true, exitCode: 0 };\n\t}\n\tif (outcome.kind === \"error\") {\n\t\twriteLine(`${outcome.message}\\n${USAGE}`);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\tconst io: BridgeSyncIo = {\n\t\treadFile: overrides.readFile ?? ((path) => (existsSync(path) ? readFileSync(path, \"utf8\") : \"\")),\n\t\twriteFile: overrides.writeFile ?? writeFileAtomically,\n\t\tfetch: overrides.fetch ?? ((url, init) => fetch(url, init)),\n\t\tgetCodexAccessToken:\n\t\t\toverrides.getCodexAccessToken ??\n\t\t\t(() => AuthStorage.create(join(agentDir, \"auth.json\")).getApiKey(\"openai-codex\")),\n\t\tnow: overrides.now ?? (() => new Date().toISOString()),\n\t};\n\tconst { parsed } = outcome;\n\tconst clientVersion =\n\t\tparsed.clientVersion ??\n\t\tenv.OMK_CODEX_CLIENT_VERSION ??\n\t\t(overrides.detectCodexVersion ?? detectCodexVersion)() ??\n\t\tCODEX_CHATGPT_WEB_FALLBACK_CLIENT_VERSION;\n\ttry {\n\t\tconst report = await syncCodexChatGptWebProvider(\n\t\t\t{ ...parsed, modelsPath: join(agentDir, \"models.json\"), clientVersion },\n\t\t\tio,\n\t\t);\n\t\tprintReport(parsed, report, writeLine);\n\t\treturn { handled: true, exitCode: 0 };\n\t} catch (error) {\n\t\tif (error instanceof BridgeSyncFailure) {\n\t\t\twriteLine(error.message);\n\t\t\treturn { handled: true, exitCode: 1 };\n\t\t}\n\t\tthrow error;\n\t}\n}\n"]}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * `omk provider sync <provider-id>`: refresh a codex-chatgpt-web provider's models.json rows from
3
+ * the launcher's live catalog.
4
+ *
5
+ * The bridge's `/v1/models` is forwarded to the Codex backend, so the request carries OMK's own
6
+ * Codex OAuth and a `client_version`; the placeholder bearer in models.json cannot authenticate
7
+ * there. Prints a change report (or one JSON document with `--json`) and exits 0 = synced or
8
+ * already current, 1 = sync failed, 2 = usage error. Usage errors never echo argument values.
9
+ */
10
+ import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { APP_NAME, getAgentDir } from "../config.js";
13
+ import { AuthStorage } from "../core/auth-storage.js";
14
+ import { CODEX_CHATGPT_WEB_FALLBACK_CLIENT_VERSION, CODEX_CHATGPT_WEB_MODEL_PREFIX, } from "../core/codex-chatgpt-web-bridge.js";
15
+ import { BridgeSyncFailure, hasBridgeSyncChanges, syncCodexChatGptWebProvider, } from "../core/codex-chatgpt-web-sync.js";
16
+ import { spawnProcessSync } from "../utils/child-process.js";
17
+ const USAGE = `Usage: ${APP_NAME} provider sync <provider-id> [--dry-run] [--json] [--timeout <ms>] [--client-version <x.y.z>]`;
18
+ const HELP = [
19
+ "Provider sync: rewrite a codex-chatgpt-web provider's models.json rows from the launcher's live catalog.",
20
+ "",
21
+ USAGE,
22
+ "",
23
+ " --dry-run report the changes without writing models.json",
24
+ " --json print one JSON document instead of the text report",
25
+ " --timeout <ms> network timeout per request (default 15000)",
26
+ " --client-version <x.y.z> Codex client version sent to the catalog (default: OMK_CODEX_CLIENT_VERSION,",
27
+ " then `codex --version`, then the version OMK last verified)",
28
+ "",
29
+ "The bridge forwards /v1/models to the Codex backend with OMK's openai-codex OAuth (/login openai-codex).",
30
+ "Exit codes: 0 = synced or already current, 1 = sync failed, 2 = usage error.",
31
+ ].join("\n");
32
+ const DEFAULT_TIMEOUT_MS = 15_000;
33
+ const CODEX_VERSION_PROBE_TIMEOUT_MS = 5_000;
34
+ function parseOption(arg, value) {
35
+ if (value === undefined || value.startsWith("-"))
36
+ return { kind: "error", message: `Missing value for ${arg}.` };
37
+ if (arg === "--timeout" && !/^[1-9]\d*$/.test(value)) {
38
+ return { kind: "error", message: "--timeout must be a positive integer of milliseconds." };
39
+ }
40
+ return undefined;
41
+ }
42
+ function parseArgs(args) {
43
+ if (args[0] !== "provider" || args[1] !== "sync")
44
+ return { kind: "absent" };
45
+ let providerId;
46
+ let dryRun = false;
47
+ let json = false;
48
+ let timeoutMs = DEFAULT_TIMEOUT_MS;
49
+ let clientVersion;
50
+ for (let index = 2; index < args.length; index += 1) {
51
+ const arg = args[index] ?? "";
52
+ if (arg === "--help" || arg === "-h")
53
+ return { kind: "help" };
54
+ if (arg === "--dry-run")
55
+ dryRun = true;
56
+ else if (arg === "--json")
57
+ json = true;
58
+ else if (arg === "--timeout" || arg === "--client-version") {
59
+ const value = args[index + 1];
60
+ const invalid = parseOption(arg, value);
61
+ if (invalid)
62
+ return invalid;
63
+ if (arg === "--timeout")
64
+ timeoutMs = Number(value);
65
+ else
66
+ clientVersion = value;
67
+ index += 1;
68
+ }
69
+ else if (arg.startsWith("-"))
70
+ return { kind: "error", message: "Unknown option for provider sync." };
71
+ else if (providerId === undefined)
72
+ providerId = arg;
73
+ else
74
+ return { kind: "error", message: "Unexpected extra argument." };
75
+ }
76
+ if (providerId === undefined)
77
+ return { kind: "error", message: "Missing provider id." };
78
+ return { kind: "ok", parsed: { providerId, dryRun, json, timeoutMs, clientVersion } };
79
+ }
80
+ function detectCodexVersion() {
81
+ const result = spawnProcessSync("codex", ["--version"], {
82
+ encoding: "utf8",
83
+ stdio: "pipe",
84
+ shell: false,
85
+ windowsHide: true,
86
+ timeout: CODEX_VERSION_PROBE_TIMEOUT_MS,
87
+ });
88
+ if (result.error !== undefined || result.status !== 0)
89
+ return undefined;
90
+ return /\d+\.\d+\.\d+/.exec(result.stdout)?.[0];
91
+ }
92
+ function writeFileAtomically(path, text) {
93
+ const staging = `${path}.${process.pid}.tmp`;
94
+ writeFileSync(staging, text, "utf8");
95
+ renameSync(staging, path);
96
+ }
97
+ function planLines(plan) {
98
+ return [
99
+ ...plan.changes.map((change) => ` ~ ${change.id} ${change.field} ${JSON.stringify(change.from)} -> ${JSON.stringify(change.to)}`),
100
+ ...plan.added.map((id) => ` + ${id} (added)`),
101
+ ...plan.removed.map((id) => ` - ${id} (removed: the bridge no longer serves it)`),
102
+ ];
103
+ }
104
+ function printReport(parsed, report, writeLine) {
105
+ const { modelsPath, baseUrl, health, clientVersion, plan, bridgeCatalog, written } = report;
106
+ if (parsed.json) {
107
+ const { models: _models, ...delta } = plan;
108
+ const bridge = { ...health, baseUrl };
109
+ const document = {
110
+ provider: parsed.providerId,
111
+ bridge,
112
+ clientVersion,
113
+ bridgeCatalog,
114
+ ...delta,
115
+ written,
116
+ modelsPath,
117
+ };
118
+ writeLine(JSON.stringify(document, null, 2));
119
+ return;
120
+ }
121
+ const turns = health.acceptingTurns ? "accepting turns" : "draining";
122
+ const served = plan.models.filter((model) => model.id.startsWith(CODEX_CHATGPT_WEB_MODEL_PREFIX)).length;
123
+ const ceilings = Object.entries(bridgeCatalog.contextCeilings)
124
+ .map(([id, ceiling]) => `${id.slice(CODEX_CHATGPT_WEB_MODEL_PREFIX.length)}=${ceiling}`)
125
+ .join(" ");
126
+ writeLine(`codex-chatgpt-web bridge ${health.version} (${health.mode} mode, ${turns}) at ${baseUrl}`);
127
+ writeLine(`catalog: ${served} chatgpt-web/* models (client_version ${clientVersion})`);
128
+ writeLine(`contextWindow follows the bridge's auto_compact_token_limit; rejection ceilings: ${ceilings}`);
129
+ for (const line of planLines(plan))
130
+ writeLine(line);
131
+ if (!hasBridgeSyncChanges(plan) && !written)
132
+ writeLine(`${modelsPath} already matches the bridge.`);
133
+ else
134
+ writeLine(written ? `wrote ${modelsPath}` : `dry run: ${modelsPath} not written`);
135
+ }
136
+ export async function runProviderSyncCli(args, overrides = {}) {
137
+ const outcome = parseArgs(args);
138
+ if (outcome.kind === "absent")
139
+ return { handled: false, exitCode: 0 };
140
+ const agentDir = overrides.agentDir ?? getAgentDir();
141
+ const env = overrides.env ?? process.env;
142
+ const writeLine = overrides.writeLine ?? ((line) => process.stdout.write(`${line}\n`));
143
+ if (outcome.kind === "help") {
144
+ writeLine(HELP);
145
+ return { handled: true, exitCode: 0 };
146
+ }
147
+ if (outcome.kind === "error") {
148
+ writeLine(`${outcome.message}\n${USAGE}`);
149
+ return { handled: true, exitCode: 2 };
150
+ }
151
+ const io = {
152
+ readFile: overrides.readFile ?? ((path) => (existsSync(path) ? readFileSync(path, "utf8") : "")),
153
+ writeFile: overrides.writeFile ?? writeFileAtomically,
154
+ fetch: overrides.fetch ?? ((url, init) => fetch(url, init)),
155
+ getCodexAccessToken: overrides.getCodexAccessToken ??
156
+ (() => AuthStorage.create(join(agentDir, "auth.json")).getApiKey("openai-codex")),
157
+ now: overrides.now ?? (() => new Date().toISOString()),
158
+ };
159
+ const { parsed } = outcome;
160
+ const clientVersion = parsed.clientVersion ??
161
+ env.OMK_CODEX_CLIENT_VERSION ??
162
+ (overrides.detectCodexVersion ?? detectCodexVersion)() ??
163
+ CODEX_CHATGPT_WEB_FALLBACK_CLIENT_VERSION;
164
+ try {
165
+ const report = await syncCodexChatGptWebProvider({ ...parsed, modelsPath: join(agentDir, "models.json"), clientVersion }, io);
166
+ printReport(parsed, report, writeLine);
167
+ return { handled: true, exitCode: 0 };
168
+ }
169
+ catch (error) {
170
+ if (error instanceof BridgeSyncFailure) {
171
+ writeLine(error.message);
172
+ return { handled: true, exitCode: 1 };
173
+ }
174
+ throw error;
175
+ }
176
+ }
177
+ //# sourceMappingURL=provider-sync-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-sync-cli.js","sourceRoot":"","sources":["../../src/commands/provider-sync-cli.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `omk provider sync <provider-id>`: refresh a codex-chatgpt-web provider's models.json rows from\n * the launcher's live catalog.\n *\n * The bridge's `/v1/models` is forwarded to the Codex backend, so the request carries OMK's own\n * Codex OAuth and a `client_version`; the placeholder bearer in models.json cannot authenticate\n * there. Prints a change report (or one JSON document with `--json`) and exits 0 = synced or\n * already current, 1 = sync failed, 2 = usage error. Usage errors never echo argument values.\n */\n\nimport { existsSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { APP_NAME, getAgentDir } from \"../config.ts\";\nimport { AuthStorage } from \"../core/auth-storage.ts\";\nimport {\n\ttype BridgeSyncPlan,\n\tCODEX_CHATGPT_WEB_FALLBACK_CLIENT_VERSION,\n\tCODEX_CHATGPT_WEB_MODEL_PREFIX,\n} from \"../core/codex-chatgpt-web-bridge.ts\";\nimport {\n\tBridgeSyncFailure,\n\ttype BridgeSyncIo,\n\ttype BridgeSyncReport,\n\thasBridgeSyncChanges,\n\tsyncCodexChatGptWebProvider,\n} from \"../core/codex-chatgpt-web-sync.ts\";\nimport { spawnProcessSync } from \"../utils/child-process.ts\";\n\nconst USAGE = `Usage: ${APP_NAME} provider sync <provider-id> [--dry-run] [--json] [--timeout <ms>] [--client-version <x.y.z>]`;\nconst HELP = [\n\t\"Provider sync: rewrite a codex-chatgpt-web provider's models.json rows from the launcher's live catalog.\",\n\t\"\",\n\tUSAGE,\n\t\"\",\n\t\" --dry-run report the changes without writing models.json\",\n\t\" --json print one JSON document instead of the text report\",\n\t\" --timeout <ms> network timeout per request (default 15000)\",\n\t\" --client-version <x.y.z> Codex client version sent to the catalog (default: OMK_CODEX_CLIENT_VERSION,\",\n\t\" then `codex --version`, then the version OMK last verified)\",\n\t\"\",\n\t\"The bridge forwards /v1/models to the Codex backend with OMK's openai-codex OAuth (/login openai-codex).\",\n\t\"Exit codes: 0 = synced or already current, 1 = sync failed, 2 = usage error.\",\n].join(\"\\n\");\nconst DEFAULT_TIMEOUT_MS = 15_000;\nconst CODEX_VERSION_PROBE_TIMEOUT_MS = 5_000;\n\nexport interface ProviderSyncCliDependencies {\n\treadonly agentDir?: string;\n\treadonly env?: Readonly<Record<string, string | undefined>>;\n\treadonly readFile?: BridgeSyncIo[\"readFile\"];\n\treadonly writeFile?: BridgeSyncIo[\"writeFile\"];\n\treadonly fetch?: BridgeSyncIo[\"fetch\"];\n\treadonly getCodexAccessToken?: BridgeSyncIo[\"getCodexAccessToken\"];\n\treadonly detectCodexVersion?: () => string | undefined;\n\treadonly now?: BridgeSyncIo[\"now\"];\n\treadonly writeLine?: (line: string) => void;\n}\n\nexport interface ProviderSyncCliOutcome {\n\treadonly handled: boolean;\n\treadonly exitCode: number;\n}\n\ninterface ParsedSyncArgs {\n\treadonly providerId: string;\n\treadonly dryRun: boolean;\n\treadonly json: boolean;\n\treadonly timeoutMs: number;\n\treadonly clientVersion: string | undefined;\n}\n\ntype ParseOutcome =\n\t| { readonly kind: \"absent\" }\n\t| { readonly kind: \"help\" }\n\t| { readonly kind: \"error\"; readonly message: string }\n\t| { readonly kind: \"ok\"; readonly parsed: ParsedSyncArgs };\n\nfunction parseOption(arg: string, value: string | undefined): { kind: \"error\"; message: string } | undefined {\n\tif (value === undefined || value.startsWith(\"-\")) return { kind: \"error\", message: `Missing value for ${arg}.` };\n\tif (arg === \"--timeout\" && !/^[1-9]\\d*$/.test(value)) {\n\t\treturn { kind: \"error\", message: \"--timeout must be a positive integer of milliseconds.\" };\n\t}\n\treturn undefined;\n}\n\nfunction parseArgs(args: readonly string[]): ParseOutcome {\n\tif (args[0] !== \"provider\" || args[1] !== \"sync\") return { kind: \"absent\" };\n\tlet providerId: string | undefined;\n\tlet dryRun = false;\n\tlet json = false;\n\tlet timeoutMs = DEFAULT_TIMEOUT_MS;\n\tlet clientVersion: string | undefined;\n\tfor (let index = 2; index < args.length; index += 1) {\n\t\tconst arg = args[index] ?? \"\";\n\t\tif (arg === \"--help\" || arg === \"-h\") return { kind: \"help\" };\n\t\tif (arg === \"--dry-run\") dryRun = true;\n\t\telse if (arg === \"--json\") json = true;\n\t\telse if (arg === \"--timeout\" || arg === \"--client-version\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tconst invalid = parseOption(arg, value);\n\t\t\tif (invalid) return invalid;\n\t\t\tif (arg === \"--timeout\") timeoutMs = Number(value);\n\t\t\telse clientVersion = value;\n\t\t\tindex += 1;\n\t\t} else if (arg.startsWith(\"-\")) return { kind: \"error\", message: \"Unknown option for provider sync.\" };\n\t\telse if (providerId === undefined) providerId = arg;\n\t\telse return { kind: \"error\", message: \"Unexpected extra argument.\" };\n\t}\n\tif (providerId === undefined) return { kind: \"error\", message: \"Missing provider id.\" };\n\treturn { kind: \"ok\", parsed: { providerId, dryRun, json, timeoutMs, clientVersion } };\n}\n\nfunction detectCodexVersion(): string | undefined {\n\tconst result = spawnProcessSync(\"codex\", [\"--version\"], {\n\t\tencoding: \"utf8\",\n\t\tstdio: \"pipe\",\n\t\tshell: false,\n\t\twindowsHide: true,\n\t\ttimeout: CODEX_VERSION_PROBE_TIMEOUT_MS,\n\t});\n\tif (result.error !== undefined || result.status !== 0) return undefined;\n\treturn /\\d+\\.\\d+\\.\\d+/.exec(result.stdout)?.[0];\n}\n\nfunction writeFileAtomically(path: string, text: string): void {\n\tconst staging = `${path}.${process.pid}.tmp`;\n\twriteFileSync(staging, text, \"utf8\");\n\trenameSync(staging, path);\n}\n\nfunction planLines(plan: BridgeSyncPlan): readonly string[] {\n\treturn [\n\t\t...plan.changes.map(\n\t\t\t(change) => ` ~ ${change.id} ${change.field} ${JSON.stringify(change.from)} -> ${JSON.stringify(change.to)}`,\n\t\t),\n\t\t...plan.added.map((id) => ` + ${id} (added)`),\n\t\t...plan.removed.map((id) => ` - ${id} (removed: the bridge no longer serves it)`),\n\t];\n}\n\nfunction printReport(parsed: ParsedSyncArgs, report: BridgeSyncReport, writeLine: (line: string) => void): void {\n\tconst { modelsPath, baseUrl, health, clientVersion, plan, bridgeCatalog, written } = report;\n\tif (parsed.json) {\n\t\tconst { models: _models, ...delta } = plan;\n\t\tconst bridge = { ...health, baseUrl };\n\t\tconst document = {\n\t\t\tprovider: parsed.providerId,\n\t\t\tbridge,\n\t\t\tclientVersion,\n\t\t\tbridgeCatalog,\n\t\t\t...delta,\n\t\t\twritten,\n\t\t\tmodelsPath,\n\t\t};\n\t\twriteLine(JSON.stringify(document, null, 2));\n\t\treturn;\n\t}\n\tconst turns = health.acceptingTurns ? \"accepting turns\" : \"draining\";\n\tconst served = plan.models.filter((model) => model.id.startsWith(CODEX_CHATGPT_WEB_MODEL_PREFIX)).length;\n\tconst ceilings = Object.entries(bridgeCatalog.contextCeilings)\n\t\t.map(([id, ceiling]) => `${id.slice(CODEX_CHATGPT_WEB_MODEL_PREFIX.length)}=${ceiling}`)\n\t\t.join(\" \");\n\twriteLine(`codex-chatgpt-web bridge ${health.version} (${health.mode} mode, ${turns}) at ${baseUrl}`);\n\twriteLine(`catalog: ${served} chatgpt-web/* models (client_version ${clientVersion})`);\n\twriteLine(`contextWindow follows the bridge's auto_compact_token_limit; rejection ceilings: ${ceilings}`);\n\tfor (const line of planLines(plan)) writeLine(line);\n\tif (!hasBridgeSyncChanges(plan) && !written) writeLine(`${modelsPath} already matches the bridge.`);\n\telse writeLine(written ? `wrote ${modelsPath}` : `dry run: ${modelsPath} not written`);\n}\n\nexport async function runProviderSyncCli(\n\targs: readonly string[],\n\toverrides: ProviderSyncCliDependencies = {},\n): Promise<ProviderSyncCliOutcome> {\n\tconst outcome = parseArgs(args);\n\tif (outcome.kind === \"absent\") return { handled: false, exitCode: 0 };\n\tconst agentDir = overrides.agentDir ?? getAgentDir();\n\tconst env = overrides.env ?? process.env;\n\tconst writeLine = overrides.writeLine ?? ((line: string) => process.stdout.write(`${line}\\n`));\n\tif (outcome.kind === \"help\") {\n\t\twriteLine(HELP);\n\t\treturn { handled: true, exitCode: 0 };\n\t}\n\tif (outcome.kind === \"error\") {\n\t\twriteLine(`${outcome.message}\\n${USAGE}`);\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\tconst io: BridgeSyncIo = {\n\t\treadFile: overrides.readFile ?? ((path) => (existsSync(path) ? readFileSync(path, \"utf8\") : \"\")),\n\t\twriteFile: overrides.writeFile ?? writeFileAtomically,\n\t\tfetch: overrides.fetch ?? ((url, init) => fetch(url, init)),\n\t\tgetCodexAccessToken:\n\t\t\toverrides.getCodexAccessToken ??\n\t\t\t(() => AuthStorage.create(join(agentDir, \"auth.json\")).getApiKey(\"openai-codex\")),\n\t\tnow: overrides.now ?? (() => new Date().toISOString()),\n\t};\n\tconst { parsed } = outcome;\n\tconst clientVersion =\n\t\tparsed.clientVersion ??\n\t\tenv.OMK_CODEX_CLIENT_VERSION ??\n\t\t(overrides.detectCodexVersion ?? detectCodexVersion)() ??\n\t\tCODEX_CHATGPT_WEB_FALLBACK_CLIENT_VERSION;\n\ttry {\n\t\tconst report = await syncCodexChatGptWebProvider(\n\t\t\t{ ...parsed, modelsPath: join(agentDir, \"models.json\"), clientVersion },\n\t\t\tio,\n\t\t);\n\t\tprintReport(parsed, report, writeLine);\n\t\treturn { handled: true, exitCode: 0 };\n\t} catch (error) {\n\t\tif (error instanceof BridgeSyncFailure) {\n\t\t\twriteLine(error.message);\n\t\t\treturn { handled: true, exitCode: 1 };\n\t\t}\n\t\tthrow error;\n\t}\n}\n"]}
@@ -0,0 +1,8 @@
1
+ type CliOutcome = {
2
+ readonly handled: boolean;
3
+ readonly exitCode: number;
4
+ };
5
+ /** Each handler owns a distinct prefix; preserve the first handled outcome. */
6
+ export declare function runCommand(args: string[]): Promise<CliOutcome>;
7
+ export {};
8
+ //# sourceMappingURL=run-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-command.d.ts","sourceRoot":"","sources":["../../src/commands/run-command.ts"],"names":[],"mappings":"AAQA,KAAK,UAAU,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAY3E,+EAA+E;AAC/E,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAMpE","sourcesContent":["import { runAdaptOrchDoctorCli } from \"./adaptorch-doctor-cli.ts\";\nimport { runDoctorProviderCli } from \"./doctor-provider-cli.ts\";\nimport { runResourceDoctorCli } from \"./resource-doctor-cli.ts\";\nimport { runRouterFeedbackCli } from \"./router-feedback-cli.ts\";\nimport { runSdkSessionCli } from \"./sdk-session-cli.ts\";\nimport { runSessionDoctorCli } from \"./session-doctor-cli.ts\";\nimport { runStatsCli } from \"./stats-cli.ts\";\n\ntype CliOutcome = { readonly handled: boolean; readonly exitCode: number };\n\nconst COMMANDS: ReadonlyArray<(args: string[]) => CliOutcome | Promise<CliOutcome>> = [\n\trunSessionDoctorCli,\n\trunDoctorProviderCli,\n\trunResourceDoctorCli,\n\trunAdaptOrchDoctorCli,\n\trunStatsCli,\n\trunSdkSessionCli,\n\trunRouterFeedbackCli,\n];\n\n/** Each handler owns a distinct prefix; preserve the first handled outcome. */\nexport async function runCommand(args: string[]): Promise<CliOutcome> {\n\tfor (const command of COMMANDS) {\n\t\tconst outcome = await command(args);\n\t\tif (outcome.handled) return outcome;\n\t}\n\treturn { handled: false, exitCode: 0 };\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { runAdaptOrchDoctorCli } from "./adaptorch-doctor-cli.js";
2
+ import { runDoctorProviderCli } from "./doctor-provider-cli.js";
3
+ import { runResourceDoctorCli } from "./resource-doctor-cli.js";
4
+ import { runRouterFeedbackCli } from "./router-feedback-cli.js";
5
+ import { runSdkSessionCli } from "./sdk-session-cli.js";
6
+ import { runSessionDoctorCli } from "./session-doctor-cli.js";
7
+ import { runStatsCli } from "./stats-cli.js";
8
+ const COMMANDS = [
9
+ runSessionDoctorCli,
10
+ runDoctorProviderCli,
11
+ runResourceDoctorCli,
12
+ runAdaptOrchDoctorCli,
13
+ runStatsCli,
14
+ runSdkSessionCli,
15
+ runRouterFeedbackCli,
16
+ ];
17
+ /** Each handler owns a distinct prefix; preserve the first handled outcome. */
18
+ export async function runCommand(args) {
19
+ for (const command of COMMANDS) {
20
+ const outcome = await command(args);
21
+ if (outcome.handled)
22
+ return outcome;
23
+ }
24
+ return { handled: false, exitCode: 0 };
25
+ }
26
+ //# sourceMappingURL=run-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../src/commands/run-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7C,MAAM,QAAQ,GAAwE;IACrF,mBAAmB;IACnB,oBAAoB;IACpB,oBAAoB;IACpB,qBAAqB;IACrB,WAAW;IACX,gBAAgB;IAChB,oBAAoB;CACpB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAc,EAAuB;IACrE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAAA,CACvC","sourcesContent":["import { runAdaptOrchDoctorCli } from \"./adaptorch-doctor-cli.ts\";\nimport { runDoctorProviderCli } from \"./doctor-provider-cli.ts\";\nimport { runResourceDoctorCli } from \"./resource-doctor-cli.ts\";\nimport { runRouterFeedbackCli } from \"./router-feedback-cli.ts\";\nimport { runSdkSessionCli } from \"./sdk-session-cli.ts\";\nimport { runSessionDoctorCli } from \"./session-doctor-cli.ts\";\nimport { runStatsCli } from \"./stats-cli.ts\";\n\ntype CliOutcome = { readonly handled: boolean; readonly exitCode: number };\n\nconst COMMANDS: ReadonlyArray<(args: string[]) => CliOutcome | Promise<CliOutcome>> = [\n\trunSessionDoctorCli,\n\trunDoctorProviderCli,\n\trunResourceDoctorCli,\n\trunAdaptOrchDoctorCli,\n\trunStatsCli,\n\trunSdkSessionCli,\n\trunRouterFeedbackCli,\n];\n\n/** Each handler owns a distinct prefix; preserve the first handled outcome. */\nexport async function runCommand(args: string[]): Promise<CliOutcome> {\n\tfor (const command of COMMANDS) {\n\t\tconst outcome = await command(args);\n\t\tif (outcome.handled) return outcome;\n\t}\n\treturn { handled: false, exitCode: 0 };\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export interface ActiveSkillState {
2
+ readonly names: readonly string[];
3
+ readonly source: string | undefined;
4
+ }
5
+ export declare function createActiveSkillState(defaultNames: readonly string[], promptNames: readonly string[], promptSource: string | undefined): ActiveSkillState;
6
+ export declare function addActiveSkills(state: ActiveSkillState, names: readonly string[], source: string): ActiveSkillState;
7
+ //# sourceMappingURL=active-skill-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-skill-state.d.ts","sourceRoot":"","sources":["../../src/core/active-skill-state.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,wBAAgB,sBAAsB,CACrC,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,YAAY,EAAE,MAAM,GAAG,SAAS,GAC9B,gBAAgB,CAKlB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAMnH","sourcesContent":["export interface ActiveSkillState {\n\treadonly names: readonly string[];\n\treadonly source: string | undefined;\n}\n\nexport function createActiveSkillState(\n\tdefaultNames: readonly string[],\n\tpromptNames: readonly string[],\n\tpromptSource: string | undefined,\n): ActiveSkillState {\n\treturn {\n\t\tnames: mergeNames(defaultNames, promptNames),\n\t\tsource: defaultNames.length > 0 ? mergeSources(\"settings\", promptSource) : promptSource,\n\t};\n}\n\nexport function addActiveSkills(state: ActiveSkillState, names: readonly string[], source: string): ActiveSkillState {\n\tif (names.length === 0) return state;\n\treturn {\n\t\tnames: mergeNames(state.names, names),\n\t\tsource: mergeSources(state.source, source),\n\t};\n}\n\nfunction mergeNames(first: readonly string[], second: readonly string[]): string[] {\n\treturn [...new Set([...first, ...second])];\n}\n\nfunction mergeSources(first: string | undefined, second: string | undefined): string | undefined {\n\tconst sources = [first, second]\n\t\t.flatMap((source) => source?.split(\"+\") ?? [])\n\t\t.map((source) => source.trim())\n\t\t.filter((source) => source !== \"\");\n\treturn sources.length > 0 ? [...new Set(sources)].join(\"+\") : undefined;\n}\n"]}
@@ -0,0 +1,25 @@
1
+ export function createActiveSkillState(defaultNames, promptNames, promptSource) {
2
+ return {
3
+ names: mergeNames(defaultNames, promptNames),
4
+ source: defaultNames.length > 0 ? mergeSources("settings", promptSource) : promptSource,
5
+ };
6
+ }
7
+ export function addActiveSkills(state, names, source) {
8
+ if (names.length === 0)
9
+ return state;
10
+ return {
11
+ names: mergeNames(state.names, names),
12
+ source: mergeSources(state.source, source),
13
+ };
14
+ }
15
+ function mergeNames(first, second) {
16
+ return [...new Set([...first, ...second])];
17
+ }
18
+ function mergeSources(first, second) {
19
+ const sources = [first, second]
20
+ .flatMap((source) => source?.split("+") ?? [])
21
+ .map((source) => source.trim())
22
+ .filter((source) => source !== "");
23
+ return sources.length > 0 ? [...new Set(sources)].join("+") : undefined;
24
+ }
25
+ //# sourceMappingURL=active-skill-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-skill-state.js","sourceRoot":"","sources":["../../src/core/active-skill-state.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,sBAAsB,CACrC,YAA+B,EAC/B,WAA8B,EAC9B,YAAgC,EACb;IACnB,OAAO;QACN,KAAK,EAAE,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC;QAC5C,MAAM,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY;KACvF,CAAC;AAAA,CACF;AAED,MAAM,UAAU,eAAe,CAAC,KAAuB,EAAE,KAAwB,EAAE,MAAc,EAAoB;IACpH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO;QACN,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC;QACrC,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;KAC1C,CAAC;AAAA,CACF;AAED,SAAS,UAAU,CAAC,KAAwB,EAAE,MAAyB,EAAY;IAClF,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAAA,CAC3C;AAED,SAAS,YAAY,CAAC,KAAyB,EAAE,MAA0B,EAAsB;IAChG,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;SAC7B,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;SAC7C,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;SAC9B,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CACxE","sourcesContent":["export interface ActiveSkillState {\n\treadonly names: readonly string[];\n\treadonly source: string | undefined;\n}\n\nexport function createActiveSkillState(\n\tdefaultNames: readonly string[],\n\tpromptNames: readonly string[],\n\tpromptSource: string | undefined,\n): ActiveSkillState {\n\treturn {\n\t\tnames: mergeNames(defaultNames, promptNames),\n\t\tsource: defaultNames.length > 0 ? mergeSources(\"settings\", promptSource) : promptSource,\n\t};\n}\n\nexport function addActiveSkills(state: ActiveSkillState, names: readonly string[], source: string): ActiveSkillState {\n\tif (names.length === 0) return state;\n\treturn {\n\t\tnames: mergeNames(state.names, names),\n\t\tsource: mergeSources(state.source, source),\n\t};\n}\n\nfunction mergeNames(first: readonly string[], second: readonly string[]): string[] {\n\treturn [...new Set([...first, ...second])];\n}\n\nfunction mergeSources(first: string | undefined, second: string | undefined): string | undefined {\n\tconst sources = [first, second]\n\t\t.flatMap((source) => source?.split(\"+\") ?? [])\n\t\t.map((source) => source.trim())\n\t\t.filter((source) => source !== \"\");\n\treturn sources.length > 0 ? [...new Set(sources)].join(\"+\") : undefined;\n}\n"]}