@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.
- package/LICENSE +34 -0
- package/README.md +330 -0
- package/dist/cli/host-backends.js +216 -0
- package/dist/cli/host-backends.js.map +1 -0
- package/dist/cli/host.js +185 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/index.js +67 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.js +68 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/install.js +220 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/pair.js +11 -0
- package/dist/cli/pair.js.map +1 -0
- package/dist/cli/uninstall.js +75 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/connectivity/auth/cf-access.js +20 -0
- package/dist/connectivity/auth/cf-access.js.map +1 -0
- package/dist/connectivity/auth/index.js +2 -0
- package/dist/connectivity/auth/index.js.map +1 -0
- package/dist/connectivity/auth/select.js +19 -0
- package/dist/connectivity/auth/select.js.map +1 -0
- package/dist/connectivity/auth/token.js +157 -0
- package/dist/connectivity/auth/token.js.map +1 -0
- package/dist/connectivity/exposure/cloudflared.js +77 -0
- package/dist/connectivity/exposure/cloudflared.js.map +1 -0
- package/dist/connectivity/exposure/index.js +2 -0
- package/dist/connectivity/exposure/index.js.map +1 -0
- package/dist/connectivity/exposure/providers.js +49 -0
- package/dist/connectivity/exposure/providers.js.map +1 -0
- package/dist/connectivity/pairing.js +29 -0
- package/dist/connectivity/pairing.js.map +1 -0
- package/dist/core/agent/acp-backend.js +539 -0
- package/dist/core/agent/acp-backend.js.map +1 -0
- package/dist/core/agent/acp-connect.js +92 -0
- package/dist/core/agent/acp-connect.js.map +1 -0
- package/dist/core/agent/acp-normalizer.js +81 -0
- package/dist/core/agent/acp-normalizer.js.map +1 -0
- package/dist/core/agent/acp-replay.js +89 -0
- package/dist/core/agent/acp-replay.js.map +1 -0
- package/dist/core/agent/acp-store.js +129 -0
- package/dist/core/agent/acp-store.js.map +1 -0
- package/dist/core/agent/backend.js +2 -0
- package/dist/core/agent/backend.js.map +1 -0
- package/dist/core/agent/diff-util.js +70 -0
- package/dist/core/agent/diff-util.js.map +1 -0
- package/dist/core/agent/event.js +12 -0
- package/dist/core/agent/event.js.map +1 -0
- package/dist/core/agent/opencode-backend.js +598 -0
- package/dist/core/agent/opencode-backend.js.map +1 -0
- package/dist/core/agent/opencode-normalizer.js +69 -0
- package/dist/core/agent/opencode-normalizer.js.map +1 -0
- package/dist/core/agent/registry.js +55 -0
- package/dist/core/agent/registry.js.map +1 -0
- package/dist/core/agent/v2-backend.js +176 -0
- package/dist/core/agent/v2-backend.js.map +1 -0
- package/dist/core/card-bus.js +74 -0
- package/dist/core/card-bus.js.map +1 -0
- package/dist/core/channels.js +95 -0
- package/dist/core/channels.js.map +1 -0
- package/dist/core/history.js +91 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/list-files.js +50 -0
- package/dist/core/list-files.js.map +1 -0
- package/dist/core/opencode-events.js +29 -0
- package/dist/core/opencode-events.js.map +1 -0
- package/dist/core/primary-election.js +91 -0
- package/dist/core/primary-election.js.map +1 -0
- package/dist/core/push.js +152 -0
- package/dist/core/push.js.map +1 -0
- package/dist/core/relay.js +400 -0
- package/dist/core/relay.js.map +1 -0
- package/dist/core/scheduler.js +150 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/state.js +222 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/stream-accumulator.js +76 -0
- package/dist/core/stream-accumulator.js.map +1 -0
- package/dist/core/structured-card.js +2 -0
- package/dist/core/structured-card.js.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/opencode/global-events.js +57 -0
- package/dist/opencode/global-events.js.map +1 -0
- package/dist/opencode/list-sessions.js +122 -0
- package/dist/opencode/list-sessions.js.map +1 -0
- package/dist/opencode/submit.js +39 -0
- package/dist/opencode/submit.js.map +1 -0
- package/dist/opencode/workspaces.js +51 -0
- package/dist/opencode/workspaces.js.map +1 -0
- package/dist/plugin/config.js +128 -0
- package/dist/plugin/config.js.map +1 -0
- package/dist/plugin/control-plane.js +133 -0
- package/dist/plugin/control-plane.js.map +1 -0
- package/dist/plugin/entry.js +409 -0
- package/dist/plugin/entry.js.map +1 -0
- package/dist/plugin/v2/event-map.js +193 -0
- package/dist/plugin/v2/event-map.js.map +1 -0
- package/dist/plugin/v2/types.js +15 -0
- package/dist/plugin/v2/types.js.map +1 -0
- package/dist/transport/interface.js +2 -0
- package/dist/transport/interface.js.map +1 -0
- package/dist/transport/telegram/esc.js +9 -0
- package/dist/transport/telegram/esc.js.map +1 -0
- package/dist/transport/telegram/handlers/info-commands.js +101 -0
- package/dist/transport/telegram/handlers/info-commands.js.map +1 -0
- package/dist/transport/telegram/handlers.js +1348 -0
- package/dist/transport/telegram/handlers.js.map +1 -0
- package/dist/transport/telegram/i18n/en.js +538 -0
- package/dist/transport/telegram/i18n/en.js.map +1 -0
- package/dist/transport/telegram/i18n/index.js +83 -0
- package/dist/transport/telegram/i18n/index.js.map +1 -0
- package/dist/transport/telegram/i18n/zh.js +538 -0
- package/dist/transport/telegram/i18n/zh.js.map +1 -0
- package/dist/transport/telegram/index.js +792 -0
- package/dist/transport/telegram/index.js.map +1 -0
- package/dist/transport/telegram/main-keyboard.js +36 -0
- package/dist/transport/telegram/main-keyboard.js.map +1 -0
- package/dist/transport/telegram/managers/abort-suppression-manager.js +33 -0
- package/dist/transport/telegram/managers/abort-suppression-manager.js.map +1 -0
- package/dist/transport/telegram/managers/external-input-suppression-manager.js +51 -0
- package/dist/transport/telegram/managers/external-input-suppression-manager.js.map +1 -0
- package/dist/transport/telegram/managers/interaction-manager.js +254 -0
- package/dist/transport/telegram/managers/interaction-manager.js.map +1 -0
- package/dist/transport/telegram/managers/permission-manager.js +242 -0
- package/dist/transport/telegram/managers/permission-manager.js.map +1 -0
- package/dist/transport/telegram/managers/question-manager.js +191 -0
- package/dist/transport/telegram/managers/question-manager.js.map +1 -0
- package/dist/transport/telegram/managers/rename-manager.js +56 -0
- package/dist/transport/telegram/managers/rename-manager.js.map +1 -0
- package/dist/transport/telegram/menus.js +77 -0
- package/dist/transport/telegram/menus.js.map +1 -0
- package/dist/transport/telegram/permission-flow.js +156 -0
- package/dist/transport/telegram/permission-flow.js.map +1 -0
- package/dist/transport/telegram/question-flow.js +224 -0
- package/dist/transport/telegram/question-flow.js.map +1 -0
- package/dist/transport/telegram/render/block-parser.js +365 -0
- package/dist/transport/telegram/render/block-parser.js.map +1 -0
- package/dist/transport/telegram/render/block-plain-text.js +87 -0
- package/dist/transport/telegram/render/block-plain-text.js.map +1 -0
- package/dist/transport/telegram/render/block-splitter.js +152 -0
- package/dist/transport/telegram/render/block-splitter.js.map +1 -0
- package/dist/transport/telegram/render/chunker.js +71 -0
- package/dist/transport/telegram/render/chunker.js.map +1 -0
- package/dist/transport/telegram/render/limits.js +13 -0
- package/dist/transport/telegram/render/limits.js.map +1 -0
- package/dist/transport/telegram/render/markdown-normalizer.js +102 -0
- package/dist/transport/telegram/render/markdown-normalizer.js.map +1 -0
- package/dist/transport/telegram/render/markdown-to-telegram-v2.js +116 -0
- package/dist/transport/telegram/render/markdown-to-telegram-v2.js.map +1 -0
- package/dist/transport/telegram/render/part-signature.js +14 -0
- package/dist/transport/telegram/render/part-signature.js.map +1 -0
- package/dist/transport/telegram/render/pipeline.js +23 -0
- package/dist/transport/telegram/render/pipeline.js.map +1 -0
- package/dist/transport/telegram/render/rich-blocks.js +311 -0
- package/dist/transport/telegram/render/rich-blocks.js.map +1 -0
- package/dist/transport/telegram/render/text-splitter.js +64 -0
- package/dist/transport/telegram/render/text-splitter.js.map +1 -0
- package/dist/transport/telegram/render/types.js +2 -0
- package/dist/transport/telegram/render/types.js.map +1 -0
- package/dist/transport/telegram/renderer.js +305 -0
- package/dist/transport/telegram/renderer.js.map +1 -0
- package/dist/transport/telegram/streaming/duration-formatter.js +68 -0
- package/dist/transport/telegram/streaming/duration-formatter.js.map +1 -0
- package/dist/transport/telegram/streaming/finalize-assistant-response.js +37 -0
- package/dist/transport/telegram/streaming/finalize-assistant-response.js.map +1 -0
- package/dist/transport/telegram/streaming/response-streamer.js +400 -0
- package/dist/transport/telegram/streaming/response-streamer.js.map +1 -0
- package/dist/transport/telegram/streaming/running-tool-tracker.js +150 -0
- package/dist/transport/telegram/streaming/running-tool-tracker.js.map +1 -0
- package/dist/transport/telegram/streaming/stream-throttle.js +57 -0
- package/dist/transport/telegram/streaming/stream-throttle.js.map +1 -0
- package/dist/transport/telegram/streaming/tool-call-streamer.js +390 -0
- package/dist/transport/telegram/streaming/tool-call-streamer.js.map +1 -0
- package/dist/transport/telegram/streaming-render.js +182 -0
- package/dist/transport/telegram/streaming-render.js.map +1 -0
- package/dist/transport/telegram/types/interaction.js +2 -0
- package/dist/transport/telegram/types/interaction.js.map +1 -0
- package/dist/transport/telegram/types/model.js +25 -0
- package/dist/transport/telegram/types/model.js.map +1 -0
- package/dist/transport/telegram/types/permission.js +2 -0
- package/dist/transport/telegram/types/permission.js.map +1 -0
- package/dist/transport/telegram/types/question.js +2 -0
- package/dist/transport/telegram/types/question.js.map +1 -0
- package/dist/transport/telegram/types/rename.js +2 -0
- package/dist/transport/telegram/types/rename.js.map +1 -0
- package/dist/transport/telegram/types/scheduled-task.js +23 -0
- package/dist/transport/telegram/types/scheduled-task.js.map +1 -0
- package/dist/transport/telegram/types/session.js +2 -0
- package/dist/transport/telegram/types/session.js.map +1 -0
- package/dist/transport/telegram/ui.js +28 -0
- package/dist/transport/telegram/ui.js.map +1 -0
- package/dist/transport/web/index.js +148 -0
- package/dist/transport/web/index.js.map +1 -0
- package/dist/transport/web/middleware/cf-access.js +104 -0
- package/dist/transport/web/middleware/cf-access.js.map +1 -0
- package/dist/transport/web/opencode-config.js +15 -0
- package/dist/transport/web/opencode-config.js.map +1 -0
- package/dist/transport/web/routes/abort.js +12 -0
- package/dist/transport/web/routes/abort.js.map +1 -0
- package/dist/transport/web/routes/approval.js +16 -0
- package/dist/transport/web/routes/approval.js.map +1 -0
- package/dist/transport/web/routes/catalog.js +11 -0
- package/dist/transport/web/routes/catalog.js.map +1 -0
- package/dist/transport/web/routes/channels.js +53 -0
- package/dist/transport/web/routes/channels.js.map +1 -0
- package/dist/transport/web/routes/commands.js +15 -0
- package/dist/transport/web/routes/commands.js.map +1 -0
- package/dist/transport/web/routes/context.js +17 -0
- package/dist/transport/web/routes/context.js.map +1 -0
- package/dist/transport/web/routes/controls.js +34 -0
- package/dist/transport/web/routes/controls.js.map +1 -0
- package/dist/transport/web/routes/create-session.js +21 -0
- package/dist/transport/web/routes/create-session.js.map +1 -0
- package/dist/transport/web/routes/diff.js +7 -0
- package/dist/transport/web/routes/diff.js.map +1 -0
- package/dist/transport/web/routes/files.js +22 -0
- package/dist/transport/web/routes/files.js.map +1 -0
- package/dist/transport/web/routes/logs.js +9 -0
- package/dist/transport/web/routes/logs.js.map +1 -0
- package/dist/transport/web/routes/m8.js +69 -0
- package/dist/transport/web/routes/m8.js.map +1 -0
- package/dist/transport/web/routes/mcp.js +7 -0
- package/dist/transport/web/routes/mcp.js.map +1 -0
- package/dist/transport/web/routes/message.js +32 -0
- package/dist/transport/web/routes/message.js.map +1 -0
- package/dist/transport/web/routes/overrides.js +20 -0
- package/dist/transport/web/routes/overrides.js.map +1 -0
- package/dist/transport/web/routes/question.js +32 -0
- package/dist/transport/web/routes/question.js.map +1 -0
- package/dist/transport/web/routes/rename.js +12 -0
- package/dist/transport/web/routes/rename.js.map +1 -0
- package/dist/transport/web/routes/schedules.js +28 -0
- package/dist/transport/web/routes/schedules.js.map +1 -0
- package/dist/transport/web/routes/session.js +20 -0
- package/dist/transport/web/routes/session.js.map +1 -0
- package/dist/transport/web/routes/sessions.js +25 -0
- package/dist/transport/web/routes/sessions.js.map +1 -0
- package/dist/transport/web/routes/subagents.js +11 -0
- package/dist/transport/web/routes/subagents.js.map +1 -0
- package/dist/transport/web/routes/suggestions.js +7 -0
- package/dist/transport/web/routes/suggestions.js.map +1 -0
- package/dist/transport/web/routes/todo.js +7 -0
- package/dist/transport/web/routes/todo.js.map +1 -0
- package/dist/transport/web/routes/version.js +5 -0
- package/dist/transport/web/routes/version.js.map +1 -0
- package/dist/transport/web/routes/workspaces.js +7 -0
- package/dist/transport/web/routes/workspaces.js.map +1 -0
- package/dist/transport/web/server.js +111 -0
- package/dist/transport/web/server.js.map +1 -0
- package/dist/transport/web/session-summary.js +46 -0
- package/dist/transport/web/session-summary.js.map +1 -0
- package/dist/transport/web/ws-hub.js +83 -0
- package/dist/transport/web/ws-hub.js.map +1 -0
- package/dist/utils/logger.js +105 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/markdown.js +129 -0
- package/dist/utils/markdown.js.map +1 -0
- package/dist/utils/paths.js +18 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/version.js +44 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +91 -0
- package/web/dist/_app/env.js +1 -0
- package/web/dist/_app/immutable/assets/0.DxN3RsuG.css +1 -0
- package/web/dist/_app/immutable/assets/2.BNuGfmZP.css +1 -0
- package/web/dist/_app/immutable/assets/3.CTDprntu.css +1 -0
- package/web/dist/_app/immutable/chunks/BUpwHpMJ.js +1 -0
- package/web/dist/_app/immutable/chunks/BjY4dxcB.js +2 -0
- package/web/dist/_app/immutable/chunks/C2FuqD3s.js +1 -0
- package/web/dist/_app/immutable/chunks/CUHGq08X.js +2 -0
- package/web/dist/_app/immutable/chunks/CWj6FrbW.js +1 -0
- package/web/dist/_app/immutable/chunks/ClvoqtGj.js +1 -0
- package/web/dist/_app/immutable/chunks/DIEDQ_hk.js +1 -0
- package/web/dist/_app/immutable/entry/app.BoRpcVMj.js +2 -0
- package/web/dist/_app/immutable/entry/start.Cj-PQNTq.js +1 -0
- package/web/dist/_app/immutable/nodes/0.y9YEms5p.js +3 -0
- package/web/dist/_app/immutable/nodes/1.CPhhiRM2.js +1 -0
- package/web/dist/_app/immutable/nodes/2.B_c84Mc9.js +1 -0
- package/web/dist/_app/immutable/nodes/3.ClTd0J3D.js +64 -0
- package/web/dist/_app/version.json +1 -0
- package/web/dist/apple-touch-icon.png +0 -0
- package/web/dist/favicon.png +0 -0
- package/web/dist/favicon.svg +17 -0
- package/web/dist/icon-192.png +0 -0
- package/web/dist/icon-512-maskable.png +0 -0
- package/web/dist/icon-512.png +0 -0
- package/web/dist/index.html +73 -0
- package/web/dist/manifest.webmanifest +28 -0
- package/web/dist/service-worker.js +1 -0
package/dist/cli/host.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone host — runs OCRC against a spawned ACP agent (kimi/gemini/…) with NO
|
|
3
|
+
* opencode. This is the parallel composition root to src/plugin/entry.ts: same
|
|
4
|
+
* relay + Telegram + Web transports, but the backend is an AcpBackend and events
|
|
5
|
+
* arrive via `backend.onEvent` (the backend owns its stream) instead of the
|
|
6
|
+
* opencode plugin `event` hook. See docs/ACP_BACKEND_DESIGN.md (Phase 2).
|
|
7
|
+
*
|
|
8
|
+
* Launch: ocrc host (reads .env: TELEGRAM_BOT_TOKEN, ALLOWED_USER_IDS,
|
|
9
|
+
* WEB_*, OCRC_ACP_CMD="kimi acp", …)
|
|
10
|
+
*/
|
|
11
|
+
import { loadPluginConfig } from '../plugin/config.js';
|
|
12
|
+
import { createFileBackedState } from '../core/state.js';
|
|
13
|
+
import { createCardBus } from '../core/card-bus.js';
|
|
14
|
+
import { createRelay } from '../core/relay.js';
|
|
15
|
+
import { startPushNotifications } from '../core/push.js';
|
|
16
|
+
import { createBackendRegistry } from '../core/agent/registry.js';
|
|
17
|
+
import { createAcpStore } from '../core/agent/acp-store.js';
|
|
18
|
+
import { buildHostBackends, parseBackendsSpec } from './host-backends.js';
|
|
19
|
+
import { dirname, join } from 'node:path';
|
|
20
|
+
// (AgentEvent wiring now lives in host-backends.ts)
|
|
21
|
+
import { createTelegramTransport } from '../transport/telegram/index.js';
|
|
22
|
+
import { createWebTransport } from '../transport/web/index.js';
|
|
23
|
+
import { selectAuthStrategy } from '../connectivity/auth/select.js';
|
|
24
|
+
import { createLogger } from '../utils/logger.js';
|
|
25
|
+
const log = createLogger('acp-host');
|
|
26
|
+
export async function main() {
|
|
27
|
+
// Keep the long-lived services alive through stray rejections (mirrors entry.ts).
|
|
28
|
+
process.on('unhandledRejection', (r) => log.warn(`unhandledRejection absorbed: ${r?.stack ?? String(r)}`));
|
|
29
|
+
process.on('uncaughtException', (e) => log.warn(`uncaughtException absorbed: ${e?.stack ?? String(e)}`));
|
|
30
|
+
const config = loadPluginConfig(undefined, { requireTelegram: false });
|
|
31
|
+
const specs = parseBackendsSpec(config.backends, config.acpCommand);
|
|
32
|
+
const telegramEnabled = !!config.telegramBotToken;
|
|
33
|
+
if (!telegramEnabled && !config.webEnabled) {
|
|
34
|
+
throw new Error('ACP host: nothing to serve — set TELEGRAM_BOT_TOKEN and/or WEB_ENABLED=true');
|
|
35
|
+
}
|
|
36
|
+
log.info(`standalone host starting — backends=[${specs.map((s) => s.id).join(', ')}], telegram=${telegramEnabled}, web=${config.webEnabled}, port=${config.webPort}`);
|
|
37
|
+
const state = createFileBackedState(config.statePath);
|
|
38
|
+
const cardBus = createCardBus();
|
|
39
|
+
// Late-bound so the permission bridge below can reach the Telegram transport
|
|
40
|
+
// (which itself needs `backend`, which needs `onPermission` — a construction cycle).
|
|
41
|
+
// Undefined in web-only mode (no Telegram token).
|
|
42
|
+
let tgTransport;
|
|
43
|
+
// ACP permission bridge → the SAME approve/deny UX as opencode permissions.
|
|
44
|
+
// `handlePluginPermissionEvent` sends the Telegram inline buttons AND publishes
|
|
45
|
+
// the Web approval card; both surfaces route the user's decision to
|
|
46
|
+
// `backend.resolvePermission(sessionId, toolCallId, decision)`, which the
|
|
47
|
+
// AcpBackend maps to the ACP optionId. We surface the request, then wait for
|
|
48
|
+
// that decision — with a timeout so an unanswered prompt cancels the tool call
|
|
49
|
+
// instead of hanging the turn.
|
|
50
|
+
//
|
|
51
|
+
// OCRC_ACP_AUTO_APPROVE=true bypasses the prompt and approves once (unattended
|
|
52
|
+
// use). Default is interactive approval.
|
|
53
|
+
const autoApprove = process.env.OCRC_ACP_AUTO_APPROVE === 'true';
|
|
54
|
+
const onPermission = async (req) => {
|
|
55
|
+
if (autoApprove) {
|
|
56
|
+
const allow = req.options.find((o) => o.kind === 'allow_once') ?? req.options.find((o) => o.kind?.startsWith('allow'));
|
|
57
|
+
log.warn(`auto-approving permission: ${req.title}`);
|
|
58
|
+
return allow?.optionId ?? req.options[0]?.optionId ?? null;
|
|
59
|
+
}
|
|
60
|
+
// Surface the request. With Telegram, handlePluginPermissionEvent sends the
|
|
61
|
+
// inline buttons AND publishes the Web approval card; web-only mode publishes
|
|
62
|
+
// the card directly. Either way the user's decision routes to resolvePermission.
|
|
63
|
+
if (tgTransport) {
|
|
64
|
+
tgTransport
|
|
65
|
+
.handlePluginPermissionEvent({
|
|
66
|
+
type: 'permission.asked',
|
|
67
|
+
properties: { id: req.requestId, sessionID: req.sessionId, title: req.title },
|
|
68
|
+
})
|
|
69
|
+
.catch((err) => log.error('failed to surface permission', err));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
cardBus.publish({ kind: 'approval', sessionId: req.sessionId, title: req.title, args: { options: req.options }, requestId: req.requestId });
|
|
73
|
+
}
|
|
74
|
+
// Resolution arrives out-of-band via backend.resolvePermission (Telegram
|
|
75
|
+
// button callback / Web POST /api/approval). Here we only enforce a timeout.
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
setTimeout(() => resolve(null), config.chatTimeoutMs);
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
// Persistent ACP session+history store (next to the state file) so kimi
|
|
81
|
+
// sessions survive restarts and reopen with their history, like opencode.
|
|
82
|
+
const acpStore = createAcpStore(join(dirname(config.statePath), 'acp-sessions.json'));
|
|
83
|
+
// Build every backend (spawning opencode server(s) + ACP agents) and wire each
|
|
84
|
+
// one's event source to the relay below.
|
|
85
|
+
const built = await buildHostBackends(specs, { cwd: process.cwd(), onAcpPermission: onPermission, store: acpStore });
|
|
86
|
+
const registry = createBackendRegistry({
|
|
87
|
+
backends: built.backends,
|
|
88
|
+
state,
|
|
89
|
+
primaryId: built.backends.find((b) => b.id === 'opencode')?.id,
|
|
90
|
+
});
|
|
91
|
+
const relay = createRelay({
|
|
92
|
+
cardBus,
|
|
93
|
+
registry,
|
|
94
|
+
state,
|
|
95
|
+
chatTimeoutMs: config.chatTimeoutMs,
|
|
96
|
+
tuiVisible: false, // no local TUI in standalone mode
|
|
97
|
+
});
|
|
98
|
+
// Persist finalized conversation cards for ACP sessions (recordCard no-ops for
|
|
99
|
+
// opencode sessions, which aren't in the store) so they reopen with history.
|
|
100
|
+
cardBus.subscribeAll((card) => {
|
|
101
|
+
if ((card.kind === 'user' || card.kind === 'assistant') && 'sessionId' in card && card.sessionId) {
|
|
102
|
+
acpStore.recordCard(card.sessionId, card, Date.now());
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// push needs a backend for the finish-summary history read; the primary backend
|
|
106
|
+
// is a best-effort source (wrong-backend reads for other sessions degrade to no
|
|
107
|
+
// summary, which the caller tolerates).
|
|
108
|
+
const push = startPushNotifications({ cardBus, backend: registry.get(registry.primaryId()), state });
|
|
109
|
+
// opencode permission events arrive on the SSE stream → forward to the same
|
|
110
|
+
// approval UX (Telegram buttons + Web card). Web-only: publish the card directly.
|
|
111
|
+
const onOpencodePermission = (ev) => {
|
|
112
|
+
if (tgTransport) {
|
|
113
|
+
tgTransport.handlePluginPermissionEvent({ type: ev.type, properties: ev.properties })
|
|
114
|
+
.catch((err) => log.error('opencode permission surface failed', err));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const p = ev.properties ?? {};
|
|
118
|
+
if (ev.type === 'permission.asked' && p.id && p.sessionID) {
|
|
119
|
+
cardBus.publish({ kind: 'approval', sessionId: p.sessionID, title: p.title ?? 'Permission', args: p.args ?? {}, requestId: p.id });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const disposeBackends = built.wire(relay, push, onOpencodePermission);
|
|
124
|
+
const transports = [];
|
|
125
|
+
if (telegramEnabled) {
|
|
126
|
+
tgTransport = createTelegramTransport({
|
|
127
|
+
token: config.telegramBotToken,
|
|
128
|
+
allowedUserIds: config.allowedUserIds,
|
|
129
|
+
// Telegram is single-backend for now (piece 6 migrates it to the registry):
|
|
130
|
+
// it drives the primary backend / pinned session.
|
|
131
|
+
backend: registry.get(registry.primaryId()),
|
|
132
|
+
state,
|
|
133
|
+
baseUrl: '',
|
|
134
|
+
tgChunkSoftLimit: config.tgChunkSoftLimit,
|
|
135
|
+
});
|
|
136
|
+
tgTransport.onMessage(relay);
|
|
137
|
+
transports.push(tgTransport);
|
|
138
|
+
}
|
|
139
|
+
if (config.webEnabled) {
|
|
140
|
+
const auth = selectAuthStrategy({
|
|
141
|
+
mode: config.webAuth,
|
|
142
|
+
token: config.webToken,
|
|
143
|
+
devEmail: config.webCfAccessDevEmail,
|
|
144
|
+
devBypass: config.webCfAccessDevBypass,
|
|
145
|
+
host: config.webHost,
|
|
146
|
+
cfAccess: {
|
|
147
|
+
team: config.webCfAccessTeam,
|
|
148
|
+
aud: config.webCfAccessAud,
|
|
149
|
+
devBypass: config.webCfAccessDevBypass,
|
|
150
|
+
devEmail: config.webCfAccessDevEmail,
|
|
151
|
+
host: config.webHost,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
const webTransport = createWebTransport({
|
|
155
|
+
host: config.webHost,
|
|
156
|
+
port: config.webPort,
|
|
157
|
+
registry,
|
|
158
|
+
auth,
|
|
159
|
+
staticRoot: config.webStaticRoot,
|
|
160
|
+
});
|
|
161
|
+
webTransport.onMessage(relay);
|
|
162
|
+
transports.push(webTransport);
|
|
163
|
+
}
|
|
164
|
+
await Promise.all(transports.map((t) => t.start({ cardBus, state })));
|
|
165
|
+
log.info(`${transports.length} transport(s) started; backends=[${registry.list().map((b) => b.id).join(', ')}]`);
|
|
166
|
+
const dispose = async () => {
|
|
167
|
+
log.info('shutting down…');
|
|
168
|
+
push.stop();
|
|
169
|
+
await disposeBackends();
|
|
170
|
+
await Promise.allSettled(transports.map((t) => t.stop()));
|
|
171
|
+
// Flush debounced writes (100ms debounce would otherwise be lost on exit).
|
|
172
|
+
try {
|
|
173
|
+
await state.flush();
|
|
174
|
+
}
|
|
175
|
+
catch { /* best effort */ }
|
|
176
|
+
try {
|
|
177
|
+
await acpStore.flush();
|
|
178
|
+
}
|
|
179
|
+
catch { /* best effort */ }
|
|
180
|
+
process.exit(0);
|
|
181
|
+
};
|
|
182
|
+
process.on('SIGINT', dispose);
|
|
183
|
+
process.on('SIGTERM', dispose);
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/cli/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { writeFileSync, existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { runInitWizard, defaultTestConnection } from './init.js';
|
|
7
|
+
const VERSION = (() => {
|
|
8
|
+
try {
|
|
9
|
+
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), '../../package.json');
|
|
10
|
+
return JSON.parse(readFileSync(pkgPath, 'utf-8')).version;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return 'unknown';
|
|
14
|
+
}
|
|
15
|
+
})();
|
|
16
|
+
const HELP = `
|
|
17
|
+
ocrc v${VERSION} (fork of agentjoey/opencode-remote-control)
|
|
18
|
+
|
|
19
|
+
USAGE:
|
|
20
|
+
ocrc <command>
|
|
21
|
+
|
|
22
|
+
COMMANDS:
|
|
23
|
+
init Interactive setup wizard (writes .env)
|
|
24
|
+
install Install as opencode plugin
|
|
25
|
+
uninstall Remove from opencode plugin config
|
|
26
|
+
pair Show QR + URL to pair a device
|
|
27
|
+
host Run standalone against an ACP agent (no opencode; OCRC_ACP_CMD)
|
|
28
|
+
--help, -h Show this help
|
|
29
|
+
`;
|
|
30
|
+
async function main() {
|
|
31
|
+
const cmd = process.argv[2];
|
|
32
|
+
if (cmd === 'init') {
|
|
33
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
34
|
+
const deps = {
|
|
35
|
+
ask: (q) => new Promise((resolve) => rl.question(q, resolve)),
|
|
36
|
+
writeFile: (p, c) => writeFileSync(p, c),
|
|
37
|
+
exists: (p) => existsSync(p),
|
|
38
|
+
testConnection: defaultTestConnection,
|
|
39
|
+
cwd: process.cwd(),
|
|
40
|
+
};
|
|
41
|
+
await runInitWizard(deps);
|
|
42
|
+
rl.close();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (cmd === 'install') {
|
|
46
|
+
await import('./install.js').then((m) => m.main(process.argv.slice(3)));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (cmd === 'uninstall') {
|
|
50
|
+
await import('./uninstall.js').then((m) => m.main());
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (cmd === 'pair') {
|
|
54
|
+
await import('./pair.js').then((m) => m.main());
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (cmd === 'host') {
|
|
58
|
+
await import('./host.js').then((m) => m.main());
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
console.log(HELP);
|
|
62
|
+
}
|
|
63
|
+
main().catch((err) => {
|
|
64
|
+
console.error(err);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline';
|
|
2
|
+
import { writeFileSync, existsSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
export async function runInitWizard(deps) {
|
|
5
|
+
console.log('🤖 opencode-remote-control setup wizard\n');
|
|
6
|
+
console.log('Get your Telegram bot token from @BotFather.');
|
|
7
|
+
console.log('Find your Telegram user ID by messaging @userinfobot.\n');
|
|
8
|
+
const token = (await deps.ask('Telegram Bot Token: ')).trim();
|
|
9
|
+
if (!token) {
|
|
10
|
+
console.log('❌ Token is required.');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const userId = (await deps.ask('Your Telegram User ID: ')).trim();
|
|
14
|
+
if (!userId || !/^\d+$/.test(userId)) {
|
|
15
|
+
console.log('❌ User ID must be numeric.');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
console.log('\n🔌 Testing connection to Telegram…');
|
|
19
|
+
try {
|
|
20
|
+
await deps.testConnection(token);
|
|
21
|
+
console.log('✅ Bot token is valid.\n');
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
console.log(`❌ Connection failed: ${err.message}`);
|
|
25
|
+
const force = await deps.ask('Continue anyway? (y/N): ');
|
|
26
|
+
if (!force.trim().toLowerCase().startsWith('y')) {
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const envPath = join(deps.cwd, '.env');
|
|
31
|
+
if (deps.exists(envPath)) {
|
|
32
|
+
const overwrite = await deps.ask('.env already exists. Overwrite? (y/N): ');
|
|
33
|
+
if (!overwrite.trim().toLowerCase().startsWith('y')) {
|
|
34
|
+
console.log('Aborted.');
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const lines = [
|
|
39
|
+
`TELEGRAM_BOT_TOKEN=${token}`,
|
|
40
|
+
`ALLOWED_USER_IDS=${userId}`,
|
|
41
|
+
'OPENCODE_BASE_URL=http://localhost:4096',
|
|
42
|
+
];
|
|
43
|
+
deps.writeFile(envPath, lines.join('\n') + '\n');
|
|
44
|
+
console.log(`✅ .env written to ${envPath}\n`);
|
|
45
|
+
console.log('Next steps:');
|
|
46
|
+
console.log(' npm install');
|
|
47
|
+
console.log(' npm run build');
|
|
48
|
+
console.log(' npx opencode-remote-control install');
|
|
49
|
+
}
|
|
50
|
+
export async function defaultTestConnection(token) {
|
|
51
|
+
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
const data = await res.json().catch(() => ({}));
|
|
54
|
+
throw new Error(data.description ?? `HTTP ${res.status}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
58
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
59
|
+
const deps = {
|
|
60
|
+
ask: (q) => new Promise((resolve) => rl.question(q, resolve)),
|
|
61
|
+
writeFile: (p, c) => writeFileSync(p, c),
|
|
62
|
+
exists: (p) => existsSync(p),
|
|
63
|
+
testConnection: defaultTestConnection,
|
|
64
|
+
cwd: process.cwd(),
|
|
65
|
+
};
|
|
66
|
+
runInitWizard(deps).finally(() => rl.close());
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { join, resolve, dirname } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
// Repo root resolved from this module's own location: dist/cli/install.js (or
|
|
7
|
+
// src/cli/install.ts in dev) — two levels below the root.
|
|
8
|
+
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
9
|
+
const OPENCODE_CONFIG_DIR = process.env.OPENCODE_CONFIG_DIR ?? join(homedir(), '.config', 'opencode');
|
|
10
|
+
const PLUGINS_DIR = join(OPENCODE_CONFIG_DIR, 'plugins');
|
|
11
|
+
const BRIDGE_FILE = join(PLUGINS_DIR, 'ocrc.js');
|
|
12
|
+
const PKG_JSON = join(OPENCODE_CONFIG_DIR, 'package.json');
|
|
13
|
+
const GLOBAL_OPENCODE_JSON = join(OPENCODE_CONFIG_DIR, 'opencode.json');
|
|
14
|
+
const ENTRY = join(REPO_ROOT, 'dist', 'plugin', 'entry.js');
|
|
15
|
+
const ENV_FILE = join(REPO_ROOT, '.env');
|
|
16
|
+
const DEFAULT_WEB_PORT = '4099'; // pairs with opencode's own server port 4096
|
|
17
|
+
async function ask(rl, question) {
|
|
18
|
+
return new Promise((res) => rl.question(question, res));
|
|
19
|
+
}
|
|
20
|
+
/** Read existing .env (if any) into a key→value map, preserving comments isn't needed for upsert. */
|
|
21
|
+
function readEnv() {
|
|
22
|
+
const map = new Map();
|
|
23
|
+
if (!existsSync(ENV_FILE))
|
|
24
|
+
return map;
|
|
25
|
+
for (const line of readFileSync(ENV_FILE, 'utf-8').split('\n')) {
|
|
26
|
+
const m = line.match(/^([A-Z0-9_]+)=(.*)$/);
|
|
27
|
+
if (m)
|
|
28
|
+
map.set(m[1], m[2]);
|
|
29
|
+
}
|
|
30
|
+
return map;
|
|
31
|
+
}
|
|
32
|
+
/** Upsert keys into .env, preserving existing keys/comments not being changed. */
|
|
33
|
+
function upsertEnv(updates) {
|
|
34
|
+
const lines = existsSync(ENV_FILE) ? readFileSync(ENV_FILE, 'utf-8').split('\n') : [];
|
|
35
|
+
const remaining = { ...updates };
|
|
36
|
+
const out = lines.map((line) => {
|
|
37
|
+
const m = line.match(/^([A-Z0-9_]+)=/);
|
|
38
|
+
if (m && m[1] in remaining) {
|
|
39
|
+
const v = remaining[m[1]];
|
|
40
|
+
delete remaining[m[1]];
|
|
41
|
+
return `${m[1]}=${v}`;
|
|
42
|
+
}
|
|
43
|
+
return line;
|
|
44
|
+
});
|
|
45
|
+
for (const [k, v] of Object.entries(remaining))
|
|
46
|
+
out.push(`${k}=${v}`);
|
|
47
|
+
// Contains the bot token — owner-only, like the web token file (token.ts).
|
|
48
|
+
writeFileSync(ENV_FILE, out.join('\n').replace(/\n*$/, '\n'), { mode: 0o600 });
|
|
49
|
+
try {
|
|
50
|
+
// mode only applies at creation; tighten permissions of a pre-existing file too.
|
|
51
|
+
chmodSync(ENV_FILE, 0o600);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* best effort */
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Create the ~/.config/opencode/plugins/ bridge that re-invokes our built plugin. */
|
|
58
|
+
function writeBridge() {
|
|
59
|
+
mkdirSync(PLUGINS_DIR, { recursive: true });
|
|
60
|
+
// Upgrade hygiene: a pre-fork install leaves an `opencode-remote-control.js`
|
|
61
|
+
// bridge behind. opencode would load BOTH bridges in one process — two
|
|
62
|
+
// elections, two web binds (one silently failing), two Telegram pollers
|
|
63
|
+
// (409 conflicts). Remove it when installing the fork bridge.
|
|
64
|
+
const legacyBridge = join(PLUGINS_DIR, 'opencode-remote-control.js');
|
|
65
|
+
try {
|
|
66
|
+
if (existsSync(legacyBridge) && legacyBridge !== BRIDGE_FILE) {
|
|
67
|
+
unlinkSync(legacyBridge);
|
|
68
|
+
console.log(` Removed legacy bridge → ${legacyBridge}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch { /* best effort */ }
|
|
72
|
+
writeFileSync(BRIDGE_FILE, `// Auto-generated by ocrc install.
|
|
73
|
+
// opencode 1.17 loads local plugins from ~/.config/opencode/plugins/ and only
|
|
74
|
+
// invokes functions DEFINED in the loaded module (re-exports are imported but
|
|
75
|
+
// never called), so we wrap the built plugin in a locally-defined function.
|
|
76
|
+
// The repo's dist stays the source of truth — rebuild dist + restart opencode
|
|
77
|
+
// to pick up changes.
|
|
78
|
+
//
|
|
79
|
+
// Dual-host default export (verified on V1.18.32 + V2.0.15):
|
|
80
|
+
// - V1 hosts call .server(ctx, options) — the classic plugin function.
|
|
81
|
+
// - V2 hosts call .setup(ctx) — and REQUIRE the default export to be an
|
|
82
|
+
// OBJECT ({id, setup}); a bare function default is silently skipped by V2.
|
|
83
|
+
// Hence the object shape here, with the callable form preserved as .server.
|
|
84
|
+
import plugin from ${JSON.stringify(ENTRY)}
|
|
85
|
+
|
|
86
|
+
const callable = typeof plugin === 'function' ? plugin : (plugin.server ?? plugin.setup ?? plugin)
|
|
87
|
+
export const opencodeRemoteControl = async (ctx) => callable(ctx, undefined)
|
|
88
|
+
export const setup = plugin.setup
|
|
89
|
+
export default {
|
|
90
|
+
id: 'ocrc',
|
|
91
|
+
server: async (ctx, options) => callable(ctx, options),
|
|
92
|
+
setup: plugin.setup,
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
// Ensure the bare .js bridge is parsed as ESM.
|
|
96
|
+
let pkg = {};
|
|
97
|
+
if (existsSync(PKG_JSON)) {
|
|
98
|
+
try {
|
|
99
|
+
pkg = JSON.parse(readFileSync(PKG_JSON, 'utf-8'));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
pkg = {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (pkg.type !== 'module') {
|
|
106
|
+
pkg.type = 'module';
|
|
107
|
+
writeFileSync(PKG_JSON, JSON.stringify(pkg, null, 2) + '\n');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Remove the legacy directory-path plugin entry from opencode.json (1.16 and earlier). */
|
|
111
|
+
function migrateLegacyConfig() {
|
|
112
|
+
if (!existsSync(GLOBAL_OPENCODE_JSON))
|
|
113
|
+
return false;
|
|
114
|
+
let config;
|
|
115
|
+
try {
|
|
116
|
+
config = JSON.parse(readFileSync(GLOBAL_OPENCODE_JSON, 'utf-8'));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const plugins = config.plugin ?? [];
|
|
122
|
+
const isLegacy = (e) => {
|
|
123
|
+
const name = Array.isArray(e) ? e[0] : e;
|
|
124
|
+
return name === REPO_ROOT || name === 'opencode-remote-control@latest' || /opencode-remote-control$/.test(name);
|
|
125
|
+
};
|
|
126
|
+
const filtered = plugins.filter((e) => !isLegacy(e));
|
|
127
|
+
if (filtered.length === plugins.length)
|
|
128
|
+
return false;
|
|
129
|
+
config.plugin = filtered;
|
|
130
|
+
writeFileSync(GLOBAL_OPENCODE_JSON, JSON.stringify(config, null, 2) + '\n');
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
export async function runInstall(options) {
|
|
134
|
+
console.log(`\nInstalling ocrc for opencode 1.17+...\n`);
|
|
135
|
+
console.log(` Repo: ${REPO_ROOT}`);
|
|
136
|
+
console.log(` Bridge: ${BRIDGE_FILE}`);
|
|
137
|
+
console.log(` Env: ${ENV_FILE}`);
|
|
138
|
+
if (!existsSync(ENTRY)) {
|
|
139
|
+
console.error(`\n dist not built: ${ENTRY} is missing. Run \`npm run build\` first.`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const env = readEnv();
|
|
143
|
+
let token = env.get('TELEGRAM_BOT_TOKEN') ?? process.env.TELEGRAM_BOT_TOKEN ?? '';
|
|
144
|
+
let ids = env.get('ALLOWED_USER_IDS') ?? process.env.ALLOWED_USER_IDS ?? '';
|
|
145
|
+
let web = env.get('WEB_ENABLED') ?? process.env.WEB_ENABLED ?? 'true';
|
|
146
|
+
let port = env.get('OCRC_WEB_PORT') ?? env.get('WEB_PORT') ?? DEFAULT_WEB_PORT;
|
|
147
|
+
if (!options.yes) {
|
|
148
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
149
|
+
console.log('\n--- Configuration ---');
|
|
150
|
+
token = (await ask(rl, `TELEGRAM_BOT_TOKEN [${token ? '***' : 'required'}]: `)).trim() || token;
|
|
151
|
+
ids = (await ask(rl, `ALLOWED_USER_IDS (comma-separated) [${ids || 'required'}]: `)).trim() || ids;
|
|
152
|
+
web = (await ask(rl, `Enable Web PWA? (true/false) [${web}]: `)).trim() || web;
|
|
153
|
+
port = (await ask(rl, `Web port (opencode itself uses 7081) [${port}]: `)).trim() || port;
|
|
154
|
+
rl.close();
|
|
155
|
+
}
|
|
156
|
+
if (!token) {
|
|
157
|
+
console.error('TELEGRAM_BOT_TOKEN is required.');
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
if (!ids) {
|
|
161
|
+
console.error('ALLOWED_USER_IDS is required.');
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
upsertEnv({
|
|
165
|
+
TELEGRAM_BOT_TOKEN: token,
|
|
166
|
+
ALLOWED_USER_IDS: ids,
|
|
167
|
+
OCRC_WEB_ENABLED: web,
|
|
168
|
+
OCRC_WEB_PORT: port,
|
|
169
|
+
});
|
|
170
|
+
console.log(`\n Wrote config to ${ENV_FILE}`);
|
|
171
|
+
writeBridge();
|
|
172
|
+
console.log(` Installed plugin bridge → ${BRIDGE_FILE}`);
|
|
173
|
+
if (migrateLegacyConfig()) {
|
|
174
|
+
console.log(` Removed legacy directory-path plugin entry from ${GLOBAL_OPENCODE_JSON}`);
|
|
175
|
+
}
|
|
176
|
+
console.log(`\nInstallation complete!`);
|
|
177
|
+
console.log(`\nNext steps:`);
|
|
178
|
+
console.log(` 1. Run \`opencode\` from any directory — the plugin loads globally.`);
|
|
179
|
+
console.log(` Tip: for an always-on hub, run it from a small/empty dir so the`);
|
|
180
|
+
console.log(` file watcher stays fast. Multiple instances elect one PRIMARY.`);
|
|
181
|
+
console.log(` 2. Send "hello" in Telegram to confirm the bot responds.`);
|
|
182
|
+
console.log(` 3. For the Web PWA: \`ocrc pair\` (or /pair in Telegram) → open the`);
|
|
183
|
+
console.log(` URL/QR. To reach it from another device, expose http://localhost:${port}`);
|
|
184
|
+
console.log(` over a tunnel or VPN (e.g. \`tailscale serve ${port}\`).`);
|
|
185
|
+
}
|
|
186
|
+
export async function main(args = process.argv.slice(2)) {
|
|
187
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
188
|
+
console.log(`
|
|
189
|
+
opencode-remote-control install (opencode 1.17+)
|
|
190
|
+
|
|
191
|
+
USAGE:
|
|
192
|
+
npm run build && node dist/cli/install.js [OPTIONS]
|
|
193
|
+
|
|
194
|
+
OPTIONS:
|
|
195
|
+
--yes, -y Skip interactive prompts (uses existing .env / env vars)
|
|
196
|
+
--help, -h Show this help
|
|
197
|
+
|
|
198
|
+
WHAT IT DOES:
|
|
199
|
+
1. Writes a plugin bridge to ~/.config/opencode/plugins/ (1.17 loads local
|
|
200
|
+
plugins from there; directory paths in opencode.json no longer work)
|
|
201
|
+
2. Ensures ~/.config/opencode/package.json has "type": "module"
|
|
202
|
+
3. Saves TELEGRAM_BOT_TOKEN / ALLOWED_USER_IDS / OCRC_WEB_ENABLED / OCRC_WEB_PORT to the
|
|
203
|
+
repo's .env (1.17 plugins receive no options object, so config lives in .env)
|
|
204
|
+
4. Removes any legacy directory-path plugin entry from opencode.json
|
|
205
|
+
|
|
206
|
+
NOTES:
|
|
207
|
+
- Default web port is ${DEFAULT_WEB_PORT} (opencode's own server occupies 7081).
|
|
208
|
+
- The bridge re-invokes the built dist, so rebuild dist + restart to update.
|
|
209
|
+
`);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
await runInstall({ yes: args.includes('--yes') || args.includes('-y') });
|
|
213
|
+
}
|
|
214
|
+
if (process.argv[1]?.endsWith('install.js') || process.argv[1]?.endsWith('install.ts')) {
|
|
215
|
+
main().catch((err) => {
|
|
216
|
+
console.error(err);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/cli/install.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/pair.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { buildPairCard, buildPairContext } from '../connectivity/pairing.js';
|
|
2
|
+
export async function main() {
|
|
3
|
+
const { token, url } = await buildPairContext();
|
|
4
|
+
const card = await buildPairCard(url, token);
|
|
5
|
+
console.log(card.qr);
|
|
6
|
+
console.log(card.lines.join('\n'));
|
|
7
|
+
}
|
|
8
|
+
if (process.argv[1]?.endsWith('pair.js') || process.argv[1]?.endsWith('pair.ts')) {
|
|
9
|
+
main().catch((err) => { console.error(err); process.exit(1); });
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=pair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pair.js","sourceRoot":"","sources":["../../src/cli/pair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAE5E,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,gBAAgB,EAAE,CAAA;IAC/C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC5C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACpB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AACpC,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;IACjF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;AAChE,CAAC"}
|