@skrr-ai/cli 0.1.134 → 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.
- package/dist/base-command.d.ts +1 -0
- package/dist/base-command.js +9 -0
- package/dist/commands/agent/message/send.js +1 -1
- package/dist/commands/agents/schedule-trace.js +1 -0
- package/dist/commands/agents/spawn.d.ts +4 -1
- package/dist/commands/agents/spawn.js +52 -2
- package/dist/commands/memory/search.js +8 -3
- package/dist/commands/memory/versions/show.js +3 -1
- package/dist/commands/spaces/autodream/status.d.ts +11 -0
- package/dist/commands/spaces/autodream/status.js +44 -0
- package/dist/commands/spaces/proposals/list.js +4 -0
- package/dist/commands/triggers/authorization.d.ts +14 -0
- package/dist/commands/triggers/authorization.js +45 -0
- package/dist/commands/triggers/create.d.ts +1 -0
- package/dist/commands/triggers/create.js +10 -0
- package/dist/commands/triggers/fire-detail.js +21 -0
- package/dist/commands/triggers/prune.js +15 -3
- package/dist/generated/agent-guides.json +29 -29
- package/dist/lib/agent-proactive-baseline.js +5 -0
- package/dist/lib/proactiveApi.d.ts +6 -2
- package/dist/lib/schedule.d.ts +4 -0
- package/dist/lib/schedule.js +28 -0
- package/dist/lib/triggers.d.ts +26 -0
- package/dist/lib/triggers.js +22 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5018 -5009
- package/oclif.manifest.json +164 -3
- package/package.json +1 -1
package/dist/base-command.d.ts
CHANGED
|
@@ -479,6 +479,7 @@ export declare abstract class BaseCommand extends Command {
|
|
|
479
479
|
* bug (2026-09-18).
|
|
480
480
|
*/
|
|
481
481
|
private lastApiRequestId?;
|
|
482
|
+
private jsonErrorWritten;
|
|
482
483
|
/** E6: the server's `Retry-After` for the refused call, when it was a 429. */
|
|
483
484
|
private lastRetryAfterMs?;
|
|
484
485
|
private writeJsonCliError;
|
package/dist/base-command.js
CHANGED
|
@@ -1352,6 +1352,13 @@ class BaseCommand extends core_1.Command {
|
|
|
1352
1352
|
}
|
|
1353
1353
|
async catch(err) {
|
|
1354
1354
|
if (isOclifExitError(err)) {
|
|
1355
|
+
// oclif's default ExitError handler calls process.exit immediately.
|
|
1356
|
+
// A JSON error already written to a pipe may still be buffered, so let
|
|
1357
|
+
// Node drain stdout naturally while preserving the requested exit code.
|
|
1358
|
+
if (this.jsonErrorWritten) {
|
|
1359
|
+
process.exitCode = err.oclif?.exit ?? 1;
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1355
1362
|
return super.catch(err);
|
|
1356
1363
|
}
|
|
1357
1364
|
// Canonical Task Model v1 removed several `tasks complete` flags outright,
|
|
@@ -2155,6 +2162,7 @@ class BaseCommand extends core_1.Command {
|
|
|
2155
2162
|
* bug (2026-09-18).
|
|
2156
2163
|
*/
|
|
2157
2164
|
lastApiRequestId;
|
|
2165
|
+
jsonErrorWritten = false;
|
|
2158
2166
|
/** E6: the server's `Retry-After` for the refused call, when it was a 429. */
|
|
2159
2167
|
lastRetryAfterMs;
|
|
2160
2168
|
writeJsonCliError({ message, code, status, exit, retryable, details, requestId, }) {
|
|
@@ -2182,6 +2190,7 @@ class BaseCommand extends core_1.Command {
|
|
|
2182
2190
|
...(details ? { details } : {}),
|
|
2183
2191
|
},
|
|
2184
2192
|
}), null, 2));
|
|
2193
|
+
this.jsonErrorWritten = true;
|
|
2185
2194
|
this.exit(exit);
|
|
2186
2195
|
}
|
|
2187
2196
|
/**
|
|
@@ -133,7 +133,7 @@ class AgentMessageSend extends base_command_1.BaseCommand {
|
|
|
133
133
|
description: 'Path to a canonical intent JSON payload, or "-" for stdin',
|
|
134
134
|
}),
|
|
135
135
|
'idempotency-key': core_1.Flags.string({
|
|
136
|
-
description: 'Stable retry key
|
|
136
|
+
description: 'Stable retry key; overrides the key in --from-json, or is auto-derived when neither is supplied',
|
|
137
137
|
}),
|
|
138
138
|
kind: core_1.Flags.string({
|
|
139
139
|
description: 'Semantic kind; prefer milestone, status, decision, blocker, or result (legacy progress/question accepted)',
|
|
@@ -113,6 +113,7 @@ class AgentsScheduleTrace extends base_command_1.BaseCommand {
|
|
|
113
113
|
{ key: 'status', header: 'STATUS' },
|
|
114
114
|
{ key: 'summary', header: 'SUMMARY', maxWidth: 48 },
|
|
115
115
|
], (line) => this.log(line));
|
|
116
|
+
(0, schedule_1.renderTodoPolicyTraceDetails)(events, (line) => this.log(line));
|
|
116
117
|
// Which collection each column came from — the trace reconciles four
|
|
117
118
|
// sources and the reader should be able to go check one.
|
|
118
119
|
if (trace.sourcePolicy) {
|
|
@@ -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`,
|
|
@@ -6,7 +6,7 @@ const scoped_memory_command_1 = require("../../lib/scoped-memory-command");
|
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
7
|
const memory_scope_1 = require("../../lib/memory-scope");
|
|
8
8
|
class MemorySearch extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
9
|
-
static description = '
|
|
9
|
+
static description = 'Search a compatibility memory pool, or specify --scope or --store for canonical Memory';
|
|
10
10
|
static examples = [
|
|
11
11
|
'<%= config.bin %> memory search "dark mode preference"',
|
|
12
12
|
'<%= config.bin %> memory search "billing" --agent agent_abc123',
|
|
@@ -68,13 +68,18 @@ class MemorySearch extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
|
68
68
|
catch (err) {
|
|
69
69
|
this.handleApiError(err);
|
|
70
70
|
}
|
|
71
|
+
const canonicalHint = flags.agent
|
|
72
|
+
? 'Canonical Agent Memory is separate. Search with the same --agent and --scope agent:<agent-id>.'
|
|
73
|
+
: 'This is a compatibility pool. Search canonical Memory with --agent and --scope agent:<agent-id> or space:<space-id>.';
|
|
71
74
|
if (flags.json) {
|
|
72
|
-
this.log(JSON.stringify(response, null, 2));
|
|
75
|
+
this.log(JSON.stringify({ ...response, memorySource: 'compatibility_pool', canonicalSearchHint: canonicalHint }, null, 2));
|
|
73
76
|
return;
|
|
74
77
|
}
|
|
75
78
|
const results = response.results ?? [];
|
|
79
|
+
this.log('Compatibility-pool memory search:');
|
|
80
|
+
this.log(canonicalHint);
|
|
76
81
|
if (results.length === 0) {
|
|
77
|
-
this.log(`No memories matched "${args.query}".`);
|
|
82
|
+
this.log(`No compatibility-pool memories matched "${args.query}".`);
|
|
78
83
|
return;
|
|
79
84
|
}
|
|
80
85
|
const rows = results.map((r) => ({
|
|
@@ -12,7 +12,9 @@ class MemoryVersionsShow extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
|
12
12
|
this.requireAuth();
|
|
13
13
|
const { args, flags } = await this.parse(MemoryVersionsShow);
|
|
14
14
|
const result = await this.memoryHistoryApi(flags, { versionId: args.id });
|
|
15
|
-
this.print(result, flags.json, `${result.id} ${result.operation}\n${JSON.stringify(result.payloadSnapshot, null, 2)}
|
|
15
|
+
this.print(result, flags.json, `${result.id} ${result.operation}\n${JSON.stringify(result.payloadSnapshot, null, 2)}${result.projection?.kind === 'legacy_episode_omitted'
|
|
16
|
+
? '\nAn invalid historical episode reference was omitted; the content hash identifies the original stored payload.'
|
|
17
|
+
: ''}`);
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
exports.default = MemoryVersionsShow;
|
|
@@ -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 },
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export default class TriggersAuthorization extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
revoke: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
restore: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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 triggers_1 = require("../../lib/triggers");
|
|
6
|
+
class TriggersAuthorization extends base_command_1.BaseCommand {
|
|
7
|
+
static description = 'Revoke or restore a trigger’s user-directed authorization grant';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> triggers authorization <trigger-id> --revoke',
|
|
10
|
+
'<%= config.bin %> triggers authorization <trigger-id> --restore --json',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: core_1.Args.string({ description: 'Trigger ID', required: true, ignoreStdin: true }),
|
|
14
|
+
};
|
|
15
|
+
static flags = {
|
|
16
|
+
revoke: core_1.Flags.boolean({ description: 'Withdraw the existing grant', exclusive: ['restore'] }),
|
|
17
|
+
restore: core_1.Flags.boolean({ description: 'Restore the existing grant', exclusive: ['revoke'] }),
|
|
18
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
19
|
+
};
|
|
20
|
+
async run() {
|
|
21
|
+
this.requireAuth();
|
|
22
|
+
const { args, flags } = await this.parse(TriggersAuthorization);
|
|
23
|
+
if (!flags.revoke && !flags.restore) {
|
|
24
|
+
this.failWithCliError({
|
|
25
|
+
message: 'Choose --revoke or --restore for the existing authorization grant.',
|
|
26
|
+
code: 'AUTHORIZATION_ACTION_REQUIRED',
|
|
27
|
+
exit: 2,
|
|
28
|
+
retryable: false,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
let result;
|
|
32
|
+
try {
|
|
33
|
+
result = await triggers_1.triggerApi.setAuthorizationRevoked(args.id, flags.revoke === true);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
this.handleApiError(err);
|
|
37
|
+
}
|
|
38
|
+
if (flags.json) {
|
|
39
|
+
this.log(JSON.stringify(result, null, 2));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.log(flags.revoke ? 'Authorization revoked.' : 'Authorization restored.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.default = TriggersAuthorization;
|
|
@@ -78,6 +78,7 @@ export default class TriggersCreate extends BaseCommand {
|
|
|
78
78
|
'allow-unknown-event': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
79
79
|
};
|
|
80
80
|
run(): Promise<void>;
|
|
81
|
+
private warnMissingSelfSchedule;
|
|
81
82
|
/**
|
|
82
83
|
* The server creates the trigger and then says whether something already
|
|
83
84
|
* watches the same thing. Printed AFTER the summary, and the sentence itself
|
|
@@ -324,6 +324,7 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
324
324
|
}
|
|
325
325
|
if (trigger.dryRun) {
|
|
326
326
|
this.log('Trigger accepted by dry run.');
|
|
327
|
+
this.warnMissingSelfSchedule(trigger);
|
|
327
328
|
return;
|
|
328
329
|
}
|
|
329
330
|
this.log('Created trigger:');
|
|
@@ -331,6 +332,15 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
331
332
|
if (url)
|
|
332
333
|
this.log(`View it at ${url}`);
|
|
333
334
|
this.warnDuplicateSubscriptions(trigger);
|
|
335
|
+
this.warnMissingSelfSchedule(trigger);
|
|
336
|
+
}
|
|
337
|
+
warnMissingSelfSchedule(trigger) {
|
|
338
|
+
const warnings = trigger?.warnings;
|
|
339
|
+
if (!Array.isArray(warnings))
|
|
340
|
+
return;
|
|
341
|
+
const warning = warnings.find((item) => item && typeof item === 'object' && item.code === 'self_scheduled_without_next_run');
|
|
342
|
+
if (typeof warning?.message === 'string')
|
|
343
|
+
this.warn(warning.message);
|
|
334
344
|
}
|
|
335
345
|
/**
|
|
336
346
|
* The server creates the trigger and then says whether something already
|
|
@@ -25,10 +25,31 @@ 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)
|
|
31
35
|
lines.push(`Conversation: ${String(detail.conversationId)}`);
|
|
36
|
+
const metadata = detail.metadata;
|
|
37
|
+
if (metadata && typeof metadata === 'object' && !Array.isArray(metadata)) {
|
|
38
|
+
const record = metadata;
|
|
39
|
+
if (record.recordKind === 'schedule_end_marker') {
|
|
40
|
+
lines.push('Note: Schedule ended after the prior fire; this is not another occurrence.');
|
|
41
|
+
if (typeof record.afterOccurrenceId === 'string')
|
|
42
|
+
lines.push(`After fire: ${record.afterOccurrenceId}`);
|
|
43
|
+
}
|
|
44
|
+
const debounce = record.debounce;
|
|
45
|
+
if (debounce && typeof debounce === 'object' && !Array.isArray(debounce)) {
|
|
46
|
+
const { retryAt, windowMs } = debounce;
|
|
47
|
+
if (typeof retryAt === 'string' && retryAt.trim())
|
|
48
|
+
lines.push(`Retry at: ${retryAt}`);
|
|
49
|
+
if (typeof windowMs === 'number' && Number.isFinite(windowMs))
|
|
50
|
+
lines.push(`Debounce: ${windowMs}ms`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
32
53
|
// Tool calls refused during a turn that was delivered: `triggers show` points here for the facts.
|
|
33
54
|
lines.push(...(0, triggers_1.fireRefusalLines)(detail.metadata));
|
|
34
55
|
return lines;
|
|
@@ -80,8 +80,18 @@ class TriggersPrune extends base_command_1.BaseCommand {
|
|
|
80
80
|
// number that sizes the sweep, and `perUser` the cap it frees.
|
|
81
81
|
const reclaimable = ownerWide ? quota.perUserReclaimable : quota.reclaimable;
|
|
82
82
|
if (flags['dry-run']) {
|
|
83
|
+
let preview;
|
|
84
|
+
try {
|
|
85
|
+
preview = await triggers_1.triggerApi.prunePreview({
|
|
86
|
+
...target,
|
|
87
|
+
...(flags.limit ? { limit: flags.limit } : {}),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
this.handleApiError(err);
|
|
92
|
+
}
|
|
83
93
|
if (flags.json) {
|
|
84
|
-
this.log(JSON.stringify({
|
|
94
|
+
this.log(JSON.stringify({ ...preview, quota }, null, 2));
|
|
85
95
|
return;
|
|
86
96
|
}
|
|
87
97
|
if (ownerWide) {
|
|
@@ -92,9 +102,11 @@ class TriggersPrune extends base_command_1.BaseCommand {
|
|
|
92
102
|
this.log(`Scope: ${quota.scopeKind}`);
|
|
93
103
|
this.log(`Active: ${quota.active} / ${quota.limit} (${quota.remaining} free)`);
|
|
94
104
|
}
|
|
95
|
-
this.log(`
|
|
105
|
+
this.log(`Would delete: ${preview.wouldDelete} disabled trigger(s)`);
|
|
106
|
+
for (const id of preview.ids)
|
|
107
|
+
this.log(` ${id}`);
|
|
96
108
|
this.log('');
|
|
97
|
-
this.log('Dry run — nothing was deleted.');
|
|
109
|
+
this.log('Dry run — nothing was deleted. Candidates can change before pruning.');
|
|
98
110
|
return;
|
|
99
111
|
}
|
|
100
112
|
if (reclaimable === 0) {
|