appback-remoteagent 0.15.4 → 0.15.5
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/dist/bot.js +38 -12
- package/docs/OPERATIONS.md +2 -0
- package/docs/RELEASING.md +57 -10
- package/package.json +3 -1
- package/scripts/prepublish-guard.mjs +19 -0
- package/scripts/release-publish.sh +45 -0
package/dist/bot.js
CHANGED
|
@@ -2258,6 +2258,9 @@ print(text)
|
|
|
2258
2258
|
const preview = stdout.trim();
|
|
2259
2259
|
return preview || undefined;
|
|
2260
2260
|
}
|
|
2261
|
+
const TELEGRAM_FILE_DOWNLOAD_ATTEMPTS = 4;
|
|
2262
|
+
const TELEGRAM_FILE_DOWNLOAD_TIMEOUT_SECONDS = 120;
|
|
2263
|
+
const TELEGRAM_FILE_DOWNLOAD_CONNECT_TIMEOUT_SECONDS = 20;
|
|
2261
2264
|
async function downloadTelegramFile(botToken, botId, chatId, fileId, preferredName) {
|
|
2262
2265
|
const file = await callTelegramApi(botToken, "getFile", {
|
|
2263
2266
|
file_id: fileId,
|
|
@@ -2270,20 +2273,43 @@ async function downloadTelegramFile(botToken, botId, chatId, fileId, preferredNa
|
|
|
2270
2273
|
const extension = path.extname(file.file_path) || path.extname(preferredName ?? "") || ".bin";
|
|
2271
2274
|
const basename = path.basename(preferredName ?? file.file_path, path.extname(preferredName ?? file.file_path));
|
|
2272
2275
|
const outputPath = path.join(directory, `${Date.now()}-${safePathSegment(basename)}-${randomUUID()}${extension}`);
|
|
2276
|
+
const partialPath = `${outputPath}.part`;
|
|
2273
2277
|
const fileUrl = new URL(file.file_path, `https://api.telegram.org/file/bot${botToken}/`).toString();
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2278
|
+
let lastError;
|
|
2279
|
+
for (let attempt = 1; attempt <= TELEGRAM_FILE_DOWNLOAD_ATTEMPTS; attempt += 1) {
|
|
2280
|
+
try {
|
|
2281
|
+
const { stderr } = await execFileAsync("curl", [
|
|
2282
|
+
"-fL",
|
|
2283
|
+
"-sS",
|
|
2284
|
+
"--connect-timeout",
|
|
2285
|
+
String(TELEGRAM_FILE_DOWNLOAD_CONNECT_TIMEOUT_SECONDS),
|
|
2286
|
+
"--max-time",
|
|
2287
|
+
String(TELEGRAM_FILE_DOWNLOAD_TIMEOUT_SECONDS),
|
|
2288
|
+
"-C",
|
|
2289
|
+
"-",
|
|
2290
|
+
"-o",
|
|
2291
|
+
partialPath,
|
|
2292
|
+
fileUrl,
|
|
2293
|
+
]);
|
|
2294
|
+
if (stderr?.trim()) {
|
|
2295
|
+
console.error(`curl stderr for Telegram file download: ${stderr.trim()}`);
|
|
2296
|
+
}
|
|
2297
|
+
await fs.rename(partialPath, outputPath);
|
|
2298
|
+
return { path: outputPath };
|
|
2299
|
+
}
|
|
2300
|
+
catch (error) {
|
|
2301
|
+
lastError = error;
|
|
2302
|
+
if (attempt < TELEGRAM_FILE_DOWNLOAD_ATTEMPTS) {
|
|
2303
|
+
const partialSize = await fs.stat(partialPath).then((stat) => stat.size).catch(() => 0);
|
|
2304
|
+
console.error(`Telegram file download attempt ${attempt}/${TELEGRAM_FILE_DOWNLOAD_ATTEMPTS} failed; ` +
|
|
2305
|
+
`retrying with resume from ${partialSize} bytes.`);
|
|
2306
|
+
await sleep(Math.min(5000, attempt * 1000));
|
|
2307
|
+
continue;
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2285
2310
|
}
|
|
2286
|
-
|
|
2311
|
+
await fs.rm(partialPath, { force: true }).catch(() => undefined);
|
|
2312
|
+
throw lastError instanceof Error ? lastError : new Error("Telegram file download failed.");
|
|
2287
2313
|
}
|
|
2288
2314
|
function safePathSegment(value) {
|
|
2289
2315
|
const safe = value.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "");
|
package/docs/OPERATIONS.md
CHANGED
|
@@ -11,6 +11,7 @@ RemoteAgent production is operated from one canonical Git history:
|
|
|
11
11
|
|
|
12
12
|
Do not treat stale server paths or duplicate worktrees as authoritative.
|
|
13
13
|
Code changes should be committed and pushed to `origin/main`, published to npm, and then server 30/26 should be updated from that npm version.
|
|
14
|
+
Installing a local tarball directly on a server is an emergency hotfix only; it is not a completed production release until the same version is published to npm and both targets are reconciled to that npm version.
|
|
14
15
|
|
|
15
16
|
## Product shape in operations
|
|
16
17
|
|
|
@@ -134,6 +135,7 @@ If a temporary branch is unavoidable, merge it back to `main`, push it, and depl
|
|
|
134
135
|
|
|
135
136
|
A task is not done until commit and push both happened.
|
|
136
137
|
A production deployment is not done until server 30 and server 26 are running the published npm version and the runtime path has been verified.
|
|
138
|
+
If npm publish fails with `403`, do not keep retrying or switch to source deployment. Confirm the npm token has publish rights for the unscoped `appback-remoteagent` package, then publish. See `docs/RELEASING.md`.
|
|
137
139
|
|
|
138
140
|
See `docs/RELEASING.md` for the detailed versioning rules.
|
|
139
141
|
|
package/docs/RELEASING.md
CHANGED
|
@@ -28,7 +28,7 @@ A release is only considered complete when all of the following are done in orde
|
|
|
28
28
|
4. Run `npm run build`
|
|
29
29
|
5. Commit the completed work
|
|
30
30
|
6. Push `main` to `origin/main`
|
|
31
|
-
7. Publish `appback-remoteagent@<version>` to npm
|
|
31
|
+
7. Publish `appback-remoteagent@<version>` to npm using a token/account that is proven to have publish rights for this unscoped package
|
|
32
32
|
8. Install that exact npm version on server 30 and server 26
|
|
33
33
|
9. Restart `remoteagent.service` on each target if runtime code changed
|
|
34
34
|
10. Verify the relevant runtime path, logs, or Telegram behavior on each target
|
|
@@ -71,27 +71,74 @@ npm pack
|
|
|
71
71
|
|
|
72
72
|
Use this package-specific path for `appback-remoteagent`.
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Direct `npm publish` is blocked by `prepublishOnly`.
|
|
75
|
+
The only normal publish command is:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm run release:publish
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Do not publish this package with the machine 21 `21token`.
|
|
82
|
+
That token can authenticate as `appbackhub`, but it does not currently have publish rights for the unscoped `appback-remoteagent` package.
|
|
83
|
+
It fails at publish time with:
|
|
75
84
|
|
|
76
85
|
```text
|
|
77
86
|
403 Forbidden - You may not perform that action with these credentials.
|
|
78
87
|
```
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
Before publishing, always verify both identity and package ownership:
|
|
81
90
|
|
|
82
91
|
```bash
|
|
83
|
-
|
|
84
|
-
npm
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
npm whoami
|
|
93
|
+
npm owner ls appback-remoteagent
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Authentication alone is not enough.
|
|
97
|
+
If `npm whoami` works but `npm publish` returns `403`, stop and get a publish-capable npm token instead of retrying with the same token.
|
|
98
|
+
|
|
99
|
+
The guarded registry publish path is:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm run release:publish
|
|
87
103
|
npm view appback-remoteagent version
|
|
88
|
-
ssh au2223@192.168.0.30 'bash -lc "npm view appback-remoteagent version"'
|
|
89
|
-
rm -f appback-remoteagent-$VERSION.tgz
|
|
90
|
-
ssh au2223@192.168.0.30 "rm -f /tmp/appback-remoteagent-$VERSION.tgz"
|
|
91
104
|
```
|
|
92
105
|
|
|
93
106
|
If registry caching briefly returns the previous version after publish, wait a few seconds and rerun `npm view appback-remoteagent version` before installing to servers.
|
|
94
107
|
|
|
108
|
+
## Emergency tarball install
|
|
109
|
+
|
|
110
|
+
An emergency tarball install is allowed only to restore a broken runtime when npm publish is blocked.
|
|
111
|
+
It is not a completed release and must be reported as a temporary hotfix.
|
|
112
|
+
|
|
113
|
+
Rules:
|
|
114
|
+
|
|
115
|
+
- do not call it "npm deployed" or "released"
|
|
116
|
+
- do not delete runtime state
|
|
117
|
+
- do not use source checkout deployment
|
|
118
|
+
- confirm no active provider process is running before restart
|
|
119
|
+
- install the exact local package tarball with `npm install -g /tmp/appback-remoteagent-<version>.tgz`
|
|
120
|
+
- follow up by publishing the same version to npm once a publish-capable token is available
|
|
121
|
+
|
|
122
|
+
Emergency server 30 flow:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
VERSION=0.14.0
|
|
126
|
+
npm pack
|
|
127
|
+
scp appback-remoteagent-$VERSION.tgz au2223@192.168.0.30:/tmp/
|
|
128
|
+
ssh au2223@192.168.0.30 "VERSION=$VERSION bash -s" <<'REMOTE'
|
|
129
|
+
set -euo pipefail
|
|
130
|
+
export PATH="/home/au2223/.local/bin:/home/au2223/.nvm/versions/node/v22.22.0/bin:$PATH"
|
|
131
|
+
pgrep -af 'codex|claude' || true
|
|
132
|
+
npm install -g "/tmp/appback-remoteagent-$VERSION.tgz"
|
|
133
|
+
remoteagent-install
|
|
134
|
+
sudo -n systemctl restart remoteagent
|
|
135
|
+
systemctl is-active remoteagent
|
|
136
|
+
node -p 'require("/home/au2223/.nvm/versions/node/v22.22.0/lib/node_modules/appback-remoteagent/package.json").version'
|
|
137
|
+
journalctl -u remoteagent --since '2 minutes ago' --no-pager
|
|
138
|
+
REMOTE
|
|
139
|
+
rm -f appback-remoteagent-$VERSION.tgz
|
|
140
|
+
```
|
|
141
|
+
|
|
95
142
|
## Target deployment sequence
|
|
96
143
|
|
|
97
144
|
Server 30 uses a systemd service:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appback-remoteagent",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.5",
|
|
4
4
|
"description": "Personal installable session server for continuing local AI work across PC and Telegram",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"check": "tsc --noEmit -p tsconfig.json",
|
|
21
21
|
"selftest:telegram": "npm run build && node scripts/selftest-telegram-update.mjs",
|
|
22
22
|
"prepare": "npm run build",
|
|
23
|
+
"prepublishOnly": "node scripts/prepublish-guard.mjs",
|
|
24
|
+
"release:publish": "bash scripts/release-publish.sh",
|
|
23
25
|
"version:patch": "npm version --no-git-tag-version patch",
|
|
24
26
|
"version:minor": "npm version --no-git-tag-version minor",
|
|
25
27
|
"version:major": "npm version --no-git-tag-version major"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
if (process.env.REMOTEAGENT_PUBLISH_GUARD_OK === "1") {
|
|
4
|
+
process.exit(0);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
console.error([
|
|
8
|
+
"Direct npm publish is blocked for appback-remoteagent.",
|
|
9
|
+
"",
|
|
10
|
+
"Use the documented release path instead:",
|
|
11
|
+
" npm run release:publish",
|
|
12
|
+
"",
|
|
13
|
+
"Reason:",
|
|
14
|
+
"- direct publish has repeatedly used the wrong npm token",
|
|
15
|
+
"- appback-remoteagent must be published only through the guarded script",
|
|
16
|
+
"- emergency tarball installs are not completed releases",
|
|
17
|
+
].join("\n"));
|
|
18
|
+
|
|
19
|
+
process.exit(1);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
cd "$ROOT"
|
|
6
|
+
|
|
7
|
+
PACKAGE_NAME="$(node -p 'require("./package.json").name')"
|
|
8
|
+
VERSION="$(node -p 'require("./package.json").version')"
|
|
9
|
+
|
|
10
|
+
if [[ "$PACKAGE_NAME" != "appback-remoteagent" ]]; then
|
|
11
|
+
echo "Unexpected package name: $PACKAGE_NAME" >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
16
|
+
echo "Working tree is not clean. Commit and push before publishing." >&2
|
|
17
|
+
git status --short >&2
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
echo "Publishing $PACKAGE_NAME@$VERSION"
|
|
22
|
+
echo
|
|
23
|
+
echo "npm identity:"
|
|
24
|
+
npm whoami
|
|
25
|
+
echo
|
|
26
|
+
echo "npm owners:"
|
|
27
|
+
npm owner ls "$PACKAGE_NAME"
|
|
28
|
+
echo
|
|
29
|
+
|
|
30
|
+
npm run check
|
|
31
|
+
npm run build
|
|
32
|
+
|
|
33
|
+
TARBALL="$(npm pack --silent)"
|
|
34
|
+
cleanup() {
|
|
35
|
+
rm -f "$TARBALL"
|
|
36
|
+
}
|
|
37
|
+
trap cleanup EXIT
|
|
38
|
+
|
|
39
|
+
echo
|
|
40
|
+
echo "Publishing tarball: $TARBALL"
|
|
41
|
+
REMOTEAGENT_PUBLISH_GUARD_OK=1 npm publish "$TARBALL" --access public
|
|
42
|
+
|
|
43
|
+
echo
|
|
44
|
+
echo "Verifying registry version:"
|
|
45
|
+
npm view "$PACKAGE_NAME" version
|