@skrr-ai/cli 0.1.135 → 0.1.136

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,10 +1,13 @@
1
1
  import { BaseCommand } from '../../base-command';
2
- import { type ApplyProactiveAgentResponse } from '../../lib/proactiveApi';
2
+ import { type ProactiveAgentSpec, type ApplyProactiveAgentResponse } from '../../lib/proactiveApi';
3
3
  export type ProactiveInstallReadiness = {
4
4
  status: 'ready' | 'degraded';
5
5
  message: string;
6
6
  repairCommand?: string;
7
7
  };
8
+ export declare function workerPolicyWindowLines(policy: NonNullable<ProactiveAgentSpec['worker']>['policy']): string[];
9
+ /** JSON previews show the effective disabled state without mutating the input spec. */
10
+ export declare function specWithEffectiveWindowFlags(spec: ProactiveAgentSpec): ProactiveAgentSpec;
8
11
  /**
9
12
  * Agent identity creation is intentionally forward-only, but an Agent URL must
10
13
  * not masquerade as a fully installed proactive service when a watcher or
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.workerPolicyWindowLines = workerPolicyWindowLines;
4
+ exports.specWithEffectiveWindowFlags = specWithEffectiveWindowFlags;
3
5
  exports.proactiveInstallReadiness = proactiveInstallReadiness;
4
6
  const core_1 = require("@oclif/core");
5
7
  const base_command_1 = require("../../base-command");
@@ -7,6 +9,40 @@ const prompt_1 = require("../../lib/prompt");
7
9
  const format_1 = require("../../lib/format");
8
10
  const web_url_1 = require("../../lib/web-url");
9
11
  const proactiveApi_1 = require("../../lib/proactiveApi");
12
+ function workerPolicyWindowLines(policy) {
13
+ const lines = [];
14
+ for (const [label, window] of [
15
+ ['Working hours', policy?.workingHours],
16
+ ['Quiet hours', policy?.quietHours],
17
+ ]) {
18
+ if (!window)
19
+ continue;
20
+ const state = window.enabled === undefined
21
+ ? 'disabled; enabled not specified'
22
+ : window.enabled ? 'enabled' : 'disabled';
23
+ lines.push(` ${label}: ${window.start}–${window.end} ${window.timezone ?? '(no zone recorded)'} (${state})`);
24
+ }
25
+ return lines;
26
+ }
27
+ /** JSON previews show the effective disabled state without mutating the input spec. */
28
+ function specWithEffectiveWindowFlags(spec) {
29
+ const policy = spec.worker?.policy;
30
+ if (!spec.worker || !policy)
31
+ return spec;
32
+ const workingHours = policy.workingHours && { ...policy.workingHours, enabled: policy.workingHours.enabled ?? false };
33
+ const quietHours = policy.quietHours && { ...policy.quietHours, enabled: policy.quietHours.enabled ?? false };
34
+ return {
35
+ ...spec,
36
+ worker: {
37
+ ...spec.worker,
38
+ policy: {
39
+ ...policy,
40
+ ...(workingHours ? { workingHours } : {}),
41
+ ...(quietHours ? { quietHours } : {}),
42
+ },
43
+ },
44
+ };
45
+ }
10
46
  /**
11
47
  * Agent identity creation is intentionally forward-only, but an Agent URL must
12
48
  * not masquerade as a fully installed proactive service when a watcher or
@@ -23,6 +59,18 @@ function proactiveInstallReadiness(result, bin) {
23
59
  message: 'The Agent is off. Review the setup warnings and enable Always-On explicitly if you want it to run.',
24
60
  };
25
61
  }
62
+ if (result.warnings.some((warning) => warning.code === 'compass_existing_not_replaced')) {
63
+ return {
64
+ status: 'degraded',
65
+ message: 'The requested standing direction was not installed. Review the existing Compass and the setup warnings.',
66
+ };
67
+ }
68
+ if (result.warnings.some((warning) => warning.code === 'policy_window_enabled_unspecified')) {
69
+ return {
70
+ status: 'degraded',
71
+ message: 'Some worker time windows are disabled because their enablement was not specified. Review the warnings.',
72
+ };
73
+ }
26
74
  // A full trigger budget must not make a new persona-only Agent look broken
27
75
  // when its core system commitments, local execution policy, and Always-On
28
76
  // state installed successfully. The optional backlog watcher is deferred;
@@ -135,7 +183,7 @@ class AgentsSpawn extends base_command_1.BaseCommand {
135
183
  const spec = (body.spec ?? body);
136
184
  if (!flags.approve) {
137
185
  if (flags.json) {
138
- this.log(JSON.stringify(spec, null, 2));
186
+ this.log(JSON.stringify(specWithEffectiveWindowFlags(spec), null, 2));
139
187
  return;
140
188
  }
141
189
  this.renderSpec(spec);
@@ -192,7 +240,7 @@ class AgentsSpawn extends base_command_1.BaseCommand {
192
240
  const spec = plan.spec;
193
241
  if (!flags.approve) {
194
242
  if (flags.json) {
195
- this.log(JSON.stringify(plan, null, 2));
243
+ this.log(JSON.stringify({ ...plan, spec: specWithEffectiveWindowFlags(spec) }, null, 2));
196
244
  return;
197
245
  }
198
246
  this.renderSpec(spec);
@@ -244,6 +292,8 @@ class AgentsSpawn extends base_command_1.BaseCommand {
244
292
  if (spec.worker) {
245
293
  this.log('');
246
294
  this.log(`Worker (event-reactive) — policy: ${spec.worker.policy?.mode ?? 'ask_first'}`);
295
+ for (const line of workerPolicyWindowLines(spec.worker.policy))
296
+ this.log(line);
247
297
  (0, format_1.renderTable)(spec.worker.watchers.map((w) => ({
248
298
  source: w.source,
249
299
  every: `${w.intervalMinutes ?? '-'}m`,
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class SpaceAutoDreamStatus extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const api_fetch_1 = require("../../../lib/api-fetch");
6
+ class SpaceAutoDreamStatus extends base_command_1.BaseCommand {
7
+ static description = 'Show current Space AutoDream eligibility and the most recent recorded cycle';
8
+ static args = { id: core_1.Args.string({ description: 'Space ID or title', required: true, ignoreStdin: true }) };
9
+ static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
10
+ async run() {
11
+ this.requireAuth();
12
+ const { args, flags } = await this.parse(SpaceAutoDreamStatus);
13
+ const spaceId = await this.resolveSpaceReference(args.id);
14
+ let result;
15
+ try {
16
+ result = await (0, api_fetch_1.apiFetch)(`/api/spaces/${encodeURIComponent(spaceId)}/autodream`, {
17
+ credential: this.resolvedCredential,
18
+ });
19
+ }
20
+ catch (error) {
21
+ this.handleApiError(error, { subject: `space ${args.id}` });
22
+ }
23
+ if (flags.json) {
24
+ this.printJsonResult(result);
25
+ return;
26
+ }
27
+ const eligibility = {
28
+ principal_missing_or_revoked: 'No active execution principal is configured.',
29
+ principal_lead_mismatch: 'The execution principal no longer matches the Space lead.',
30
+ principal_configured_unverified: 'An execution principal is configured; its current access has not been verified by this status check.',
31
+ }[result.currentEligibility] || 'Current eligibility is unknown.';
32
+ this.log(`Current eligibility: ${eligibility}`);
33
+ this.log(`Checked at: ${result.checkedAt}`);
34
+ const cycle = result.latestRecordedCycle;
35
+ if (cycle) {
36
+ this.log(`Most recent recorded cycle: ${cycle.window} — ${cycle.outcome}${cycle.reason ? ` (${cycle.reason})` : ''}; completed ${cycle.completedAt}`);
37
+ }
38
+ else {
39
+ this.log('No recorded cycle. This does not establish whether a cycle was scheduled.');
40
+ }
41
+ this.log('Cycle receipts are best-effort; an unrecorded later cycle may exist.');
42
+ }
43
+ }
44
+ exports.default = SpaceAutoDreamStatus;
@@ -62,6 +62,10 @@ class SpacesProposalsList extends base_command_1.BaseCommand {
62
62
  if (!result.data.length) {
63
63
  for (const line of (0, space_proposals_1.emptySpaceInboxLines)(result.nextCursor))
64
64
  this.log(line);
65
+ if (!result.nextCursor) {
66
+ const bin = this.config?.bin || 'skrr';
67
+ this.log(`For AutoDream status, run: ${bin} spaces autodream status ${spaceId}`);
68
+ }
65
69
  }
66
70
  (0, format_1.renderTable)(result.data.map(space_proposals_1.spaceProposalRow), [
67
71
  { key: 'id', header: 'PROPOSAL', verbatim: true },
@@ -25,6 +25,10 @@ function describeFireAuditDetail(detail, fireId, triggerId) {
25
25
  lines.push(`Reason: ${reason}`);
26
26
  if (message && message !== reason)
27
27
  lines.push(`${reason ? 'Detail:' : 'Reason:'} ${message}`);
28
+ const quietHours = (0, triggers_1.quietHoursAuditExplanation)(detail);
29
+ if (quietHours) {
30
+ lines.push(`Explanation: ${quietHours.summary}. ${quietHours.detail}`);
31
+ }
28
32
  if (detail.durationMs !== undefined)
29
33
  lines.push(`Duration: ${String(detail.durationMs)}ms`);
30
34
  if (detail.conversationId)
@@ -7,6 +7,10 @@ export interface ProactiveWorkingHours {
7
7
  end: string;
8
8
  timezone?: string;
9
9
  }
10
+ /** Worker policy windows have an explicit enable switch; orchestrator hours do not. */
11
+ export interface ProactiveWorkerPolicyHours extends ProactiveWorkingHours {
12
+ enabled?: boolean;
13
+ }
10
14
  export interface SpecWatcher {
11
15
  source: WatcherSource;
12
16
  intervalMinutes?: number;
@@ -34,8 +38,8 @@ export interface ProactiveAgentSpec {
34
38
  maxAutoRunsPerDay?: number;
35
39
  cooldownMinutes?: number;
36
40
  requireApprovalRiskLevels?: string[];
37
- workingHours?: ProactiveWorkingHours;
38
- quietHours?: ProactiveWorkingHours;
41
+ workingHours?: ProactiveWorkerPolicyHours;
42
+ quietHours?: ProactiveWorkerPolicyHours;
39
43
  };
40
44
  };
41
45
  orchestrator?: {
@@ -583,6 +583,15 @@ export declare function renderTriggerSummary(trigger: TriggerDefinition, log: (l
583
583
  baseURL?: string;
584
584
  }): void;
585
585
  export declare function renderLegacyRuns(runs: LegacyTriggerRun[], log: (line: string) => void): void;
586
+ /** Human explanation for quiet-hour audit rows; a one-shot may have been re-armed. */
587
+ export declare function quietHoursAuditExplanation(fire: {
588
+ source?: unknown;
589
+ reason?: unknown;
590
+ outcome?: unknown;
591
+ }): {
592
+ summary: string;
593
+ detail: string;
594
+ } | null;
586
595
  export declare function renderFireAudit(fires: TriggerFireRecord[], log: (line: string) => void): void;
587
596
  /**
588
597
  * Trigger budget for one scope. `active` counts only ENABLED rows — a disabled
@@ -53,6 +53,7 @@ exports.toolsRefusedHintLines = toolsRefusedHintLines;
53
53
  exports.fireRefusalLines = fireRefusalLines;
54
54
  exports.renderTriggerSummary = renderTriggerSummary;
55
55
  exports.renderLegacyRuns = renderLegacyRuns;
56
+ exports.quietHoursAuditExplanation = quietHoursAuditExplanation;
56
57
  exports.renderFireAudit = renderFireAudit;
57
58
  const data_provider_1 = require("@skrr-ai/data-provider");
58
59
  const node_fs_1 = require("node:fs");
@@ -1524,6 +1525,22 @@ function renderLegacyRuns(runs, log) {
1524
1525
  { key: 'conversation', header: 'CONVO', maxWidth: 24 },
1525
1526
  ], log);
1526
1527
  }
1528
+ /** Human explanation for quiet-hour audit rows; a one-shot may have been re-armed. */
1529
+ function quietHoursAuditExplanation(fire) {
1530
+ const reason = fire.reason || fire.outcome;
1531
+ if (reason !== 'inside_quiet_hours' && reason !== 'initiative_policy_quiet_hours')
1532
+ return null;
1533
+ if (fire.source === 'once') {
1534
+ return {
1535
+ summary: 'One-shot skipped: quiet hours',
1536
+ detail: 'This skipped occurrence will not retry automatically. Check the trigger state; if the one-shot is spent, schedule a new one outside quiet hours.',
1537
+ };
1538
+ }
1539
+ return {
1540
+ summary: 'Skipped: quiet hours',
1541
+ detail: 'Review the trigger and Agent quiet-hours settings before retrying.',
1542
+ };
1543
+ }
1527
1544
  function renderFireAudit(fires, log) {
1528
1545
  if (fires.length === 0) {
1529
1546
  log('No fire audit records.');
@@ -1536,7 +1553,7 @@ function renderFireAudit(fires, log) {
1536
1553
  source: fire.source ?? '-',
1537
1554
  reason: fire.metadata?.recordKind === 'schedule_end_marker'
1538
1555
  ? 'Schedule ended after prior fire'
1539
- : fire.reason ?? fire.errorMessage ?? '',
1556
+ : quietHoursAuditExplanation(fire)?.summary ?? fire.reason ?? fire.errorMessage ?? '',
1540
1557
  duration: fire.durationMs === undefined ? '-' : `${fire.durationMs}ms`,
1541
1558
  replay: fire.metadata?.replayable === true || fire.metadata?.replayContext
1542
1559
  ? 'yes'
@@ -90022,6 +90022,76 @@
90022
90022
  "update.js"
90023
90023
  ]
90024
90024
  },
90025
+ "spaces:autodream:status": {
90026
+ "aliases": [],
90027
+ "args": {
90028
+ "id": {
90029
+ "description": "Space ID or title",
90030
+ "name": "id",
90031
+ "required": true
90032
+ }
90033
+ },
90034
+ "description": "Show current Space AutoDream eligibility and the most recent recorded cycle",
90035
+ "flags": {
90036
+ "bare": {
90037
+ "description": "Bare mode — ignore keychain/file credential sources. Token must come from env or --token.",
90038
+ "name": "bare",
90039
+ "allowNo": false,
90040
+ "type": "boolean"
90041
+ },
90042
+ "token": {
90043
+ "description": "Bearer token for this invocation (debugging/impersonation). Overrides env and stored creds.",
90044
+ "name": "token",
90045
+ "hasDynamicHelp": false,
90046
+ "multiple": false,
90047
+ "type": "option"
90048
+ },
90049
+ "workspace": {
90050
+ "description": "Workspace ID for workspace-scoped requests (also sets X-Workspace-Id).",
90051
+ "name": "workspace",
90052
+ "hasDynamicHelp": false,
90053
+ "multiple": false,
90054
+ "type": "option"
90055
+ },
90056
+ "profile": {
90057
+ "description": "Which stored session to use. Each profile keeps its own credential and deployment, so signing into one does not sign you out of another. Also OVERSKY_PROFILE. List them with `profiles list`.",
90058
+ "name": "profile",
90059
+ "hasDynamicHelp": false,
90060
+ "multiple": false,
90061
+ "type": "option"
90062
+ },
90063
+ "raw": {
90064
+ "description": "With --json, keep the Mongo storage fields (_id next to id, __v) that the CLI otherwise strips. Also OVERSKY_CLI_RAW=1.",
90065
+ "name": "raw",
90066
+ "allowNo": false,
90067
+ "type": "boolean"
90068
+ },
90069
+ "json": {
90070
+ "description": "Output as JSON",
90071
+ "name": "json",
90072
+ "allowNo": false,
90073
+ "type": "boolean"
90074
+ }
90075
+ },
90076
+ "hasDynamicHelp": false,
90077
+ "hiddenAliases": [],
90078
+ "id": "spaces:autodream:status",
90079
+ "pluginAlias": "@skrr-ai/cli",
90080
+ "pluginName": "@skrr-ai/cli",
90081
+ "pluginType": "core",
90082
+ "strict": true,
90083
+ "enableJsonFlag": false,
90084
+ "autonomousCredentialPolicy": "delegated",
90085
+ "resolveSpaceFlag": true,
90086
+ "isESM": false,
90087
+ "relativePath": [
90088
+ "dist",
90089
+ "commands",
90090
+ "spaces",
90091
+ "autodream",
90092
+ "status.js"
90093
+ ]
90094
+ },
90025
90095
  "spaces:bootstrap": {
90026
90096
  "aliases": [],
90027
90097
  "args": {
@@ -143454,5 +143524,5 @@
143454
143524
  ]
143455
143525
  }
143456
143526
  },
143457
- "version": "0.1.135"
143527
+ "version": "0.1.136"
143458
143528
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skrr-ai/cli",
3
- "version": "0.1.135",
3
+ "version": "0.1.136",
4
4
  "description": "Command-line interface for skrr",
5
5
  "license": "ISC",
6
6
  "author": "skrr",