@skrr-ai/cli 0.1.133 → 0.1.134

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.
@@ -1,5 +1,7 @@
1
1
  import { BaseCommand } from '../../base-command';
2
2
  import { type AgentGuidePointer } from '../../lib/guide-pointer';
3
+ /** Do not silently discard a JSON source's scope or event filters. */
4
+ export declare function applyWatchedSourceFlags(payload: Record<string, unknown>, built: Array<Record<string, unknown>> | undefined): void;
3
5
  /**
4
6
  * True only when the authored create body can materialize at least one event
5
7
  * binding. A polling-only source must not make `--event-driven` look successful
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyWatchedSourceFlags = applyWatchedSourceFlags;
3
4
  exports.hasEventCapableWatchedSource = hasEventCapableWatchedSource;
4
5
  exports.assertEventDrivenWatchedSource = assertEventDrivenWatchedSource;
5
6
  exports.createCadenceFromFlags = createCadenceFromFlags;
@@ -36,6 +37,17 @@ function configuredId(config, ...keys) {
36
37
  return typeof value === 'string' && value.trim().length > 0;
37
38
  });
38
39
  }
40
+ /** Do not silently discard a JSON source's scope or event filters. */
41
+ function applyWatchedSourceFlags(payload, built) {
42
+ if (!built)
43
+ return;
44
+ if (payload.watchedSources !== undefined) {
45
+ throw new Error('Cannot combine watchedSources in --from-json with watched-source flags: ' +
46
+ 'the flags would replace the entire JSON list, including its filters. ' +
47
+ 'Remove watchedSources from the JSON to use flags, or remove the watched-source flags to keep the JSON.');
48
+ }
49
+ payload.watchedSources = built;
50
+ }
39
51
  function hasStructurallyValidExplicitEvent(config) {
40
52
  const events = config?.events;
41
53
  if (!Array.isArray(events))
@@ -456,8 +468,7 @@ JSON
456
468
  githubEvents: (0, triggers_1.splitRepeated)(flags['github-event']),
457
469
  githubRepository: flags.repo,
458
470
  });
459
- if (built)
460
- payload.watchedSources = built;
471
+ applyWatchedSourceFlags(payload, built);
461
472
  const cadence = createCadenceFromFlags({
462
473
  eventDriven: flags['event-driven'],
463
474
  cadence: flags.cadence,
@@ -38,15 +38,31 @@ class MemoryMaintain extends base_command_1.BaseCommand {
38
38
  this.error('input must be a JSON object');
39
39
  }
40
40
  let result;
41
+ // Keep stdout machine-readable for --json; progress goes only to stderr.
42
+ const waiting = args.operation === 'remember' ? setTimeout(() => {
43
+ process.stderr.write('Still waiting for the memory save; the result is not confirmed yet.\n');
44
+ }, 4000) : null;
45
+ waiting?.unref();
41
46
  try {
42
47
  if (args.operation === 'remember')
43
- result = await data_provider_1.dataService.rememberAgentMemory(flags.agent, input);
48
+ result = await data_provider_1.dataService.rememberAgentMemory(flags.agent, input, { timeoutMs: 60000 });
44
49
  else
45
50
  result = await data_provider_1.dataService.maintainAgentMemory(flags.agent, args.operation, input);
46
51
  }
47
52
  catch (error) {
53
+ const e = error;
54
+ const status = e?.status ?? e?.response?.status;
55
+ const transportLost = ['ECONNABORTED', 'ETIMEDOUT', 'ECONNRESET', 'EPIPE', 'ERR_NETWORK', 'ECONNREFUSED', 'EAI_AGAIN'].includes(e?.code || '') ||
56
+ e?.name === 'TimeoutError' || /fetch failed|socket hang up|network error|timed out|timeout/i.test(e?.message || '');
57
+ if (args.operation === 'remember' && ((status !== undefined && status >= 500) || (!status && transportLost))) {
58
+ this.error('The memory save was not confirmed. It may have succeeded; check the Agent’s Memory or retry the exact same command.', { code: 'MEMORY_OUTCOME_UNKNOWN' });
59
+ }
48
60
  this.handleApiError(error);
49
61
  }
62
+ finally {
63
+ if (waiting)
64
+ clearTimeout(waiting);
65
+ }
50
66
  if (flags.json)
51
67
  this.log(this.agentJson(flags.agent, result));
52
68
  else {
@@ -181,7 +181,15 @@ function createNodeAdapter(opts = {}) {
181
181
  // (and per retry: proofs are single-use). No-op for every other token.
182
182
  Object.assign(headers, await (0, dpop_auth_1.dpopHeadersFor)(currentCredential().token, method, finalUrl));
183
183
  // E6: bounded retry on 429 for a GET or an idempotency-keyed write.
184
- const { response, retryAfterMs } = await (0, rate_limit_retry_1.fetchWithRateLimitRetry)(() => fetch(finalUrl, { method, headers, body: finalBody, ...(0, task_runtime_headers_1.taskRuntimeRedirectOptions)(headers) }), { method, headers });
184
+ // Callers that explicitly set a timeout need a real fetch deadline. The
185
+ // Node adapter otherwise silently drops the data-provider request option.
186
+ const timeoutMs = Number(options?.timeout);
187
+ const timeoutSignal = Number.isFinite(timeoutMs) && timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined;
188
+ const callerSignal = options?.signal;
189
+ const signal = timeoutSignal && callerSignal
190
+ ? AbortSignal.any([timeoutSignal, callerSignal])
191
+ : timeoutSignal || callerSignal;
192
+ const { response, retryAfterMs } = await (0, rate_limit_retry_1.fetchWithRateLimitRetry)(() => fetch(finalUrl, { method, headers, body: finalBody, ...(signal ? { signal } : {}), ...(0, task_runtime_headers_1.taskRuntimeRedirectOptions)(headers) }), { method, headers });
185
193
  lastRetryAfterMs = retryAfterMs;
186
194
  return response;
187
195
  }
@@ -64,6 +64,7 @@ export interface SmartScheduleProposal {
64
64
  workingHours: WorkingHoursWindow;
65
65
  contextSummary: {
66
66
  spaceName?: string;
67
+ taskScope?: 'lead_space' | 'no_lead_space' | 'unavailable';
67
68
  goalCount: number;
68
69
  openTaskCount: number;
69
70
  truncated: boolean;
@@ -160,6 +160,14 @@ function renderProposal(proposal, log) {
160
160
  const ctx = proposal.contextSummary;
161
161
  log(`Context: ${ctx.openTaskCount} open task(s), ${ctx.goalCount} goal(s)` +
162
162
  `${ctx.spaceName ? ` · ${ctx.spaceName}` : ''}${ctx.truncated ? ' (truncated)' : ''}`);
163
+ const taskScope = ctx.taskScope === 'lead_space'
164
+ ? 'Tasks were checked only in the lead Space; assigned tasks in other Spaces were not checked.'
165
+ : ctx.taskScope === 'no_lead_space'
166
+ ? 'No lead Space was found; assigned tasks in other Spaces were not checked.'
167
+ : ctx.taskScope === 'unavailable'
168
+ ? 'Task context was unavailable; the count may be incomplete.'
169
+ : 'Task search scope was not recorded for this proposal.';
170
+ log(`Task scope: ${taskScope}`);
163
171
  if (proposal.expiresAt)
164
172
  log(`Expires: ${formatStamp(proposal.expiresAt)}`);
165
173
  renderCapacityWarning(proposal.capacity, log);