nanobazaar-cli 2.0.0 → 2.0.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `nanobazaar-cli` are documented in this file.
4
4
 
5
5
  This project follows Semantic Versioning.
6
6
 
7
+ ## [2.0.1] - 2026-02-08
8
+
9
+ ### Changed
10
+ - `nanobazaar watch` is now notifier-only: it keeps an SSE connection and wakes OpenClaw on relay wake events + a safety interval, but does not poll or ack.
11
+ - Added `--safety-wake-interval` (alias for `--safety-poll-interval`) to reflect notifier semantics.
12
+
7
13
  ## [2.0.0] - 2026-02-08
8
14
 
9
15
  ### Added
package/bin/nanobazaar CHANGED
@@ -1235,11 +1235,11 @@ Commands:
1235
1235
  Poll events and optionally ack
1236
1236
  poll ack --up-to-event-id <id>
1237
1237
  Advance the server-side poll cursor (used for 410 resync)
1238
- watch [--stream-path /v0/stream] [--safety-poll-interval <seconds>]
1238
+ watch [--stream-path /v0/stream] [--safety-wake-interval <seconds>]
1239
1239
  [--state-path <path>] [--openclaw-bin <bin>] [--event-text <text>]
1240
- [--mode now|next] [--no-openclaw] [--no-fetch-payloads]
1241
- Maintain SSE connection; poll on wake + on safety interval.
1242
- Triggers an OpenClaw wakeup when new events are persisted.
1240
+ [--mode now|next] [--no-openclaw]
1241
+ Maintain SSE connection; wake OpenClaw on relay wake events + on a safety interval.
1242
+ Does not poll or ack (OpenClaw should run /nanobazaar poll).
1243
1243
 
1244
1244
  Global flags:
1245
1245
  --help Show this help
@@ -2987,14 +2987,15 @@ async function runWatch(argv) {
2987
2987
  throw new Error('Local fswatch wakeups are removed. Remove --fswatch-bin/--debounce-ms and retry.');
2988
2988
  }
2989
2989
 
2990
- const safetyIntervalSeconds = flags.safetyPollInterval
2991
- ? parsePositiveInt(flags.safetyPollInterval, '--safety-poll-interval')
2992
- : 180;
2990
+ if (flags.ack !== undefined || flags.fetchPayloads !== undefined || flags.limit !== undefined || flags.output !== undefined || flags.printPolls !== undefined || flags.types !== undefined) {
2991
+ throw new Error('watch no longer polls. Remove polling flags (--no-ack/--no-fetch-payloads/--limit/--types/--print-polls/--output) and retry.');
2992
+ }
2993
2993
 
2994
- const printPolls = !!flags.printPolls;
2995
- const pollLimit = parseOptionalPositiveInt(flags.limit, '--limit')
2996
- ?? parseOptionalPositiveInt(config.poll_limit, 'NBR_POLL_LIMIT');
2997
- const pollTypes = flags.types || config.poll_types;
2994
+ const safetyIntervalSeconds = flags.safetyWakeInterval
2995
+ ? parsePositiveInt(flags.safetyWakeInterval, '--safety-wake-interval')
2996
+ : flags.safetyPollInterval
2997
+ ? parsePositiveInt(flags.safetyPollInterval, '--safety-poll-interval')
2998
+ : 180;
2998
2999
 
2999
3000
  const openclawBin = String(flags.openclawBin || 'openclaw');
3000
3001
  const mode = String(flags.mode || 'now');
@@ -3005,22 +3006,18 @@ async function runWatch(argv) {
3005
3006
  relay_url: config.relay_url,
3006
3007
  state_path: statePath,
3007
3008
  stream_path: streamPath,
3008
- safety_poll_interval_seconds: safetyIntervalSeconds,
3009
- ack: flags.ack !== false,
3010
- poll_limit: pollLimit ?? null,
3011
- poll_types: pollTypes ?? null,
3012
- print_polls: printPolls,
3009
+ safety_wake_interval_seconds: safetyIntervalSeconds,
3013
3010
  openclaw_enabled: openclawEnabled,
3014
3011
  });
3015
3012
 
3016
- let pollInFlight = false;
3017
- let pollQueued = false;
3018
- let queuedReason = null;
3019
3013
  let openclawMissing = false;
3014
+ let wakeInFlight = false;
3015
+ let wakeQueued = false;
3016
+ let queuedReason = null;
3020
3017
 
3021
3018
  function triggerOpenclawWake(reason) {
3022
3019
  if (!openclawEnabled || openclawMissing) {
3023
- return;
3020
+ return false;
3024
3021
  }
3025
3022
  if (debugLog) {
3026
3023
  debugLog('openclaw wake', {reason, openclaw_bin: openclawBin, mode, event_text: eventText});
@@ -3032,53 +3029,30 @@ async function runWatch(argv) {
3032
3029
  if (debugLog) {
3033
3030
  debugLog('openclaw wake failed', result.error && result.error.message ? result.error.message : String(result.error));
3034
3031
  }
3032
+ return false;
3035
3033
  }
3034
+ return true;
3036
3035
  }
3037
3036
 
3038
- async function runPollLoop(reason) {
3037
+ async function runWakeLoop(reason) {
3039
3038
  queuedReason = reason;
3040
- pollQueued = true;
3041
- if (pollInFlight) {
3039
+ wakeQueued = true;
3040
+ if (wakeInFlight) {
3042
3041
  return;
3043
3042
  }
3044
- pollInFlight = true;
3043
+ wakeInFlight = true;
3045
3044
  try {
3046
- while (pollQueued) {
3047
- pollQueued = false;
3045
+ while (wakeQueued) {
3046
+ wakeQueued = false;
3048
3047
  const label = queuedReason || reason;
3049
3048
  queuedReason = null;
3050
- try {
3051
- const {response, events, addedEvents, ackedId} = await pollOnce({
3052
- config,
3053
- state,
3054
- statePath,
3055
- keys,
3056
- identity,
3057
- since: undefined,
3058
- limit: pollLimit,
3059
- types: pollTypes,
3060
- ack: flags.ack !== false,
3061
- fetchPayloads: flags.fetchPayloads !== false,
3062
- quiet: true,
3063
- compact: !!flags.compact,
3064
- debugLog,
3065
- });
3066
-
3067
- if (printPolls && response) {
3068
- printJson(response, !!flags.compact);
3069
- }
3070
3049
 
3071
- console.error(`[watch] poll ok (${label}): events=${events.length} added=${addedEvents} ack=${flags.ack === false ? 'disabled' : ackedId}`);
3072
- if (addedEvents > 0) {
3073
- triggerOpenclawWake(label);
3074
- }
3075
- } catch (err) {
3076
- console.error(`[watch] poll error (${label}): ${err && err.message ? err.message : String(err)}`);
3077
- // Keep running; polling is idempotent and can be retried on the next wake/safety interval.
3078
- }
3050
+ // Best-effort: waking OpenClaw can be retried on the next wake/safety interval.
3051
+ const didWake = triggerOpenclawWake(label);
3052
+ console.error(`[watch] wake ${didWake ? 'ok' : 'skipped'} (${label})`);
3079
3053
  }
3080
3054
  } finally {
3081
- pollInFlight = false;
3055
+ wakeInFlight = false;
3082
3056
  }
3083
3057
  }
3084
3058
 
@@ -3096,17 +3070,17 @@ async function runWatch(argv) {
3096
3070
  console.error(`[watch] relay=${config.relay_url}`);
3097
3071
  console.error(`[watch] state_path=${statePath}`);
3098
3072
  console.error(`[watch] stream_path=${streamPath}`);
3099
- console.error(`[watch] safety_poll_interval_seconds=${safetyIntervalSeconds}`);
3073
+ console.error(`[watch] safety_wake_interval_seconds=${safetyIntervalSeconds}`);
3100
3074
 
3101
3075
  const safetyTimer = setInterval(() => {
3102
3076
  if (signal.aborted) {
3103
3077
  return;
3104
3078
  }
3105
- void runPollLoop('safety');
3079
+ void runWakeLoop('safety');
3106
3080
  }, safetyIntervalSeconds * 1000);
3107
3081
 
3108
- // Kick off an initial poll so the watcher is useful even if wakeups are missed.
3109
- void runPollLoop('startup');
3082
+ // Kick off an initial wake so the agent can poll even if wakeups are missed.
3083
+ void runWakeLoop('startup');
3110
3084
 
3111
3085
  let attempt = 0;
3112
3086
  function isWakeEvent(evt) {
@@ -3160,7 +3134,7 @@ async function runWatch(argv) {
3160
3134
  });
3161
3135
  if (isWakeEvent(evt)) {
3162
3136
  debugLog('wake detected', {});
3163
- void runPollLoop('wake');
3137
+ void runWakeLoop('wake');
3164
3138
  }
3165
3139
  },
3166
3140
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nanobazaar-cli",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "NanoBazaar CLI for the NanoBazaar Relay and OpenClaw skill.",
5
5
  "homepage": "https://github.com/nanobazaar/nanobazaar/tree/main/packages/nanobazaar-cli#readme",
6
6
  "license": "UNLICENSED",