appback-remoteagent 0.15.2 → 0.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bot.js CHANGED
@@ -105,24 +105,18 @@ class AutoContinueController {
105
105
  stopInProgress = new Set();
106
106
  stopDedupUntil = new Map();
107
107
  stopDedupMs = 10_000;
108
- suppressUntil = new Map();
109
- suppressMs = 60_000;
110
108
  constructor(stopGatePath) {
111
109
  this.stopGatePath = stopGatePath;
112
- this.loadStopGates();
110
+ this.clearLegacyStopGates();
113
111
  }
114
112
  requestStop(botId, chatId, sessionId) {
115
113
  for (const key of this.keys(botId, chatId, sessionId)) {
116
114
  this.stops.add(key);
117
- this.suppressUntil.set(key, Date.now() + this.suppressMs);
118
115
  }
119
- this.persistStopGates();
120
116
  }
121
117
  requestSessionStop(sessionId) {
122
118
  const key = this.sessionKey(sessionId);
123
119
  this.stops.add(key);
124
- this.suppressUntil.set(key, Date.now() + this.suppressMs);
125
- this.persistStopGates();
126
120
  }
127
121
  beginStop(botId, chatId, sessionId) {
128
122
  const key = this.primaryKey(botId, chatId, sessionId);
@@ -153,26 +147,6 @@ class AutoContinueController {
153
147
  isStopRequested(botId, chatId, sessionId) {
154
148
  return this.keys(botId, chatId, sessionId).some((key) => this.stops.has(key));
155
149
  }
156
- isSuppressingNewWork(botId, chatId, sessionId) {
157
- for (const key of this.keys(botId, chatId, sessionId)) {
158
- if (this.isSuppressingKey(key)) {
159
- return true;
160
- }
161
- }
162
- return false;
163
- }
164
- isSuppressingKey(key) {
165
- const until = this.suppressUntil.get(key);
166
- if (!until) {
167
- return false;
168
- }
169
- if (Date.now() > until) {
170
- this.suppressUntil.delete(key);
171
- this.persistStopGates();
172
- return false;
173
- }
174
- return true;
175
- }
176
150
  keys(botId, chatId, sessionId) {
177
151
  const keys = [this.chatKey(botId, chatId)];
178
152
  if (sessionId) {
@@ -189,31 +163,12 @@ class AutoContinueController {
189
163
  sessionKey(sessionId) {
190
164
  return `session:${sessionId}`;
191
165
  }
192
- loadStopGates() {
193
- try {
194
- const raw = fsSync.readFileSync(this.stopGatePath, "utf8");
195
- const parsed = JSON.parse(raw);
196
- const now = Date.now();
197
- for (const [key, until] of Object.entries(parsed)) {
198
- if (Number.isFinite(until) && until > now) {
199
- this.suppressUntil.set(key, until);
200
- }
201
- }
202
- }
203
- catch {
204
- // Missing or invalid gate files should not prevent the bot from starting.
205
- }
206
- }
207
- persistStopGates() {
208
- const entries = Object.fromEntries(this.suppressUntil.entries());
166
+ clearLegacyStopGates() {
209
167
  try {
210
- fsSync.mkdirSync(path.dirname(this.stopGatePath), { recursive: true });
211
- const tmpPath = `${this.stopGatePath}.tmp`;
212
- fsSync.writeFileSync(tmpPath, JSON.stringify(entries, null, 2), "utf8");
213
- fsSync.renameSync(tmpPath, this.stopGatePath);
168
+ fsSync.rmSync(this.stopGatePath, { force: true });
214
169
  }
215
170
  catch {
216
- // Stop should still work in memory even if persisting the gate fails.
171
+ // Legacy stop gate cleanup must not prevent the bot from starting.
217
172
  }
218
173
  }
219
174
  }
@@ -878,11 +833,6 @@ ${bridge.formatStatus(mapping)}`);
878
833
  return;
879
834
  }
880
835
  const mapping = await bridge.status(botId, chatId).catch(() => undefined);
881
- if (autoContinue.isSuppressingNewWork(botId, chatId, mapping?.session.sessionId)) {
882
- await bridge.logSystem(botId, chatId, "Telegram message ignored during stop cooldown.");
883
- await reply(ctx, "Stopped. Ignored this message so the previous work does not restart. Send a new message again in a moment to start fresh.");
884
- return;
885
- }
886
836
  if (photo) {
887
837
  const downloaded = await downloadTelegramFile(token, botId, chatId, photo.file_id, "telegram-photo.jpg");
888
838
  await memoryService.recordArtifact({
@@ -179,10 +179,16 @@ export class BotPollingStateService {
179
179
  const state = await this.read();
180
180
  state.updatedAt = new Date().toISOString();
181
181
  const tmpPath = `${this.filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
182
- this.writeInFlight = this.writeInFlight.then(async () => {
182
+ this.writeInFlight = this.writeInFlight.catch(() => undefined).then(async () => {
183
183
  await fs.mkdir(path.dirname(this.filePath), { recursive: true });
184
- await fs.writeFile(tmpPath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
185
- await fs.rename(tmpPath, this.filePath);
184
+ try {
185
+ await fs.writeFile(tmpPath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
186
+ await fs.rename(tmpPath, this.filePath);
187
+ }
188
+ catch (error) {
189
+ await fs.rm(tmpPath, { force: true }).catch(() => undefined);
190
+ throw error;
191
+ }
186
192
  });
187
193
  await this.writeInFlight;
188
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appback-remoteagent",
3
- "version": "0.15.2",
3
+ "version": "0.15.4",
4
4
  "description": "Personal installable session server for continuing local AI work across PC and Telegram",
5
5
  "license": "MIT",
6
6
  "type": "module",