appback-remoteagent 0.13.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 (46) hide show
  1. package/.env.example +39 -0
  2. package/LICENSE +21 -0
  3. package/README.md +371 -0
  4. package/bin/remoteagent.js +2 -0
  5. package/dist/adapters/claude-adapter.js +78 -0
  6. package/dist/adapters/codex-adapter.js +241 -0
  7. package/dist/adapters/provider-adapter.js +1 -0
  8. package/dist/adapters/shell-adapter.js +44 -0
  9. package/dist/adapters/windows-shell.js +111 -0
  10. package/dist/bot.js +2135 -0
  11. package/dist/config.js +170 -0
  12. package/dist/index.js +534 -0
  13. package/dist/secret-helper.js +24 -0
  14. package/dist/services/agent-memory-service.js +737 -0
  15. package/dist/services/bot-management-service.js +626 -0
  16. package/dist/services/bridge-service.js +807 -0
  17. package/dist/services/local-ui-service.js +533 -0
  18. package/dist/services/provider-setup-service.js +284 -0
  19. package/dist/services/remote-shell-service.js +97 -0
  20. package/dist/store/file-store.js +690 -0
  21. package/dist/telegram-fetch.js +85 -0
  22. package/dist/types.js +1 -0
  23. package/docs/ARCHITECTURE.md +170 -0
  24. package/docs/COKACDIR_NOTES.md +79 -0
  25. package/docs/ERROR_NORMALIZATION.md +46 -0
  26. package/docs/MINI_APP.md +112 -0
  27. package/docs/MVP.md +108 -0
  28. package/docs/OPERATIONS.md +181 -0
  29. package/docs/RELEASING.md +87 -0
  30. package/docs/SESSION_DIRECTORY_PLAN.md +506 -0
  31. package/package.json +47 -0
  32. package/scripts/bump-version.sh +23 -0
  33. package/scripts/finish-claude-login.sh +48 -0
  34. package/scripts/install-claude.sh +6 -0
  35. package/scripts/install-codex.sh +8 -0
  36. package/scripts/install.ps1 +51 -0
  37. package/scripts/install.sh +101 -0
  38. package/scripts/mock-adapter.sh +7 -0
  39. package/scripts/restart-after-bot-op.sh +118 -0
  40. package/scripts/selftest-telegram-update.mjs +359 -0
  41. package/scripts/start-claude-login.sh +4 -0
  42. package/scripts/start.ps1 +39 -0
  43. package/scripts/start.sh +54 -0
  44. package/scripts/stop.ps1 +40 -0
  45. package/scripts/stop.sh +39 -0
  46. package/tsconfig.json +20 -0
@@ -0,0 +1,85 @@
1
+ import http from "node:http";
2
+ import https from "node:https";
3
+ import { URL } from "node:url";
4
+ function normalizeBody(body) {
5
+ if (body == null) {
6
+ return undefined;
7
+ }
8
+ if (typeof body === "string") {
9
+ return Buffer.from(body, "utf8");
10
+ }
11
+ if (body instanceof URLSearchParams) {
12
+ return Buffer.from(body.toString(), "utf8");
13
+ }
14
+ if (Buffer.isBuffer(body)) {
15
+ return body;
16
+ }
17
+ if (ArrayBuffer.isView(body)) {
18
+ return Buffer.from(body.buffer, body.byteOffset, body.byteLength);
19
+ }
20
+ if (body instanceof ArrayBuffer) {
21
+ return Buffer.from(body);
22
+ }
23
+ throw new TypeError("Unsupported fetch body type.");
24
+ }
25
+ export async function telegramFetch(input, init) {
26
+ const target = new URL(typeof input === "string"
27
+ ? input
28
+ : input instanceof URL
29
+ ? input.toString()
30
+ : input.url);
31
+ const requestInit = init ?? {};
32
+ const method = requestInit.method ?? (input instanceof Request ? input.method : "GET");
33
+ const headers = new Headers(input instanceof Request ? input.headers : undefined);
34
+ if (requestInit.headers) {
35
+ const extra = new Headers(requestInit.headers);
36
+ extra.forEach((value, key) => headers.set(key, value));
37
+ }
38
+ const rawBody = requestInit.body ?? (input instanceof Request ? await input.arrayBuffer() : undefined);
39
+ const body = normalizeBody(rawBody);
40
+ if (body && !headers.has("content-length")) {
41
+ headers.set("content-length", String(body.byteLength));
42
+ }
43
+ return await new Promise((resolve, reject) => {
44
+ const client = target.protocol === "http:" ? http : https;
45
+ const req = client.request(target, {
46
+ method,
47
+ headers: Object.fromEntries(headers.entries()),
48
+ }, (res) => {
49
+ const chunks = [];
50
+ res.on("data", (chunk) => {
51
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
52
+ });
53
+ res.on("end", () => {
54
+ const responseHeaders = new Headers();
55
+ for (const [key, value] of Object.entries(res.headers)) {
56
+ if (Array.isArray(value)) {
57
+ responseHeaders.set(key, value.join(", "));
58
+ }
59
+ else if (value !== undefined) {
60
+ responseHeaders.set(key, value);
61
+ }
62
+ }
63
+ resolve(new Response(Buffer.concat(chunks), {
64
+ status: res.statusCode ?? 500,
65
+ statusText: res.statusMessage ?? "",
66
+ headers: responseHeaders,
67
+ }));
68
+ });
69
+ });
70
+ req.on("error", reject);
71
+ if (requestInit.signal) {
72
+ if (requestInit.signal.aborted) {
73
+ req.destroy(new Error("The operation was aborted."));
74
+ return;
75
+ }
76
+ requestInit.signal.addEventListener("abort", () => {
77
+ req.destroy(new Error("The operation was aborted."));
78
+ }, { once: true });
79
+ }
80
+ if (body) {
81
+ req.write(body);
82
+ }
83
+ req.end();
84
+ });
85
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,170 @@
1
+ # Architecture
2
+
3
+ ## Intent
4
+
5
+ RemoteAgent is a personal installable runtime for six primary jobs:
6
+
7
+ 1. Telegram control
8
+ 2. terminal control
9
+ 3. Telegram to Codex session continuity
10
+ 4. Telegram to Claude Code session continuity
11
+ 5. Telegram attachment intake for images, documents, and related files
12
+ 6. Telegram Mini App UI over the same runtime state
13
+
14
+ The runtime machine is the source of truth.
15
+ Telegram is a client of that runtime, not the owner of the session state.
16
+ The Mini App is a richer client of the same runtime, not a separate backend.
17
+
18
+ ## Core principles
19
+
20
+ 1. One owner, one runtime, local control.
21
+ 2. Sessions belong to the local runtime.
22
+ 3. Telegram chat is a remote control surface over those sessions.
23
+ 4. A Telegram Mini App is an optional structured UI over the same sessions.
24
+ 5. Codex and Claude Code are adapters behind a shared local session model.
25
+ 6. Terminal control is gated and attached to runtime-owned session state.
26
+ 7. Telegram attachments are materialized locally before provider routing.
27
+ 8. Process ownership must remain single-instance and deterministic.
28
+
29
+ ## System shape
30
+
31
+ ```text
32
+ Telegram chat client Telegram Mini App UI
33
+ \ /
34
+ \ /
35
+ -> RemoteAgent runtime on the owner machine
36
+ -> session store
37
+ -> chat/session bindings
38
+ -> event logs
39
+ -> attachment store
40
+ -> provider router
41
+ -> owner-only terminal gateway
42
+ -> Codex adapter
43
+ -> Claude Code adapter
44
+ -> future providers
45
+ ```
46
+
47
+ ## Main subsystems
48
+
49
+ ### Telegram control layer
50
+
51
+ Responsibilities:
52
+
53
+ - accept Telegram commands and messages
54
+ - bind chats to runtime sessions
55
+ - expose status/list/switch/reset flows
56
+ - accept attachments and route them to the active session
57
+ - gate privileged commands such as remote shell
58
+
59
+ ### Telegram Mini App layer
60
+
61
+ Responsibilities:
62
+
63
+ - present the same sessions in a richer UI
64
+ - expose session lists, status, logs, and actions without relying on raw slash commands
65
+ - submit structured actions back to the runtime server
66
+ - stay thin: no provider execution, no separate session source of truth
67
+
68
+ ### Session layer
69
+
70
+ Responsibilities:
71
+
72
+ - own RemoteAgent session ids
73
+ - persist workspace metadata
74
+ - track provider bindings
75
+ - record append-only event history
76
+ - serialize work per session when needed
77
+
78
+ ### Provider adapter layer
79
+
80
+ Responsibilities:
81
+
82
+ - start or continue provider sessions
83
+ - translate runtime requests into provider-specific commands
84
+ - store provider session identifiers such as Codex `thread_id` and Claude `session_id`
85
+ - return normalized outputs back to the runtime
86
+
87
+ ### Terminal control layer
88
+
89
+ Responsibilities:
90
+
91
+ - execute owner-only shell commands in the active workspace
92
+ - enforce private-chat and owner-only restrictions
93
+ - keep terminal access tied to Codex danger-full-access mode
94
+
95
+ ### Attachment layer
96
+
97
+ Responsibilities:
98
+
99
+ - download Telegram-hosted files
100
+ - store them under runtime-owned local paths
101
+ - build attachment prompts for the active provider flow
102
+ - keep internal runtime paths out of user-facing responses where possible
103
+
104
+ ## Provider support today
105
+
106
+ | Provider | Current state | Resume identifier | Notes |
107
+ | --- | --- | --- | --- |
108
+ | Codex | Implemented | `thread_id` | Supports Telegram sandbox control and remote-shell gating |
109
+ | Claude Code | Implemented | `session_id` | Supports attach/resume through the same runtime model |
110
+ | OpenClaw | Planned | TBD | Not yet implemented |
111
+
112
+ ## Mini App role
113
+
114
+ The Mini App should be treated as a control-plane UI for an already-installed runtime.
115
+
116
+ It is not:
117
+
118
+ - a replacement for the runtime server
119
+ - a hosted multi-tenant backend
120
+ - a place where provider CLIs run directly
121
+
122
+ It is:
123
+
124
+ - a Telegram-native web UI
125
+ - an easier way to view and manage sessions
126
+ - a better surface for logs, buttons, state, and attachments
127
+ - a future replacement for some slash-command-heavy workflows
128
+
129
+ ## Operational constraints
130
+
131
+ The runtime must behave as a single owned process.
132
+
133
+ That means:
134
+
135
+ - `systemd` owns the production runtime on server 30
136
+ - ad hoc duplicate `node dist/index.js` processes must not coexist
137
+ - stale PID and stale lock state must not become the effective source of truth
138
+ - image and attachment incidents must be debugged against one live process generation, not many
139
+
140
+ The production operating rules are documented in [OPERATIONS.md](./OPERATIONS.md).
141
+
142
+ ## Current status
143
+
144
+ Stable today:
145
+
146
+ - Telegram control
147
+ - owner-only terminal control
148
+ - Telegram <-> Codex session handling
149
+ - Telegram <-> Claude Code session handling
150
+ - Telegram attachment download and local materialization
151
+ - single-instance runtime locking on server 30
152
+
153
+ Planned next:
154
+
155
+ - Telegram Mini App UI over existing runtime state
156
+ - structured session controls in Telegram beyond slash commands
157
+ - richer attachment and log inspection UX
158
+
159
+ Still improving:
160
+
161
+ - attachment response policy and user-facing output quality
162
+ - broader inspection and debugging UX
163
+ - future local PC chat UI maturity
164
+
165
+ ## Non-goals
166
+
167
+ - hosted multi-tenant control plane
168
+ - account pooling or resale
169
+ - pretending RemoteAgent is the official Codex or Claude desktop product
170
+ - treating Telegram itself as the execution backend
@@ -0,0 +1,79 @@
1
+ # COKACDIR Notes
2
+
3
+ ## What was referenced
4
+
5
+ `cokacdir` was used as a reference point for product shape, not as a codebase to mirror exactly.
6
+
7
+ The useful high-level ideas are:
8
+
9
+ - installable owner-run runtime
10
+ - Telegram as a remote control surface for an existing coding agent
11
+ - no separate hosted AI backend required
12
+ - local session persistence
13
+ - strong operator tooling around logs, processes, and files
14
+
15
+ ## What `cokacdir` appears to optimize for
16
+
17
+ From its public README and local repository layout, `cokacdir` is broader than RemoteAgent.
18
+ It combines:
19
+
20
+ - Telegram bot control
21
+ - multi-provider execution
22
+ - terminal/file manager style tooling
23
+ - process management
24
+ - SSH/SFTP and other power-user utilities
25
+ - a larger installable desktop/runtime surface
26
+
27
+ That is a different product envelope from RemoteAgent.
28
+
29
+ ## What RemoteAgent should borrow
30
+
31
+ The main lessons worth borrowing are operational, not cosmetic:
32
+
33
+ 1. one installable runtime per owner
34
+ 2. stable local state directories
35
+ 3. explicit environment-driven configuration
36
+ 4. practical operator commands for logs, status, and process control
37
+ 5. Telegram as a client of the runtime, not the source of truth
38
+
39
+ ## What RemoteAgent should not copy blindly
40
+
41
+ RemoteAgent is intentionally narrower.
42
+ It should not drift into a giant terminal/file-manager product just because `cokacdir` supports that.
43
+
44
+ RemoteAgent should stay focused on:
45
+
46
+ - personal session runtime
47
+ - Codex/Claude style provider adapters
48
+ - Telegram and future local chat UI over the same session model
49
+ - predictable session/workspace ownership
50
+ - safe process lifecycle
51
+
52
+ ## Key difference in current implementation
53
+
54
+ A critical design decision for RemoteAgent is:
55
+
56
+ - server 30 is the canonical runtime for `codex_remoteagent_bot`
57
+ - local machine 21 is separate for `sqream_bot`
58
+ - runtime ownership matters more than chat UX convenience
59
+
60
+ This means RemoteAgent must care deeply about:
61
+
62
+ - which machine owns the provider session
63
+ - where the workspace actually lives
64
+ - where the runtime state is stored
65
+ - which exact process is answering Telegram
66
+
67
+ That last point became important during the image-send incident.
68
+ The bug felt like an attachment bug, but the root problem was that multiple runtime generations could coexist.
69
+
70
+ ## Current conclusion
71
+
72
+ `cokacdir` is a useful reference for the installable Telegram-controlled agent idea.
73
+ But RemoteAgent should keep its own simpler model:
74
+
75
+ ```text
76
+ Telegram/local UI -> single local runtime -> provider adapters -> local sessions/workspaces
77
+ ```
78
+
79
+ The value is continuity across the owner's own machines and sessions, not reproducing every feature from a broader terminal product.
@@ -0,0 +1,46 @@
1
+ # Error Normalization
2
+
3
+ RemoteAgent should never leak raw provider event payloads directly to Telegram users.
4
+
5
+ ## Goals
6
+
7
+ - normalize provider failures into stable user-facing messages
8
+ - classify retryable vs non-retryable failures
9
+ - keep internal details in logs, not in Telegram replies
10
+ - make retry behavior predictable for long-running Telegram sessions
11
+ - tell users when a retryable issue is being retried and when automatic retries stop
12
+
13
+ ## Current retryable classes
14
+
15
+ - `provider.capacity.retryable`
16
+ - example: `Selected model is at capacity`
17
+ - behavior: send a progress-style retry notice, wait, retry automatically
18
+ - `provider.empty_response.retryable`
19
+ - example: provider returned no usable final text after progress
20
+ - behavior: send a progress-style retry notice, wait, retry automatically
21
+ - `provider.timeout.final`
22
+ - example: `Codex timed out after 600s without returning a final reply`
23
+ - behavior: do not retry automatically; explain the exact configured timeout that killed the provider process
24
+
25
+ ## Current terminal behavior
26
+
27
+ When retries are exhausted:
28
+
29
+ - capacity -> say the selected model is at capacity, then ask the user to retry later or switch models
30
+ - empty response -> explain that automatic continuation stopped after repeated empty follow-up replies
31
+
32
+ When a provider process reaches `COMMAND_TIMEOUT_MS`:
33
+
34
+ - report that the provider process exceeded the configured execution timeout
35
+ - do not say only that "response was delayed"
36
+ - do not invent a cause such as context compaction, provider outage, or model quality unless the provider output explicitly says that
37
+ - tell the operator to increase `/option timeout <seconds>` for long-running work
38
+
39
+ ## Maintenance rule
40
+
41
+ When a new provider error shape appears:
42
+
43
+ 1. capture the raw provider output in logs
44
+ 2. add a stable classifier
45
+ 3. map it to a retry policy or a final user-facing message
46
+ 4. keep raw JSON and internal event envelopes out of Telegram replies
@@ -0,0 +1,112 @@
1
+ # Telegram Mini App Plan
2
+
3
+ ## Positioning
4
+
5
+ RemoteAgent should treat a Telegram Mini App as a richer control UI for the same installable runtime.
6
+
7
+ It should not be described as:
8
+
9
+ - a standalone hosted app
10
+ - a replacement for the runtime server
11
+ - a separate agent execution environment
12
+
13
+ It should be described as:
14
+
15
+ - a Telegram-native web UI
16
+ - an optional control plane for the installed runtime
17
+ - a structured companion to the existing Telegram bot chat
18
+
19
+ ## Why it fits RemoteAgent
20
+
21
+ RemoteAgent already has:
22
+
23
+ - Telegram bot identity and chat entry points
24
+ - persisted sessions
25
+ - session switching
26
+ - provider metadata
27
+ - stop and continue controls
28
+ - attachment history
29
+ - event logs
30
+
31
+ A Mini App can expose those features more clearly than raw commands.
32
+
33
+ ## First MVP
34
+
35
+ The first Mini App should focus on runtime visibility and control, not on replacing chat.
36
+
37
+ ### MVP screens
38
+
39
+ 1. Session list
40
+ - public session id
41
+ - provider mode
42
+ - workspace label
43
+ - updated time
44
+
45
+ 2. Session detail
46
+ - current provider
47
+ - model
48
+ - sandbox state
49
+ - workspace path summary
50
+ - provider binding state
51
+
52
+ 3. Activity view
53
+ - recent event log items
54
+ - progress/result/blocked states
55
+ - attachment entries
56
+
57
+ 4. Actions
58
+ - switch session
59
+ - continue
60
+ - stop
61
+ - new session
62
+ - reset binding
63
+
64
+ ## Runtime boundary
65
+
66
+ The Mini App should call runtime-owned APIs.
67
+ It should not directly execute Codex, Claude Code, or shell commands on its own.
68
+
69
+ The runtime remains responsible for:
70
+
71
+ - provider execution
72
+ - session storage
73
+ - authorization
74
+ - attachment download and send
75
+ - error normalization
76
+
77
+ ## Authentication model
78
+
79
+ The Mini App should trust Telegram launch context only as an input signal.
80
+ Runtime-side checks still matter.
81
+
82
+ Expected checks:
83
+
84
+ - Telegram user id matches `TELEGRAM_OWNER_ID` for privileged actions
85
+ - current bot/chat context maps to the expected runtime channel
86
+ - action is valid for the target session
87
+
88
+ ## Suggested rollout
89
+
90
+ ### Phase 1
91
+
92
+ - menu button launches Mini App
93
+ - read-only session list and session detail
94
+ - stop and continue buttons
95
+
96
+ ### Phase 2
97
+
98
+ - attachment history
99
+ - structured model selection
100
+ - better progress log browsing
101
+
102
+ ### Phase 3
103
+
104
+ - richer batch composition
105
+ - per-session settings views
106
+ - safer admin flows for bot/runtime management
107
+
108
+ ## Non-goals
109
+
110
+ - replacing Telegram chat entirely
111
+ - multi-user SaaS dashboard
112
+ - separate hosted control plane detached from the runtime machine
package/docs/MVP.md ADDED
@@ -0,0 +1,108 @@
1
+ # MVP
2
+
3
+ ## Objective
4
+
5
+ The MVP is a usable personal runtime that proves five things together:
6
+
7
+ 1. Telegram can control the runtime
8
+ 2. the owner can use terminal control safely
9
+ 3. Telegram can continue Codex work
10
+ 4. Telegram can continue Claude Code work
11
+ 5. Telegram can pass images and documents into the active session flow
12
+
13
+ Success means the owner can work on their machine, continue from Telegram, and return without losing the local runtime context.
14
+
15
+ ## Product boundary
16
+
17
+ This MVP is for:
18
+
19
+ - one owner
20
+ - one installable local runtime
21
+ - personal provider credentials
22
+ - local state only
23
+
24
+ This MVP is not for:
25
+
26
+ - hosted SaaS
27
+ - external users
28
+ - team billing or org management
29
+ - account sharing
30
+
31
+ ## MVP pillars
32
+
33
+ ### 1. Telegram control
34
+
35
+ Minimum requirements:
36
+
37
+ - create or bind a local session from Telegram
38
+ - inspect status
39
+ - switch sessions
40
+ - reset a chat binding
41
+ - send normal Telegram text messages into the active provider session
42
+
43
+ ### 2. Terminal control
44
+
45
+ Minimum requirements:
46
+
47
+ - run shell commands from Telegram
48
+ - keep this owner-only
49
+ - keep this private-chat-only
50
+ - tie dangerous shell access to the current Codex sandbox policy
51
+
52
+ ### 3. Codex integration
53
+
54
+ Minimum requirements:
55
+
56
+ - start a fresh Codex pairing
57
+ - attach to an existing Codex `thread_id`
58
+ - continue the same Codex session across turns
59
+ - keep workspace metadata with the session
60
+
61
+ ### 4. Claude Code integration
62
+
63
+ Minimum requirements:
64
+
65
+ - start a fresh Claude pairing
66
+ - attach to an existing Claude `session_id`
67
+ - continue the same Claude session across turns
68
+ - keep workspace metadata with the session
69
+
70
+ ### 5. Attachment intake
71
+
72
+ Minimum requirements:
73
+
74
+ - accept Telegram photos and supported files
75
+ - materialize them locally in runtime-owned storage
76
+ - route them through the active session flow
77
+ - avoid leaking internal local paths in normal user-facing replies when possible
78
+
79
+ ## Supporting runtime requirements
80
+
81
+ To make the five pillars actually usable, the runtime also needs:
82
+
83
+ - local session persistence
84
+ - provider binding persistence
85
+ - append-only event logs
86
+ - stable runtime-owned session ids
87
+ - deterministic single-instance process ownership
88
+ - recoverable restart behavior
89
+
90
+ ## Acceptance criteria
91
+
92
+ The MVP is done when all of the following are true:
93
+
94
+ 1. Telegram can control a local runtime session reliably.
95
+ 2. Terminal control works under explicit restrictions.
96
+ 3. Codex can be paired or attached from Telegram.
97
+ 4. Claude Code can be paired or attached from Telegram.
98
+ 5. Telegram image/document inputs reach the active session flow.
99
+ 6. Restarts do not create ambiguous multi-process ownership.
100
+ 7. Session state survives process restarts.
101
+
102
+ ## Explicit non-goals
103
+
104
+ - hosted sync service
105
+ - public multi-user bot service
106
+ - account resale
107
+ - exact parity with official desktop apps
108
+ - turning RemoteAgent into a general-purpose terminal file manager