@bd7pil/ocrc 0.9.0

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 (292) hide show
  1. package/LICENSE +34 -0
  2. package/README.md +330 -0
  3. package/dist/cli/host-backends.js +216 -0
  4. package/dist/cli/host-backends.js.map +1 -0
  5. package/dist/cli/host.js +185 -0
  6. package/dist/cli/host.js.map +1 -0
  7. package/dist/cli/index.js +67 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/cli/init.js +68 -0
  10. package/dist/cli/init.js.map +1 -0
  11. package/dist/cli/install.js +220 -0
  12. package/dist/cli/install.js.map +1 -0
  13. package/dist/cli/pair.js +11 -0
  14. package/dist/cli/pair.js.map +1 -0
  15. package/dist/cli/uninstall.js +75 -0
  16. package/dist/cli/uninstall.js.map +1 -0
  17. package/dist/connectivity/auth/cf-access.js +20 -0
  18. package/dist/connectivity/auth/cf-access.js.map +1 -0
  19. package/dist/connectivity/auth/index.js +2 -0
  20. package/dist/connectivity/auth/index.js.map +1 -0
  21. package/dist/connectivity/auth/select.js +19 -0
  22. package/dist/connectivity/auth/select.js.map +1 -0
  23. package/dist/connectivity/auth/token.js +157 -0
  24. package/dist/connectivity/auth/token.js.map +1 -0
  25. package/dist/connectivity/exposure/cloudflared.js +77 -0
  26. package/dist/connectivity/exposure/cloudflared.js.map +1 -0
  27. package/dist/connectivity/exposure/index.js +2 -0
  28. package/dist/connectivity/exposure/index.js.map +1 -0
  29. package/dist/connectivity/exposure/providers.js +49 -0
  30. package/dist/connectivity/exposure/providers.js.map +1 -0
  31. package/dist/connectivity/pairing.js +29 -0
  32. package/dist/connectivity/pairing.js.map +1 -0
  33. package/dist/core/agent/acp-backend.js +539 -0
  34. package/dist/core/agent/acp-backend.js.map +1 -0
  35. package/dist/core/agent/acp-connect.js +92 -0
  36. package/dist/core/agent/acp-connect.js.map +1 -0
  37. package/dist/core/agent/acp-normalizer.js +81 -0
  38. package/dist/core/agent/acp-normalizer.js.map +1 -0
  39. package/dist/core/agent/acp-replay.js +89 -0
  40. package/dist/core/agent/acp-replay.js.map +1 -0
  41. package/dist/core/agent/acp-store.js +129 -0
  42. package/dist/core/agent/acp-store.js.map +1 -0
  43. package/dist/core/agent/backend.js +2 -0
  44. package/dist/core/agent/backend.js.map +1 -0
  45. package/dist/core/agent/diff-util.js +70 -0
  46. package/dist/core/agent/diff-util.js.map +1 -0
  47. package/dist/core/agent/event.js +12 -0
  48. package/dist/core/agent/event.js.map +1 -0
  49. package/dist/core/agent/opencode-backend.js +598 -0
  50. package/dist/core/agent/opencode-backend.js.map +1 -0
  51. package/dist/core/agent/opencode-normalizer.js +69 -0
  52. package/dist/core/agent/opencode-normalizer.js.map +1 -0
  53. package/dist/core/agent/registry.js +55 -0
  54. package/dist/core/agent/registry.js.map +1 -0
  55. package/dist/core/agent/v2-backend.js +176 -0
  56. package/dist/core/agent/v2-backend.js.map +1 -0
  57. package/dist/core/card-bus.js +74 -0
  58. package/dist/core/card-bus.js.map +1 -0
  59. package/dist/core/channels.js +95 -0
  60. package/dist/core/channels.js.map +1 -0
  61. package/dist/core/history.js +91 -0
  62. package/dist/core/history.js.map +1 -0
  63. package/dist/core/list-files.js +50 -0
  64. package/dist/core/list-files.js.map +1 -0
  65. package/dist/core/opencode-events.js +29 -0
  66. package/dist/core/opencode-events.js.map +1 -0
  67. package/dist/core/primary-election.js +91 -0
  68. package/dist/core/primary-election.js.map +1 -0
  69. package/dist/core/push.js +152 -0
  70. package/dist/core/push.js.map +1 -0
  71. package/dist/core/relay.js +400 -0
  72. package/dist/core/relay.js.map +1 -0
  73. package/dist/core/scheduler.js +150 -0
  74. package/dist/core/scheduler.js.map +1 -0
  75. package/dist/core/state.js +222 -0
  76. package/dist/core/state.js.map +1 -0
  77. package/dist/core/stream-accumulator.js +76 -0
  78. package/dist/core/stream-accumulator.js.map +1 -0
  79. package/dist/core/structured-card.js +2 -0
  80. package/dist/core/structured-card.js.map +1 -0
  81. package/dist/core/types.js +2 -0
  82. package/dist/core/types.js.map +1 -0
  83. package/dist/index.js +3 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/opencode/global-events.js +57 -0
  86. package/dist/opencode/global-events.js.map +1 -0
  87. package/dist/opencode/list-sessions.js +122 -0
  88. package/dist/opencode/list-sessions.js.map +1 -0
  89. package/dist/opencode/submit.js +39 -0
  90. package/dist/opencode/submit.js.map +1 -0
  91. package/dist/opencode/workspaces.js +51 -0
  92. package/dist/opencode/workspaces.js.map +1 -0
  93. package/dist/plugin/config.js +128 -0
  94. package/dist/plugin/config.js.map +1 -0
  95. package/dist/plugin/control-plane.js +133 -0
  96. package/dist/plugin/control-plane.js.map +1 -0
  97. package/dist/plugin/entry.js +409 -0
  98. package/dist/plugin/entry.js.map +1 -0
  99. package/dist/plugin/v2/event-map.js +193 -0
  100. package/dist/plugin/v2/event-map.js.map +1 -0
  101. package/dist/plugin/v2/types.js +15 -0
  102. package/dist/plugin/v2/types.js.map +1 -0
  103. package/dist/transport/interface.js +2 -0
  104. package/dist/transport/interface.js.map +1 -0
  105. package/dist/transport/telegram/esc.js +9 -0
  106. package/dist/transport/telegram/esc.js.map +1 -0
  107. package/dist/transport/telegram/handlers/info-commands.js +101 -0
  108. package/dist/transport/telegram/handlers/info-commands.js.map +1 -0
  109. package/dist/transport/telegram/handlers.js +1348 -0
  110. package/dist/transport/telegram/handlers.js.map +1 -0
  111. package/dist/transport/telegram/i18n/en.js +538 -0
  112. package/dist/transport/telegram/i18n/en.js.map +1 -0
  113. package/dist/transport/telegram/i18n/index.js +83 -0
  114. package/dist/transport/telegram/i18n/index.js.map +1 -0
  115. package/dist/transport/telegram/i18n/zh.js +538 -0
  116. package/dist/transport/telegram/i18n/zh.js.map +1 -0
  117. package/dist/transport/telegram/index.js +792 -0
  118. package/dist/transport/telegram/index.js.map +1 -0
  119. package/dist/transport/telegram/main-keyboard.js +36 -0
  120. package/dist/transport/telegram/main-keyboard.js.map +1 -0
  121. package/dist/transport/telegram/managers/abort-suppression-manager.js +33 -0
  122. package/dist/transport/telegram/managers/abort-suppression-manager.js.map +1 -0
  123. package/dist/transport/telegram/managers/external-input-suppression-manager.js +51 -0
  124. package/dist/transport/telegram/managers/external-input-suppression-manager.js.map +1 -0
  125. package/dist/transport/telegram/managers/interaction-manager.js +254 -0
  126. package/dist/transport/telegram/managers/interaction-manager.js.map +1 -0
  127. package/dist/transport/telegram/managers/permission-manager.js +242 -0
  128. package/dist/transport/telegram/managers/permission-manager.js.map +1 -0
  129. package/dist/transport/telegram/managers/question-manager.js +191 -0
  130. package/dist/transport/telegram/managers/question-manager.js.map +1 -0
  131. package/dist/transport/telegram/managers/rename-manager.js +56 -0
  132. package/dist/transport/telegram/managers/rename-manager.js.map +1 -0
  133. package/dist/transport/telegram/menus.js +77 -0
  134. package/dist/transport/telegram/menus.js.map +1 -0
  135. package/dist/transport/telegram/permission-flow.js +156 -0
  136. package/dist/transport/telegram/permission-flow.js.map +1 -0
  137. package/dist/transport/telegram/question-flow.js +224 -0
  138. package/dist/transport/telegram/question-flow.js.map +1 -0
  139. package/dist/transport/telegram/render/block-parser.js +365 -0
  140. package/dist/transport/telegram/render/block-parser.js.map +1 -0
  141. package/dist/transport/telegram/render/block-plain-text.js +87 -0
  142. package/dist/transport/telegram/render/block-plain-text.js.map +1 -0
  143. package/dist/transport/telegram/render/block-splitter.js +152 -0
  144. package/dist/transport/telegram/render/block-splitter.js.map +1 -0
  145. package/dist/transport/telegram/render/chunker.js +71 -0
  146. package/dist/transport/telegram/render/chunker.js.map +1 -0
  147. package/dist/transport/telegram/render/limits.js +13 -0
  148. package/dist/transport/telegram/render/limits.js.map +1 -0
  149. package/dist/transport/telegram/render/markdown-normalizer.js +102 -0
  150. package/dist/transport/telegram/render/markdown-normalizer.js.map +1 -0
  151. package/dist/transport/telegram/render/markdown-to-telegram-v2.js +116 -0
  152. package/dist/transport/telegram/render/markdown-to-telegram-v2.js.map +1 -0
  153. package/dist/transport/telegram/render/part-signature.js +14 -0
  154. package/dist/transport/telegram/render/part-signature.js.map +1 -0
  155. package/dist/transport/telegram/render/pipeline.js +23 -0
  156. package/dist/transport/telegram/render/pipeline.js.map +1 -0
  157. package/dist/transport/telegram/render/rich-blocks.js +311 -0
  158. package/dist/transport/telegram/render/rich-blocks.js.map +1 -0
  159. package/dist/transport/telegram/render/text-splitter.js +64 -0
  160. package/dist/transport/telegram/render/text-splitter.js.map +1 -0
  161. package/dist/transport/telegram/render/types.js +2 -0
  162. package/dist/transport/telegram/render/types.js.map +1 -0
  163. package/dist/transport/telegram/renderer.js +305 -0
  164. package/dist/transport/telegram/renderer.js.map +1 -0
  165. package/dist/transport/telegram/streaming/duration-formatter.js +68 -0
  166. package/dist/transport/telegram/streaming/duration-formatter.js.map +1 -0
  167. package/dist/transport/telegram/streaming/finalize-assistant-response.js +37 -0
  168. package/dist/transport/telegram/streaming/finalize-assistant-response.js.map +1 -0
  169. package/dist/transport/telegram/streaming/response-streamer.js +400 -0
  170. package/dist/transport/telegram/streaming/response-streamer.js.map +1 -0
  171. package/dist/transport/telegram/streaming/running-tool-tracker.js +150 -0
  172. package/dist/transport/telegram/streaming/running-tool-tracker.js.map +1 -0
  173. package/dist/transport/telegram/streaming/stream-throttle.js +57 -0
  174. package/dist/transport/telegram/streaming/stream-throttle.js.map +1 -0
  175. package/dist/transport/telegram/streaming/tool-call-streamer.js +390 -0
  176. package/dist/transport/telegram/streaming/tool-call-streamer.js.map +1 -0
  177. package/dist/transport/telegram/streaming-render.js +182 -0
  178. package/dist/transport/telegram/streaming-render.js.map +1 -0
  179. package/dist/transport/telegram/types/interaction.js +2 -0
  180. package/dist/transport/telegram/types/interaction.js.map +1 -0
  181. package/dist/transport/telegram/types/model.js +25 -0
  182. package/dist/transport/telegram/types/model.js.map +1 -0
  183. package/dist/transport/telegram/types/permission.js +2 -0
  184. package/dist/transport/telegram/types/permission.js.map +1 -0
  185. package/dist/transport/telegram/types/question.js +2 -0
  186. package/dist/transport/telegram/types/question.js.map +1 -0
  187. package/dist/transport/telegram/types/rename.js +2 -0
  188. package/dist/transport/telegram/types/rename.js.map +1 -0
  189. package/dist/transport/telegram/types/scheduled-task.js +23 -0
  190. package/dist/transport/telegram/types/scheduled-task.js.map +1 -0
  191. package/dist/transport/telegram/types/session.js +2 -0
  192. package/dist/transport/telegram/types/session.js.map +1 -0
  193. package/dist/transport/telegram/ui.js +28 -0
  194. package/dist/transport/telegram/ui.js.map +1 -0
  195. package/dist/transport/web/index.js +148 -0
  196. package/dist/transport/web/index.js.map +1 -0
  197. package/dist/transport/web/middleware/cf-access.js +104 -0
  198. package/dist/transport/web/middleware/cf-access.js.map +1 -0
  199. package/dist/transport/web/opencode-config.js +15 -0
  200. package/dist/transport/web/opencode-config.js.map +1 -0
  201. package/dist/transport/web/routes/abort.js +12 -0
  202. package/dist/transport/web/routes/abort.js.map +1 -0
  203. package/dist/transport/web/routes/approval.js +16 -0
  204. package/dist/transport/web/routes/approval.js.map +1 -0
  205. package/dist/transport/web/routes/catalog.js +11 -0
  206. package/dist/transport/web/routes/catalog.js.map +1 -0
  207. package/dist/transport/web/routes/channels.js +53 -0
  208. package/dist/transport/web/routes/channels.js.map +1 -0
  209. package/dist/transport/web/routes/commands.js +15 -0
  210. package/dist/transport/web/routes/commands.js.map +1 -0
  211. package/dist/transport/web/routes/context.js +17 -0
  212. package/dist/transport/web/routes/context.js.map +1 -0
  213. package/dist/transport/web/routes/controls.js +34 -0
  214. package/dist/transport/web/routes/controls.js.map +1 -0
  215. package/dist/transport/web/routes/create-session.js +21 -0
  216. package/dist/transport/web/routes/create-session.js.map +1 -0
  217. package/dist/transport/web/routes/diff.js +7 -0
  218. package/dist/transport/web/routes/diff.js.map +1 -0
  219. package/dist/transport/web/routes/files.js +22 -0
  220. package/dist/transport/web/routes/files.js.map +1 -0
  221. package/dist/transport/web/routes/logs.js +9 -0
  222. package/dist/transport/web/routes/logs.js.map +1 -0
  223. package/dist/transport/web/routes/m8.js +69 -0
  224. package/dist/transport/web/routes/m8.js.map +1 -0
  225. package/dist/transport/web/routes/mcp.js +7 -0
  226. package/dist/transport/web/routes/mcp.js.map +1 -0
  227. package/dist/transport/web/routes/message.js +32 -0
  228. package/dist/transport/web/routes/message.js.map +1 -0
  229. package/dist/transport/web/routes/overrides.js +20 -0
  230. package/dist/transport/web/routes/overrides.js.map +1 -0
  231. package/dist/transport/web/routes/question.js +32 -0
  232. package/dist/transport/web/routes/question.js.map +1 -0
  233. package/dist/transport/web/routes/rename.js +12 -0
  234. package/dist/transport/web/routes/rename.js.map +1 -0
  235. package/dist/transport/web/routes/schedules.js +28 -0
  236. package/dist/transport/web/routes/schedules.js.map +1 -0
  237. package/dist/transport/web/routes/session.js +20 -0
  238. package/dist/transport/web/routes/session.js.map +1 -0
  239. package/dist/transport/web/routes/sessions.js +25 -0
  240. package/dist/transport/web/routes/sessions.js.map +1 -0
  241. package/dist/transport/web/routes/subagents.js +11 -0
  242. package/dist/transport/web/routes/subagents.js.map +1 -0
  243. package/dist/transport/web/routes/suggestions.js +7 -0
  244. package/dist/transport/web/routes/suggestions.js.map +1 -0
  245. package/dist/transport/web/routes/todo.js +7 -0
  246. package/dist/transport/web/routes/todo.js.map +1 -0
  247. package/dist/transport/web/routes/version.js +5 -0
  248. package/dist/transport/web/routes/version.js.map +1 -0
  249. package/dist/transport/web/routes/workspaces.js +7 -0
  250. package/dist/transport/web/routes/workspaces.js.map +1 -0
  251. package/dist/transport/web/server.js +111 -0
  252. package/dist/transport/web/server.js.map +1 -0
  253. package/dist/transport/web/session-summary.js +46 -0
  254. package/dist/transport/web/session-summary.js.map +1 -0
  255. package/dist/transport/web/ws-hub.js +83 -0
  256. package/dist/transport/web/ws-hub.js.map +1 -0
  257. package/dist/utils/logger.js +105 -0
  258. package/dist/utils/logger.js.map +1 -0
  259. package/dist/utils/markdown.js +129 -0
  260. package/dist/utils/markdown.js.map +1 -0
  261. package/dist/utils/paths.js +18 -0
  262. package/dist/utils/paths.js.map +1 -0
  263. package/dist/utils/version.js +44 -0
  264. package/dist/utils/version.js.map +1 -0
  265. package/package.json +91 -0
  266. package/web/dist/_app/env.js +1 -0
  267. package/web/dist/_app/immutable/assets/0.DxN3RsuG.css +1 -0
  268. package/web/dist/_app/immutable/assets/2.BNuGfmZP.css +1 -0
  269. package/web/dist/_app/immutable/assets/3.CTDprntu.css +1 -0
  270. package/web/dist/_app/immutable/chunks/BUpwHpMJ.js +1 -0
  271. package/web/dist/_app/immutable/chunks/BjY4dxcB.js +2 -0
  272. package/web/dist/_app/immutable/chunks/C2FuqD3s.js +1 -0
  273. package/web/dist/_app/immutable/chunks/CUHGq08X.js +2 -0
  274. package/web/dist/_app/immutable/chunks/CWj6FrbW.js +1 -0
  275. package/web/dist/_app/immutable/chunks/ClvoqtGj.js +1 -0
  276. package/web/dist/_app/immutable/chunks/DIEDQ_hk.js +1 -0
  277. package/web/dist/_app/immutable/entry/app.BoRpcVMj.js +2 -0
  278. package/web/dist/_app/immutable/entry/start.Cj-PQNTq.js +1 -0
  279. package/web/dist/_app/immutable/nodes/0.y9YEms5p.js +3 -0
  280. package/web/dist/_app/immutable/nodes/1.CPhhiRM2.js +1 -0
  281. package/web/dist/_app/immutable/nodes/2.B_c84Mc9.js +1 -0
  282. package/web/dist/_app/immutable/nodes/3.ClTd0J3D.js +64 -0
  283. package/web/dist/_app/version.json +1 -0
  284. package/web/dist/apple-touch-icon.png +0 -0
  285. package/web/dist/favicon.png +0 -0
  286. package/web/dist/favicon.svg +17 -0
  287. package/web/dist/icon-192.png +0 -0
  288. package/web/dist/icon-512-maskable.png +0 -0
  289. package/web/dist/icon-512.png +0 -0
  290. package/web/dist/index.html +73 -0
  291. package/web/dist/manifest.webmanifest +28 -0
  292. package/web/dist/service-worker.js +1 -0
@@ -0,0 +1,128 @@
1
+ import { config as dotenvConfig } from 'dotenv';
2
+ import { resolve, dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { createLogger } from '../utils/logger.js';
5
+ import { ocrcHome } from '../utils/paths.js';
6
+ const log = createLogger('config');
7
+ // Repo root resolved from this module's OWN location (<repo>/dist/plugin/config.js,
8
+ // or <repo>/src/plugin/config.ts in dev — both two levels below the root). The
9
+ // plugin is registered globally, so opencode can be launched from any folder;
10
+ // resolving .env and bundled web assets against this constant instead of cwd is
11
+ // what keeps it working regardless of the launch directory.
12
+ const PLUGIN_ROOT = (() => {
13
+ try {
14
+ return resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
15
+ }
16
+ catch {
17
+ return process.cwd();
18
+ }
19
+ })();
20
+ // dotenv never overrides an already-set variable, so the FIRST file loaded
21
+ // wins. The plugin's own install directory is authoritative: opencode can be
22
+ // launched from any folder, and a project-level .env must not be able to
23
+ // hijack the bot identity / allowlist / web token. cwd is loaded LAST (lowest
24
+ // priority — it can still supply keys nothing else defines).
25
+ // Exported for tests.
26
+ export function dotEnvPaths() {
27
+ const paths = [resolve(ocrcHome(), 'config.env'), resolve(PLUGIN_ROOT, '.env')];
28
+ if (process.env.OPENCODE_CONFIG_DIR) {
29
+ paths.push(resolve(process.env.OPENCODE_CONFIG_DIR, '.env'));
30
+ }
31
+ if (process.env.OPENCODE_PROJECT) {
32
+ paths.push(resolve(process.env.OPENCODE_PROJECT, '.env'));
33
+ paths.push(resolve(process.env.OPENCODE_PROJECT, '.opencode', '.env'));
34
+ }
35
+ paths.push(resolve(process.cwd(), '.env'));
36
+ return paths;
37
+ }
38
+ function loadDotEnv() {
39
+ for (const path of dotEnvPaths())
40
+ dotenvConfig({ path, override: false });
41
+ }
42
+ function env(key, optionsVal) {
43
+ return optionsVal ?? process.env[key];
44
+ }
45
+ /** Read an OCRC-owned setting by its fork name, falling back to the upstream
46
+ * pre-fork variable so existing .env files keep working after the rename. */
47
+ function envFork(key, legacy, optionsVal) {
48
+ return optionsVal ?? process.env[key] ?? process.env[legacy];
49
+ }
50
+ export function loadPluginConfig(options, opts) {
51
+ loadDotEnv();
52
+ // The opencode plugin always needs Telegram; the standalone host can run
53
+ // web-only (no bot), so it passes requireTelegram=false.
54
+ const requireTelegram = opts?.requireTelegram ?? true;
55
+ const token = options?.telegramBotToken ?? process.env.TELEGRAM_BOT_TOKEN;
56
+ if (!token && requireTelegram) {
57
+ throw new Error('TELEGRAM_BOT_TOKEN is required. Set it via opencode.json plugin options or TELEGRAM_BOT_TOKEN environment variable.');
58
+ }
59
+ const userIdsRaw = options?.allowedUserIds ?? process.env.ALLOWED_USER_IDS ?? '';
60
+ const ids = userIdsRaw
61
+ .toString()
62
+ .split(',')
63
+ .map((s) => s.trim())
64
+ .filter(Boolean)
65
+ .map(Number)
66
+ .filter((n) => Number.isFinite(n));
67
+ // Token and allowlist must come as a pair: with a token but no IDs the
68
+ // transport would start and address every push to chat "undefined".
69
+ if (ids.length === 0 && (requireTelegram || token)) {
70
+ throw new Error('ALLOWED_USER_IDS is required (comma-separated Telegram user IDs) whenever Telegram is enabled. Set it, or unset TELEGRAM_BOT_TOKEN to run web-only.');
71
+ }
72
+ // Fork defaults (2026-09-25 decisions): bind 0.0.0.0 — the product is
73
+ // LAN-first (phone on the same network), and the token gate below is not
74
+ // optional; port 4099 pairs with opencode's own 4096. Upstream variable
75
+ // names keep working via envFork().
76
+ const webHost = envFork('OCRC_WEB_HOST', 'WEB_HOST', options?.webHost) ?? '0.0.0.0';
77
+ const devBypassExplicit = bool(options?.webCfAccessDevBypass);
78
+ const devBypassEnv = process.env.OCRC_WEB_CF_ACCESS_DEV_BYPASS ?? process.env.WEB_CF_ACCESS_DEV_BYPASS;
79
+ return {
80
+ telegramBotToken: token ?? '',
81
+ allowedUserIds: ids,
82
+ webEnabled: bool(options?.webEnabled) ??
83
+ (process.env.OCRC_WEB_ENABLED ?? process.env.WEB_ENABLED) === 'true',
84
+ webHost,
85
+ webPort: num(options?.webPort ?? process.env.OCRC_WEB_PORT ?? process.env.WEB_PORT, 4099, 'OCRC_WEB_PORT'),
86
+ webPublicUrl: envFork('OCRC_WEB_PUBLIC_URL', 'WEB_PUBLIC_URL', options?.webPublicUrl) ?? '',
87
+ webStaticRoot: envFork('OCRC_WEB_STATIC_ROOT', 'WEB_STATIC_ROOT', options?.webStaticRoot) ?? resolve(PLUGIN_ROOT, 'web', 'dist'),
88
+ webCacheSize: num(options?.webCacheSize ?? process.env.OCRC_WEB_SESSION_CACHE_SIZE ?? process.env.WEB_SESSION_CACHE_SIZE, 100, 'OCRC_WEB_SESSION_CACHE_SIZE'),
89
+ webCfAccessTeam: envFork('OCRC_WEB_CF_ACCESS_TEAM', 'WEB_CF_ACCESS_TEAM', options?.webCfAccessTeam) ?? '',
90
+ webCfAccessAud: envFork('OCRC_WEB_CF_ACCESS_AUD', 'WEB_CF_ACCESS_AUD', options?.webCfAccessAud) ?? '',
91
+ // Default OFF: a loopback bind is not a safe bypass signal when traffic
92
+ // arrives via a tunnel (cloudflared connects from 127.0.0.1). Local dev
93
+ // must opt in explicitly with OCRC_WEB_CF_ACCESS_DEV_BYPASS=true.
94
+ webCfAccessDevBypass: devBypassExplicit ?? (devBypassEnv !== undefined ? devBypassEnv === 'true' : false),
95
+ webCfAccessDevEmail: envFork('OCRC_WEB_CF_ACCESS_DEV_EMAIL', 'WEB_CF_ACCESS_DEV_EMAIL', options?.webCfAccessDevEmail) ?? 'dev@localhost',
96
+ webAuth: (envFork('OCRC_WEB_AUTH', 'WEB_AUTH', options?.webAuth) ?? 'token') === 'cf-access' ? 'cf-access' : 'token',
97
+ webToken: envFork('OCRC_WEB_TOKEN', 'WEB_TOKEN', options?.webToken) ?? '',
98
+ statePath: envFork('OCRC_STATE_PATH', 'STATE_PATH', options?.statePath) ?? join(ocrcHome(), 'state.json'),
99
+ tuiVisible: bool(options?.tuiVisible) ?? process.env.TUI_VISIBLE !== 'false',
100
+ transport: env('TRANSPORT', options?.transport) ?? 'telegram',
101
+ chatTimeoutMs: num(options?.chatTimeoutMs ?? process.env.CHAT_TIMEOUT_MS, 600000, 'CHAT_TIMEOUT_MS'),
102
+ baseUrl: env('OPENCODE_BASE_URL', options?.baseUrl) ?? '',
103
+ tgChunkSoftLimit: num(options?.tgChunkSoftLimit ?? process.env.TG_CHUNK_SOFT_LIMIT, 3500, 'TG_CHUNK_SOFT_LIMIT'),
104
+ acpCommand: env('OCRC_ACP_CMD', options?.acpCommand) ?? 'kimi acp',
105
+ backends: env('OCRC_BACKENDS', options?.backends) ?? '',
106
+ };
107
+ }
108
+ function bool(val) {
109
+ if (val === undefined)
110
+ return undefined;
111
+ if (val === 'true' || val === '1' || val === 'yes')
112
+ return true;
113
+ if (val === 'false' || val === '0' || val === 'no')
114
+ return false;
115
+ return undefined;
116
+ }
117
+ /** Parse a numeric setting; a non-finite value falls back to the default with a warning. */
118
+ function num(raw, fallback, name) {
119
+ if (raw === undefined || raw === null || raw === '')
120
+ return fallback;
121
+ const n = Number(raw);
122
+ if (!Number.isFinite(n)) {
123
+ log.warn(`invalid number for ${name}: ${JSON.stringify(String(raw))} — using default ${fallback}`);
124
+ return fallback;
125
+ }
126
+ return n;
127
+ }
128
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/plugin/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ import { createOpencodeBackend } from '../core/agent/opencode-backend.js';
2
+ import { createV2Backend } from '../core/agent/v2-backend.js';
3
+ import { createV2EventMapper } from './v2/event-map.js';
4
+ import { createLogger } from '../utils/logger.js';
5
+ const log = createLogger('control-plane');
6
+ export function createV1ControlPlane(ctx) {
7
+ const serverUrl = ctx.serverUrl.toString().replace(/\/+$/, '');
8
+ const backend = createOpencodeBackend({ client: ctx.client, baseUrl: serverUrl });
9
+ return {
10
+ serverUrl,
11
+ directory: ctx.worktree,
12
+ backend,
13
+ async getSession(id) {
14
+ const res = await ctx.client.session.get({ path: { id } });
15
+ return res?.data;
16
+ },
17
+ wireEvents(dispatchEvent) {
18
+ // The plugin `event` hook is the SINGLE dispatch source for session/relay
19
+ // events. The old design also pulled /global/event for "other workspaces"
20
+ // on the premise that the hook only sees its own directory — but on
21
+ // opencode 1.18.32 the hook demonstrably receives EVERY workspace's
22
+ // events (verified live: with both sources wired, a turn in another-
23
+ // directory session was finalized twice, 4ms apart, publishing duplicate
24
+ // assistant cards).
25
+ //
26
+ // EXCEPTION (M10, verified live): the hook does NOT carry `question.*`
27
+ // events — a pending question appears on /global/event as
28
+ // question.asked/replied/rejected but never on the hook. Pull a dedicated
29
+ // SSE and forward ONLY those types, so session events stay single-source
30
+ // while questions still reach the TG wizard and web cards.
31
+ const QUESTION_TYPES = new Set(['question.asked', 'question.replied', 'question.rejected']);
32
+ const controller = new AbortController();
33
+ const consume = async () => {
34
+ let buf = '';
35
+ while (!controller.signal.aborted) {
36
+ try {
37
+ const res = await fetch(`${serverUrl}/global/event`, { signal: controller.signal });
38
+ if (!res.ok || !res.body)
39
+ throw new Error(`global/event HTTP ${res.status}`);
40
+ const decoder = new TextDecoder();
41
+ const reader = res.body.getReader();
42
+ buf = '';
43
+ for (;;) {
44
+ const { done, value } = await reader.read();
45
+ if (done)
46
+ break;
47
+ buf += decoder.decode(value, { stream: true });
48
+ let idx;
49
+ while ((idx = buf.indexOf('\n')) >= 0) {
50
+ const line = buf.slice(0, idx).trimEnd();
51
+ buf = buf.slice(idx + 1);
52
+ if (!line.startsWith('data:'))
53
+ continue;
54
+ const payload = line.slice(5).trim();
55
+ if (!payload)
56
+ continue;
57
+ try {
58
+ // Wire envelope: {directory, project, payload:{type, properties}}
59
+ const frame = JSON.parse(payload);
60
+ const type = frame?.payload?.type ?? '';
61
+ if (!QUESTION_TYPES.has(type))
62
+ continue;
63
+ await dispatchEvent({
64
+ type,
65
+ properties: frame.payload.properties ?? {},
66
+ });
67
+ }
68
+ catch { /* malformed frame — keep the stream */ }
69
+ }
70
+ }
71
+ }
72
+ catch (err) {
73
+ if (controller.signal.aborted)
74
+ return;
75
+ log.debug('question SSE dropped, reconnecting', err.message);
76
+ }
77
+ if (!controller.signal.aborted)
78
+ await new Promise((r) => setTimeout(r, 3000));
79
+ }
80
+ };
81
+ void consume();
82
+ return () => controller.abort();
83
+ },
84
+ eventHook(dispatchEvent) {
85
+ return async ({ event }) => {
86
+ await dispatchEvent(event);
87
+ };
88
+ },
89
+ };
90
+ }
91
+ export function createV2ControlPlane(ctx) {
92
+ const { backend, observeSessionEvent } = createV2Backend(ctx);
93
+ const mapper = createV2EventMapper();
94
+ return {
95
+ directory: ctx.location?.directory,
96
+ backend,
97
+ wireEvents(dispatchEvent) {
98
+ // V2 has no plugin event hook: everything arrives via the async event
99
+ // iterator. Map V2Event → V1 shapes, feed the session registry, and
100
+ // dispatch — the same dispatchEvent the V1 hook path uses.
101
+ const controller = new AbortController();
102
+ void (async () => {
103
+ try {
104
+ for await (const raw of ctx.event.subscribe({ signal: controller.signal })) {
105
+ try {
106
+ const ev = raw;
107
+ const sid = ev?.data?.sessionID;
108
+ if (typeof sid === 'string') {
109
+ observeSessionEvent({
110
+ type: ev.type,
111
+ sessionID: sid,
112
+ title: ev?.data?.title ?? (ev?.data?.info?.title ?? undefined),
113
+ });
114
+ }
115
+ for (const mapped of mapper.map(ev)) {
116
+ await dispatchEvent(mapped);
117
+ }
118
+ }
119
+ catch (err) {
120
+ // one bad event must not kill the loop
121
+ }
122
+ }
123
+ }
124
+ catch (err) {
125
+ if (!controller.signal.aborted)
126
+ throw err;
127
+ }
128
+ })();
129
+ return () => controller.abort();
130
+ },
131
+ };
132
+ }
133
+ //# sourceMappingURL=control-plane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-plane.js","sourceRoot":"","sources":["../../src/plugin/control-plane.ts"],"names":[],"mappings":"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"}