zames_pro 2.38.0 → 2.40.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/dist/i18n.js CHANGED
@@ -237,6 +237,10 @@ const CATALOG = {
237
237
  ru: 'Использование: /cron "<мин> <час> <день> <мес> <день недели>" <задача>',
238
238
  en: 'Usage: /cron "<min> <hour> <dom> <month> <dow>" <task>',
239
239
  },
240
+ 'sched.loop_too_short': {
241
+ ru: 'Слишком часто: минимум {min} (троттлинг отправок 15с).',
242
+ en: 'Too frequent: minimum {min} (the send throttle is 15s).',
243
+ },
240
244
  'sched.added': {
241
245
  ru: '⏰ Задача #{id} добавлена ({when}): {task}',
242
246
  en: '⏰ Job #{id} added ({when}): {task}',
package/dist/index.js CHANGED
@@ -18,12 +18,16 @@ import { UndoStore } from './undo.js';
18
18
  import { selfReview, selfDiff, selfApply, selfList } from './self-review.js';
19
19
  import { formatDiff, diffGitArgs, parseTranscript, summarizeTranscript, renderCost, formatExport, defaultExportPath, renderDoctor, renderPermissions, resolveExtraDir, buildReviewPrompt, formatDuration, trimRestoredMessages, RESTORED_HISTORY_LIMIT, mergeMessages, hasQueuedJob, isSlashCommand, parseQueueCommand, parseLiveToggle, parseGoalCommand, isLiveConfigCommand, withGoal, formatQueueList, ctrlCEscalation, } from './commands.js';
20
20
  import { performCompact } from './compact.js';
21
- import { Scheduler, parseInterval, formatInterval, parseCron, } from './scheduler.js';
21
+ import { Scheduler, parseInterval, formatInterval, formatJobLine, parseCron, } from './scheduler.js';
22
22
  import { renderMarkdown } from './markdown.js';
23
23
  import { closeWeb } from './web.js';
24
24
  import { saveSession, loadLastSession, listSessions, sessionsDir, } from './sessions.js';
25
25
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
26
26
  const NL = String.fromCharCode(10);
27
+ // Floor for a /loop interval. A loop faster than the send throttle (15s)
28
+ // cannot do anything useful and would just hammer the rate limit, so we refuse
29
+ // it. It does NOT touch the throttle itself.
30
+ const MIN_LOOP_MS = 15_000;
27
31
  // True when a DeepSeek session/credentials were stored earlier (auth.json).
28
32
  // Used by /doctor to report that auto re-login is ready.
29
33
  function authMarkerExists() {
@@ -2387,6 +2391,15 @@ async function main() {
2387
2391
  console.error(theme.error(t('sched.loop_usage')));
2388
2392
  continue;
2389
2393
  }
2394
+ // A very short loop (e.g. "/loop 1s ...") would keep the agent sending
2395
+ // back-to-back and hit the rate limit. Enforce a floor; the send throttle
2396
+ // is 15s, so anything faster is pointless anyway.
2397
+ if (ms < MIN_LOOP_MS) {
2398
+ console.error(theme.error(t('sched.loop_too_short', {
2399
+ min: formatInterval(MIN_LOOP_MS),
2400
+ })));
2401
+ continue;
2402
+ }
2390
2403
  const job = scheduler.addLoop(ms, taskStr, Date.now());
2391
2404
  startScheduleTicker();
2392
2405
  console.log(theme.system(t('sched.added', {
@@ -2456,11 +2469,7 @@ async function main() {
2456
2469
  }
2457
2470
  console.log(theme.system(t('sched.title')));
2458
2471
  for (const j of jobs) {
2459
- const when = j.kind === 'loop'
2460
- ? 'every ' + formatInterval(j.intervalMs || 0)
2461
- : j.cron || '';
2462
- const nextIn = formatInterval(Math.max(0, j.nextAt - Date.now()));
2463
- console.log(theme.assistant(' #' + j.id + ' [' + when + ', next ~' + nextIn + '] ' + j.task));
2472
+ console.log(theme.assistant(formatJobLine(j, Date.now())));
2464
2473
  }
2465
2474
  console.log(theme.dim(t('sched.remove_hint')));
2466
2475
  continue;
package/dist/scheduler.js CHANGED
@@ -19,7 +19,11 @@ export function parseInterval(text) {
19
19
  return n * mult;
20
20
  }
21
21
  // Render an interval back to the shortest human form (used in listings).
22
+ // Non-finite input (a cron job whose next fire could not be computed sets
23
+ // nextAt to Infinity) renders as "-" instead of "Infinityh".
22
24
  export function formatInterval(ms) {
25
+ if (!Number.isFinite(ms))
26
+ return '-';
23
27
  if (ms % 3_600_000 === 0)
24
28
  return ms / 3_600_000 + 'h';
25
29
  if (ms % 60_000 === 0)
@@ -111,6 +115,15 @@ export function nextCronTime(expr, fromMs) {
111
115
  }
112
116
  return null;
113
117
  }
118
+ // One listing line for a job: "#3 [every 10m, next ~5m] run the tests". Pure,
119
+ // so the /jobs formatting is unit-tested without a live scheduler.
120
+ export function formatJobLine(job, now) {
121
+ const when = job.kind === 'loop'
122
+ ? 'every ' + formatInterval(job.intervalMs || 0)
123
+ : job.cron || '';
124
+ const nextIn = formatInterval(Math.max(0, job.nextAt - now));
125
+ return ' #' + job.id + ' [' + when + ', next ~' + nextIn + '] ' + job.task;
126
+ }
114
127
  // Holds the scheduled jobs. Pure: no timers here. index.ts drives it with a
115
128
  // 1-second tick and enqueues the tasks that `due()` returns.
116
129
  export class Scheduler {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.38.0",
3
+ "version": "2.40.0",
4
4
  "description": "Terminal coding agent over chat.deepseek.com via Playwright",
5
5
  "type": "module",
6
6
  "bin": {