@skrr-ai/cli 0.1.101 → 0.1.103
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.js +24 -0
- package/dist/commands/agent/message/send.js +6 -2
- package/dist/commands/agents/triggers/create.js +7 -17
- package/dist/commands/agents/triggers/update.js +41 -28
- package/dist/commands/commitments/control/apply.d.ts +15 -0
- package/dist/commands/commitments/control/apply.js +36 -0
- package/dist/commands/commitments/control/preview.d.ts +17 -0
- package/dist/commands/commitments/control/preview.js +43 -0
- package/dist/commands/commitments/control/show.d.ts +12 -0
- package/dist/commands/commitments/control/show.js +29 -0
- package/dist/commands/commitments/create.js +5 -2
- package/dist/commands/commitments/observation/probe.d.ts +15 -0
- package/dist/commands/commitments/observation/probe.js +46 -0
- package/dist/commands/commitments/observation/summary.d.ts +9 -0
- package/dist/commands/commitments/observation/summary.js +31 -0
- package/dist/commands/commitments/preflight.js +18 -1
- package/dist/commands/commitments/readiness/show.d.ts +12 -0
- package/dist/commands/commitments/readiness/show.js +29 -0
- package/dist/commands/commitments/readiness/verify.d.ts +13 -0
- package/dist/commands/commitments/readiness/verify.js +33 -0
- package/dist/commands/commitments/roster.d.ts +15 -0
- package/dist/commands/commitments/roster.js +39 -0
- package/dist/commands/commitments/show.js +1 -1
- package/dist/commands/commitments/status.d.ts +17 -0
- package/dist/commands/commitments/status.js +41 -0
- package/dist/commands/commitments/update.js +23 -9
- package/dist/commands/commitments/work-plan.d.ts +11 -0
- package/dist/commands/commitments/work-plan.js +36 -0
- package/dist/commands/compass/effective-policy.d.ts +12 -0
- package/dist/commands/compass/effective-policy.js +34 -0
- package/dist/commands/compass/update.d.ts +12 -0
- package/dist/commands/compass/update.js +27 -0
- package/dist/commands/daemon/logs.d.ts +39 -1
- package/dist/commands/daemon/logs.js +140 -13
- package/dist/commands/followups/checkin.js +46 -3
- package/dist/commands/machines/dedicated/exec.js +3 -1
- package/dist/commands/proposals/discard.d.ts +4 -0
- package/dist/commands/proposals/discard.js +3 -0
- package/dist/commands/proposals/keep.d.ts +4 -0
- package/dist/commands/proposals/keep.js +3 -0
- package/dist/commands/proposals/snooze.d.ts +4 -0
- package/dist/commands/proposals/snooze.js +3 -0
- package/dist/commands/spaces/workflows/cancel-node.d.ts +16 -0
- package/dist/commands/spaces/workflows/cancel-node.js +44 -0
- package/dist/commands/spaces/workflows/cancel.d.ts +40 -0
- package/dist/commands/spaces/workflows/cancel.js +109 -3
- package/dist/commands/spaces/workflows/run.d.ts +9 -0
- package/dist/commands/spaces/workflows/run.js +38 -0
- package/dist/commands/tasks/approvals/resolve.d.ts +12 -0
- package/dist/commands/tasks/approvals/resolve.js +21 -5
- package/dist/commands/tasks/schedule.js +1 -1
- package/dist/commands/triggers/capabilities.js +7 -0
- package/dist/commands/triggers/create.js +12 -18
- package/dist/commands/triggers/fire.js +3 -0
- package/dist/commands/triggers/update.js +41 -27
- package/dist/commands/widgets/check.d.ts +39 -0
- package/dist/commands/widgets/check.js +179 -0
- package/dist/lib/agent-mailbox.d.ts +0 -1
- package/dist/lib/agent-mailbox.js +0 -1
- package/dist/lib/commitment-loop-status.d.ts +16 -0
- package/dist/lib/commitment-loop-status.js +164 -0
- package/dist/lib/commitments.d.ts +47 -1
- package/dist/lib/commitments.js +218 -6
- package/dist/lib/compasses.d.ts +3 -0
- package/dist/lib/compasses.js +1 -0
- package/dist/lib/delegated-cli.d.ts +23 -1
- package/dist/lib/delegated-cli.js +61 -4
- package/dist/lib/first-party-harness.d.ts +1 -1
- package/dist/lib/first-party-harness.js +1 -1
- package/dist/lib/responsibility-controls.d.ts +11 -0
- package/dist/lib/responsibility-controls.js +119 -0
- package/dist/lib/session-task-write.d.ts +13 -0
- package/dist/lib/session-task-write.js +63 -3
- package/dist/lib/stewardship-output.js +13 -2
- package/dist/lib/triggers.d.ts +26 -0
- package/dist/lib/triggers.js +134 -1
- package/dist/lib/widgetCheck.d.ts +123 -0
- package/dist/lib/widgetCheck.js +998 -0
- package/dist/lib/widgetStaticScan.d.ts +111 -0
- package/dist/lib/widgetStaticScan.js +833 -0
- package/dist/lib/workflow-node-control.d.ts +10 -0
- package/dist/lib/workflow-node-control.js +76 -0
- package/dist/lib/workspaces.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +9 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +12 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +9 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +12 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +11924 -8704
- package/oclif.manifest.json +1487 -396
- package/package.json +11 -2
|
@@ -41,6 +41,9 @@ class TriggersFire extends base_command_1.BaseCommand {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
this.log(`Fire requested: outcome=${String(result.outcome ?? '-')} reason=${String(result.reason ?? '-')}`);
|
|
44
|
+
const note = (0, triggers_1.describeScheduledFire)(result);
|
|
45
|
+
if (note)
|
|
46
|
+
this.log(note);
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
exports.default = TriggersFire;
|
|
@@ -48,7 +48,9 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
48
48
|
multiple: true,
|
|
49
49
|
}),
|
|
50
50
|
timezone: core_1.Flags.string({ description: 'IANA timezone for schedule triggers' }),
|
|
51
|
-
'max-fires-per-day': core_1.Flags.integer({
|
|
51
|
+
'max-fires-per-day': core_1.Flags.integer({
|
|
52
|
+
description: 'Daily fire cap (schedule, stochastic and self_scheduled triggers only)',
|
|
53
|
+
}),
|
|
52
54
|
'max-runs': core_1.Flags.integer({ description: 'Lifetime fire cap for schedule triggers' }),
|
|
53
55
|
'end-at': core_1.Flags.string({
|
|
54
56
|
description: 'ISO-8601 datetime after which a schedule stops firing',
|
|
@@ -150,6 +152,29 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
150
152
|
throw new Error('Trigger kind cannot be changed after creation. ' +
|
|
151
153
|
'Remove `kind` from --from-json, or delete and recreate the trigger.');
|
|
152
154
|
}
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
this.error(err.message, { exit: 1 });
|
|
158
|
+
}
|
|
159
|
+
// The kind is the server's to say and cannot change, so the flags are checked against it and
|
|
160
|
+
// only the config block it owns is sent. Every block used to go: `--max-fires-per-day` wrote
|
|
161
|
+
// `stochastic` and `selfScheduled` onto a schedule trigger, and onto an on_demand one a cap
|
|
162
|
+
// nothing reads (OSK-15491).
|
|
163
|
+
let existing;
|
|
164
|
+
try {
|
|
165
|
+
existing = await triggers_1.triggerApi.get(args.id);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
this.handleApiError(err);
|
|
169
|
+
}
|
|
170
|
+
const existingKind = existing?.kind;
|
|
171
|
+
if (typeof existingKind !== 'string') {
|
|
172
|
+
this.error(`Trigger ${args.id} did not report its kind, so its settings cannot be checked.`, {
|
|
173
|
+
exit: 1,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
(0, triggers_1.assertKindFlagsApply)(existingKind, flags, { kindIsFixed: true });
|
|
153
178
|
const execution = {};
|
|
154
179
|
const builtinAction = (0, triggers_1.buildBuiltinActionPayload)({
|
|
155
180
|
builtinAction: flags['builtin-action'],
|
|
@@ -169,7 +194,10 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
169
194
|
});
|
|
170
195
|
const schedule = (0, triggers_1.buildScheduleConfigFromFlags)(flags);
|
|
171
196
|
(0, triggers_1.assertScheduleTimingShape)(schedule);
|
|
172
|
-
const once = (0, triggers_1.buildOnceConfigFromFlags)(flags
|
|
197
|
+
const once = (0, triggers_1.buildOnceConfigFromFlags)(flags, {
|
|
198
|
+
kind: existingKind,
|
|
199
|
+
allowNextRunAtAlias: true,
|
|
200
|
+
});
|
|
173
201
|
const filterValues = (0, triggers_1.splitRepeated)(flags['filter-value']);
|
|
174
202
|
// Consult the authoritative server catalog before warning about a local
|
|
175
203
|
// snapshot miss; server validation remains final when it is unavailable.
|
|
@@ -188,22 +216,8 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
188
216
|
filterValues,
|
|
189
217
|
});
|
|
190
218
|
const event = {};
|
|
191
|
-
(0, triggers_1.
|
|
192
|
-
|
|
193
|
-
eventType: flags.event,
|
|
194
|
-
filterMode: flags['filter-mode'],
|
|
195
|
-
filterField: flags['filter-field'],
|
|
196
|
-
filterValue: filterValues && filterValues.length > 1 ? filterValues : filterValues?.[0],
|
|
197
|
-
debounceMs: flags['debounce-ms'],
|
|
198
|
-
maxPerHour: flags['max-per-hour'],
|
|
199
|
-
});
|
|
200
|
-
const stochastic = {};
|
|
201
|
-
(0, triggers_1.setDefined)(stochastic, {
|
|
202
|
-
probability: flags.probability === undefined ? undefined : Number(flags.probability),
|
|
203
|
-
jitterMs: flags['jitter-ms'],
|
|
204
|
-
maxFiresPerDay: flags['max-fires-per-day'],
|
|
205
|
-
evalIntervalMinutes: flags['eval-interval-minutes'],
|
|
206
|
-
});
|
|
219
|
+
Object.assign(event, (0, triggers_1.buildEventConfigFromFlags)(flags, filterValues));
|
|
220
|
+
const stochastic = (0, triggers_1.buildStochasticConfigFromFlags)(flags);
|
|
207
221
|
const selfScheduled = (0, triggers_1.buildSelfScheduledConfigFromFlags)(flags);
|
|
208
222
|
const form = (0, triggers_1.buildFormConfigFromFlags)(flags);
|
|
209
223
|
const chatMessage = (0, triggers_1.buildChatMessageConfigFromFlags)(flags);
|
|
@@ -215,15 +229,15 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
215
229
|
idempotencyWindow: flags['idempotency-window'],
|
|
216
230
|
});
|
|
217
231
|
(0, triggers_1.mergeObjectField)(payload, 'execution', execution);
|
|
218
|
-
(0, triggers_1.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
232
|
+
(0, triggers_1.mergeTriggerKindConfig)(payload, existingKind, {
|
|
233
|
+
schedule,
|
|
234
|
+
once,
|
|
235
|
+
event,
|
|
236
|
+
stochastic,
|
|
237
|
+
selfScheduled,
|
|
238
|
+
form,
|
|
239
|
+
chatMessage,
|
|
240
|
+
});
|
|
227
241
|
}
|
|
228
242
|
catch (err) {
|
|
229
243
|
this.error(err.message, { exit: 1 });
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr widgets check` — the offline self-check a harness runs in Bash BEFORE it
|
|
4
|
+
* replies, because a rejected widget is only discovered after the message is sent.
|
|
5
|
+
*
|
|
6
|
+
* It extends `Command`, not `BaseCommand`, on purpose: it reads a file or stdin and
|
|
7
|
+
* prints, so it must work with no sign-in, no network and no daemon credential
|
|
8
|
+
* (a sandboxed harness has none, and `BaseCommand.init()` resolves one before any
|
|
9
|
+
* command body runs). The same reason `instructions guide` does it.
|
|
10
|
+
*
|
|
11
|
+
* It reaches NO API. There is no route behind it, so there is nothing for the
|
|
12
|
+
* CLI/API parity spec (`domain-api-parity.spec.ts`) to hold it to: it adds nothing
|
|
13
|
+
* to `api-endpoints.ts` or `dataService`, and it is safe to run anywhere.
|
|
14
|
+
*
|
|
15
|
+
* Exit codes: 0 every widget would be accepted and has no error finding; 1 at
|
|
16
|
+
* least one would be refused or has an error finding (or none was found); 2 the
|
|
17
|
+
* input could not be read.
|
|
18
|
+
*/
|
|
19
|
+
export declare const WIDGETS_CHECK_EXIT: {
|
|
20
|
+
readonly ok: 0;
|
|
21
|
+
readonly notOk: 1;
|
|
22
|
+
readonly unreadable: 2;
|
|
23
|
+
};
|
|
24
|
+
export default class WidgetsCheck extends Command {
|
|
25
|
+
static description: string;
|
|
26
|
+
static examples: string[];
|
|
27
|
+
static args: {
|
|
28
|
+
file: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
29
|
+
};
|
|
30
|
+
static flags: {
|
|
31
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
32
|
+
format: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
33
|
+
strict: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
34
|
+
'render-fence': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
35
|
+
};
|
|
36
|
+
run(): Promise<void>;
|
|
37
|
+
private readInput;
|
|
38
|
+
private emitInputError;
|
|
39
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.WIDGETS_CHECK_EXIT = void 0;
|
|
37
|
+
const core_1 = require("@oclif/core");
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
39
|
+
const prompt_1 = require("../../lib/prompt");
|
|
40
|
+
const widgetCheck_1 = require("../../lib/widgetCheck");
|
|
41
|
+
/**
|
|
42
|
+
* `skrr widgets check` — the offline self-check a harness runs in Bash BEFORE it
|
|
43
|
+
* replies, because a rejected widget is only discovered after the message is sent.
|
|
44
|
+
*
|
|
45
|
+
* It extends `Command`, not `BaseCommand`, on purpose: it reads a file or stdin and
|
|
46
|
+
* prints, so it must work with no sign-in, no network and no daemon credential
|
|
47
|
+
* (a sandboxed harness has none, and `BaseCommand.init()` resolves one before any
|
|
48
|
+
* command body runs). The same reason `instructions guide` does it.
|
|
49
|
+
*
|
|
50
|
+
* It reaches NO API. There is no route behind it, so there is nothing for the
|
|
51
|
+
* CLI/API parity spec (`domain-api-parity.spec.ts`) to hold it to: it adds nothing
|
|
52
|
+
* to `api-endpoints.ts` or `dataService`, and it is safe to run anywhere.
|
|
53
|
+
*
|
|
54
|
+
* Exit codes: 0 every widget would be accepted and has no error finding; 1 at
|
|
55
|
+
* least one would be refused or has an error finding (or none was found); 2 the
|
|
56
|
+
* input could not be read.
|
|
57
|
+
*/
|
|
58
|
+
exports.WIDGETS_CHECK_EXIT = { ok: 0, notOk: 1, unreadable: 2 };
|
|
59
|
+
class WidgetsCheck extends core_1.Command {
|
|
60
|
+
static description = 'Check a generative-UI widget offline before sending it: grammar, size limits, JavaScript syntax and likely sandbox failures. Runs entirely offline: it reaches no API, so it needs no sign-in and has no route to keep in parity.';
|
|
61
|
+
static examples = [
|
|
62
|
+
'<%= config.bin %> widgets check reply.md',
|
|
63
|
+
'<%= config.bin %> widgets check - < reply.md',
|
|
64
|
+
'<%= config.bin %> widgets check widget.json --json',
|
|
65
|
+
'<%= config.bin %> widgets check widget.json --render-fence > block.txt',
|
|
66
|
+
];
|
|
67
|
+
static args = {
|
|
68
|
+
file: core_1.Args.string({
|
|
69
|
+
description: 'File to check, or - for stdin. Text containing a widget block, or a JSON widget (a payload, a ui_widget part, or the ui_widget_render arguments, one or an array).',
|
|
70
|
+
required: true,
|
|
71
|
+
ignoreStdin: true,
|
|
72
|
+
}),
|
|
73
|
+
};
|
|
74
|
+
static flags = {
|
|
75
|
+
json: core_1.Flags.boolean({
|
|
76
|
+
description: 'Output the report as JSON: { ok, widgets: [{ id, title, bytes, limits, complete, accepted, ok, issues }], errors, warnings, summary }',
|
|
77
|
+
}),
|
|
78
|
+
format: core_1.Flags.string({
|
|
79
|
+
description: 'How to read the input: auto (JSON if it parses as JSON, otherwise text that contains a widget block), fence, or json',
|
|
80
|
+
options: ['auto', 'fence', 'json'],
|
|
81
|
+
default: 'auto',
|
|
82
|
+
}),
|
|
83
|
+
strict: core_1.Flags.boolean({
|
|
84
|
+
description: 'Also fail (exit 1) on warnings',
|
|
85
|
+
default: false,
|
|
86
|
+
}),
|
|
87
|
+
'render-fence': core_1.Flags.boolean({
|
|
88
|
+
description: 'For a JSON widget: print the correctly delimited block to stdout (the report goes to stderr), verified by parsing it back',
|
|
89
|
+
default: false,
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
async run() {
|
|
93
|
+
const { args, flags } = await this.parse(WidgetsCheck);
|
|
94
|
+
const read = await this.readInput(args.file);
|
|
95
|
+
if (!read.ok) {
|
|
96
|
+
this.emitInputError(flags.json, read.error);
|
|
97
|
+
this.exit(exports.WIDGETS_CHECK_EXIT.unreadable);
|
|
98
|
+
}
|
|
99
|
+
const result = (0, widgetCheck_1.checkWidgetInput)(read.text, {
|
|
100
|
+
format: flags.format,
|
|
101
|
+
strict: flags.strict,
|
|
102
|
+
});
|
|
103
|
+
if (flags['render-fence']) {
|
|
104
|
+
const rendered = (0, widgetCheck_1.renderWidgetFences)(result);
|
|
105
|
+
const report = {
|
|
106
|
+
...result.report,
|
|
107
|
+
errors: [...result.report.errors, ...rendered.errors],
|
|
108
|
+
};
|
|
109
|
+
report.ok = report.ok && rendered.errors.length === 0;
|
|
110
|
+
report.summary = {
|
|
111
|
+
...report.summary,
|
|
112
|
+
errors: report.summary.errors + rendered.errors.length,
|
|
113
|
+
};
|
|
114
|
+
if (flags.json) {
|
|
115
|
+
this.log(JSON.stringify({ ...report, fences: rendered.fences }, null, 2));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
for (const fence of rendered.fences) {
|
|
119
|
+
this.log(fence);
|
|
120
|
+
}
|
|
121
|
+
process.stderr.write(`${(0, widgetCheck_1.formatWidgetCheckReport)(report).join('\n')}\n`);
|
|
122
|
+
}
|
|
123
|
+
this.exit(report.ok ? exports.WIDGETS_CHECK_EXIT.ok : exports.WIDGETS_CHECK_EXIT.notOk);
|
|
124
|
+
}
|
|
125
|
+
if (flags.json) {
|
|
126
|
+
this.log(JSON.stringify(result.report, null, 2));
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.log((0, widgetCheck_1.formatWidgetCheckReport)(result.report).join('\n'));
|
|
130
|
+
}
|
|
131
|
+
this.exit(result.report.ok ? exports.WIDGETS_CHECK_EXIT.ok : exports.WIDGETS_CHECK_EXIT.notOk);
|
|
132
|
+
}
|
|
133
|
+
async readInput(source) {
|
|
134
|
+
try {
|
|
135
|
+
if (source === '-') {
|
|
136
|
+
if (process.stdin.isTTY) {
|
|
137
|
+
return {
|
|
138
|
+
ok: false,
|
|
139
|
+
error: {
|
|
140
|
+
code: 'input/no-stdin',
|
|
141
|
+
message: 'No input on stdin: it is a terminal, so there is nothing to read.',
|
|
142
|
+
fix: `Pipe the widget in (${this.config.bin} widgets check - < reply.md) or pass a file path.`,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return { ok: true, text: await (0, prompt_1.readStdin)() };
|
|
147
|
+
}
|
|
148
|
+
const size = fs.statSync(source).size;
|
|
149
|
+
if (size > widgetCheck_1.WIDGET_CHECK_MAX_INPUT_CHARS * 4) {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
error: {
|
|
153
|
+
code: 'input/too-large',
|
|
154
|
+
message: `${source} is ${size} bytes, far more than a message can carry.`,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return { ok: true, text: fs.readFileSync(source, 'utf8') };
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
return {
|
|
162
|
+
ok: false,
|
|
163
|
+
error: {
|
|
164
|
+
code: 'input/unreadable',
|
|
165
|
+
message: `Could not read ${source}: ${err?.message ?? String(err)}`,
|
|
166
|
+
fix: 'Pass the path of a readable file, or - to read stdin.',
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
emitInputError(json, error) {
|
|
172
|
+
if (json) {
|
|
173
|
+
this.log(JSON.stringify((0, widgetCheck_1.inputErrorReport)(error), null, 2));
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
process.stderr.write(`error: ${error.message}\n${error.fix ? ` fix: ${error.fix}\n` : ''}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.default = WidgetsCheck;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text rendering for `skrr commitments roster` / `skrr commitments status`.
|
|
3
|
+
*
|
|
4
|
+
* The loop state is DERIVED server-side (`CommitmentLoopStatus`); this file
|
|
5
|
+
* only words it. Two rules it must keep:
|
|
6
|
+
* - paused, unarmed and degraded read differently — "you paused it", "nothing
|
|
7
|
+
* will wake it" and "it cannot see" have different fixes;
|
|
8
|
+
* - `unknown` never borrows the healthy wording or an OK mark. "Cannot see"
|
|
9
|
+
* is not "fine".
|
|
10
|
+
*/
|
|
11
|
+
import { type CommitmentLoopStatus, type CommitmentRoster } from '@skrr-ai/data-provider';
|
|
12
|
+
export declare function loopStateLabel(state: unknown): string;
|
|
13
|
+
/** Roster table: one row per Commitment. */
|
|
14
|
+
export declare function formatCommitmentRoster(roster: Partial<CommitmentRoster>): string[];
|
|
15
|
+
/** One Commitment's loop, in full. */
|
|
16
|
+
export declare function formatCommitmentLoopStatus(status: CommitmentLoopStatus): string[];
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loopStateLabel = loopStateLabel;
|
|
4
|
+
exports.formatCommitmentRoster = formatCommitmentRoster;
|
|
5
|
+
exports.formatCommitmentLoopStatus = formatCommitmentLoopStatus;
|
|
6
|
+
/**
|
|
7
|
+
* Text rendering for `skrr commitments roster` / `skrr commitments status`.
|
|
8
|
+
*
|
|
9
|
+
* The loop state is DERIVED server-side (`CommitmentLoopStatus`); this file
|
|
10
|
+
* only words it. Two rules it must keep:
|
|
11
|
+
* - paused, unarmed and degraded read differently — "you paused it", "nothing
|
|
12
|
+
* will wake it" and "it cannot see" have different fixes;
|
|
13
|
+
* - `unknown` never borrows the healthy wording or an OK mark. "Cannot see"
|
|
14
|
+
* is not "fine".
|
|
15
|
+
*/
|
|
16
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
17
|
+
const format_1 = require("./format");
|
|
18
|
+
/** One word per state, with a mark only `healthy` may use. */
|
|
19
|
+
const STATE_LABEL = {
|
|
20
|
+
healthy: '✓ healthy',
|
|
21
|
+
blocked: '! blocked',
|
|
22
|
+
paused: '‖ paused',
|
|
23
|
+
unarmed: '! unarmed',
|
|
24
|
+
degraded: '! degraded',
|
|
25
|
+
inactive: '- inactive',
|
|
26
|
+
unknown: '? unknown',
|
|
27
|
+
};
|
|
28
|
+
function loopStateLabel(state) {
|
|
29
|
+
return typeof state === 'string' && state in STATE_LABEL
|
|
30
|
+
? STATE_LABEL[state]
|
|
31
|
+
: STATE_LABEL.unknown;
|
|
32
|
+
}
|
|
33
|
+
function when(value) {
|
|
34
|
+
if (typeof value !== 'string')
|
|
35
|
+
return '-';
|
|
36
|
+
const date = new Date(value);
|
|
37
|
+
if (Number.isNaN(date.getTime()))
|
|
38
|
+
return '-';
|
|
39
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
40
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
41
|
+
}
|
|
42
|
+
function count(value) {
|
|
43
|
+
return typeof value === 'number' && Number.isFinite(value) ? String(value) : '?';
|
|
44
|
+
}
|
|
45
|
+
function runs(status) {
|
|
46
|
+
const used = count(status.cost?.runsToday);
|
|
47
|
+
const max = status.cost?.maxRunsPerDay;
|
|
48
|
+
return typeof max === 'number' ? `${used}/${max}` : used;
|
|
49
|
+
}
|
|
50
|
+
function spend(status) {
|
|
51
|
+
const value = status.cost?.spendTodayUsd;
|
|
52
|
+
if (typeof value !== 'number')
|
|
53
|
+
return 'not metered';
|
|
54
|
+
const amount = `$${value.toFixed(2)}`;
|
|
55
|
+
// A partial ledger is a lower bound; never print it as the whole answer.
|
|
56
|
+
return status.cost?.spendKnown ? amount : `≥ ${amount} (some runs unpriced)`;
|
|
57
|
+
}
|
|
58
|
+
function nextWake(status) {
|
|
59
|
+
const wake = status.nextWakes?.[0];
|
|
60
|
+
return wake ? `${when(wake.at)} ${wake.kind}` : '-';
|
|
61
|
+
}
|
|
62
|
+
function watchSummary(status) {
|
|
63
|
+
const rows = Array.isArray(status.watching) ? status.watching : [];
|
|
64
|
+
if (!rows.length)
|
|
65
|
+
return '-';
|
|
66
|
+
return rows
|
|
67
|
+
.map((row) => {
|
|
68
|
+
const mark = row.access === 'blocked'
|
|
69
|
+
? '✗'
|
|
70
|
+
: row.access === 'unknown'
|
|
71
|
+
? '?'
|
|
72
|
+
: row.completeness === 'partial'
|
|
73
|
+
? '~'
|
|
74
|
+
: '✓';
|
|
75
|
+
return `${row.source}${mark}`;
|
|
76
|
+
})
|
|
77
|
+
.join(' ');
|
|
78
|
+
}
|
|
79
|
+
/** Roster table: one row per Commitment. */
|
|
80
|
+
function formatCommitmentRoster(roster) {
|
|
81
|
+
const lines = [];
|
|
82
|
+
const commitments = Array.isArray(roster.commitments) ? roster.commitments : [];
|
|
83
|
+
lines.push(`Agent ${roster.agentId ?? '-'} — ${commitments.length} commitment${commitments.length === 1 ? '' : 's'}`);
|
|
84
|
+
if (!commitments.length) {
|
|
85
|
+
lines.push('No commitments.');
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
(0, format_1.renderTable)(commitments.map((status) => ({
|
|
89
|
+
state: loopStateLabel(status.loopState),
|
|
90
|
+
id: status.commitmentId,
|
|
91
|
+
title: status.systemRole ? `${status.title} [${status.systemRole}]` : status.title,
|
|
92
|
+
next: nextWake(status),
|
|
93
|
+
runs: runs(status),
|
|
94
|
+
watching: watchSummary(status),
|
|
95
|
+
reason: status.loopReason ?? '',
|
|
96
|
+
})), [
|
|
97
|
+
{ key: 'state', header: 'STATE' },
|
|
98
|
+
{ key: 'id', header: 'ID', verbatim: true },
|
|
99
|
+
{ key: 'title', header: 'TITLE', maxWidth: 36 },
|
|
100
|
+
{ key: 'next', header: 'NEXT WAKE' },
|
|
101
|
+
{ key: 'runs', header: 'RUNS TODAY' },
|
|
102
|
+
{ key: 'watching', header: 'WATCHING', maxWidth: 40 },
|
|
103
|
+
{ key: 'reason', header: 'REASON', maxWidth: 40 },
|
|
104
|
+
], (line) => lines.push(line));
|
|
105
|
+
const attention = commitments.filter((status) => !['healthy', 'paused', 'inactive'].includes(String(status.loopState))).length;
|
|
106
|
+
if (attention) {
|
|
107
|
+
lines.push(`${attention} need${attention === 1 ? 's' : ''} attention — run \`skrr commitments status <id>\` for why.`);
|
|
108
|
+
}
|
|
109
|
+
if (roster.truncated) {
|
|
110
|
+
lines.push('More commitments exist than this roster shows.');
|
|
111
|
+
}
|
|
112
|
+
return lines;
|
|
113
|
+
}
|
|
114
|
+
/** One Commitment's loop, in full. */
|
|
115
|
+
function formatCommitmentLoopStatus(status) {
|
|
116
|
+
const lines = [];
|
|
117
|
+
lines.push(`${status.title} (${status.commitmentId})${status.systemRole ? ` [${status.systemRole}]` : ''}`);
|
|
118
|
+
lines.push(` Loop: ${loopStateLabel(status.loopState)}${status.loopReason ? ` (${status.loopReason})` : ''}`);
|
|
119
|
+
lines.push(` ${status.loopDetail || (0, data_provider_1.describeCommitmentLoopState)(status.loopState)}`);
|
|
120
|
+
lines.push(` Lifecycle: ${status.lifecycleStatus}`);
|
|
121
|
+
lines.push(` Last check: ${when(status.lastCheckAt)}`);
|
|
122
|
+
lines.push(` Last seen: ${when(status.lastSuccessfulObservationAt)}`);
|
|
123
|
+
if (status.lastStop) {
|
|
124
|
+
// `fix` is an optional contract field; read it defensively across package builds.
|
|
125
|
+
const stop = status.lastStop;
|
|
126
|
+
lines.push(` Last stop: ${stop.question}${stop.reason ? ` — ${stop.reason}` : ''}`);
|
|
127
|
+
if (stop.detail)
|
|
128
|
+
lines.push(` ${stop.detail}`);
|
|
129
|
+
if (stop.fix)
|
|
130
|
+
lines.push(` Fix: ${stop.fix}`);
|
|
131
|
+
}
|
|
132
|
+
const wakes = Array.isArray(status.nextWakes) ? status.nextWakes : [];
|
|
133
|
+
lines.push(' Next wakes:');
|
|
134
|
+
if (!wakes.length) {
|
|
135
|
+
lines.push(status.loopState === 'unknown'
|
|
136
|
+
? ' (could not be read)'
|
|
137
|
+
: ' none — nothing is scheduled to wake it');
|
|
138
|
+
}
|
|
139
|
+
for (const wake of wakes) {
|
|
140
|
+
lines.push(` ${when(wake.at)} ${wake.kind}${wake.reason ? ` (${wake.reason})` : ''}`);
|
|
141
|
+
}
|
|
142
|
+
const watching = Array.isArray(status.watching) ? status.watching : [];
|
|
143
|
+
lines.push(' Watching:');
|
|
144
|
+
if (!watching.length)
|
|
145
|
+
lines.push(' nothing declared');
|
|
146
|
+
for (const row of watching) {
|
|
147
|
+
const access = row.access === 'readable'
|
|
148
|
+
? row.completeness === 'partial'
|
|
149
|
+
? 'readable, PARTIAL read'
|
|
150
|
+
: 'readable'
|
|
151
|
+
: row.access === 'blocked'
|
|
152
|
+
? 'CANNOT READ'
|
|
153
|
+
: 'not known';
|
|
154
|
+
lines.push(` ${row.source}${row.scope ? ` (${row.scope})` : ''}: ${access}${row.reason ? ` — ${row.reason}` : ''}`);
|
|
155
|
+
// Optional contract field; read defensively across package builds.
|
|
156
|
+
const limitations = row.limitations;
|
|
157
|
+
if (Array.isArray(limitations) && limitations.length) {
|
|
158
|
+
lines.push(` not watched: ${limitations.join(', ')}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
lines.push(` Open loops: ${count(status.pendingWork?.openLoops)} Pending runs: ${count(status.pendingWork?.pendingRuns)}`);
|
|
162
|
+
lines.push(` Runs today: ${runs(status)} Spend today: ${spend(status)}`);
|
|
163
|
+
return lines;
|
|
164
|
+
}
|
|
@@ -18,7 +18,7 @@ import { type CommitmentObservationsQuery, type CommitmentObservationsResponse }
|
|
|
18
18
|
* "hold this state", derived from a Compass invariant — not authored here).
|
|
19
19
|
*/
|
|
20
20
|
import { COMMITMENT_WATCHED_SOURCES, COMMITMENT_TEMPLATE_IDS, COMMITMENT_CADENCE_MODES, COMMITMENT_CADENCE_TIME_PATTERN, COMMITMENT_CADENCE_MAX_TIMES, COMMITMENT_EXECUTION_ISOLATION_MODES, COMMITMENT_STATUSES, COMMITMENT_KIND_VALUES } from '@skrr-ai/data-provider';
|
|
21
|
-
import type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, CommitmentExecutionReceiptListResponse, CommitmentExecutionReceiptQuarterlyMetricsResponse, CommitmentCapabilitySource, CommitmentDeliveryPatchResponse, CommitmentDeliveryBundleResponse, CommitmentCyclesResponse, CommitmentExplanationResponse, CommitmentRunPermissions } from '@skrr-ai/data-provider';
|
|
21
|
+
import type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, CommitmentExecutionReceiptListResponse, CommitmentExecutionReceiptQuarterlyMetricsResponse, CommitmentCapabilitySource, CommitmentDeliveryPatchResponse, CommitmentDeliveryBundleResponse, CommitmentCyclesResponse, CommitmentExplanationResponse, CommitmentRunPermissions, CommitmentLoopStatus, CommitmentRoster } from '@skrr-ai/data-provider';
|
|
22
22
|
import { withQuery } from './triggers';
|
|
23
23
|
export { COMMITMENT_WATCHED_SOURCES, COMMITMENT_TEMPLATE_IDS, COMMITMENT_CADENCE_MODES, COMMITMENT_CADENCE_TIME_PATTERN, COMMITMENT_CADENCE_MAX_TIMES, COMMITMENT_STATUSES, COMMITMENT_KIND_VALUES, };
|
|
24
24
|
export type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, };
|
|
@@ -223,6 +223,10 @@ export declare const commitmentApi: {
|
|
|
223
223
|
* swept, how stale that is, and the tally it last persisted. Aggregate only.
|
|
224
224
|
*/
|
|
225
225
|
livenessSweep: () => Promise<Record<string, unknown>>;
|
|
226
|
+
/** One agent's Commitments, system roles included, each with its loop status. */
|
|
227
|
+
roster: (agentId: string) => Promise<CommitmentRoster>;
|
|
228
|
+
/** Is this Commitment's loop installed and working. */
|
|
229
|
+
loopStatus: (id: string) => Promise<CommitmentLoopStatus>;
|
|
226
230
|
manifest: (id: string) => Promise<Record<string, unknown>>;
|
|
227
231
|
import: (body: Record<string, unknown>) => Promise<{
|
|
228
232
|
commitment: {
|
|
@@ -247,6 +251,23 @@ export declare const commitmentApi: {
|
|
|
247
251
|
};
|
|
248
252
|
}>;
|
|
249
253
|
get: (id: string) => Promise<CommitmentStatusResponse>;
|
|
254
|
+
controlPreview: (id: string, query: Parameters<typeof withQuery>[1]) => Promise<Record<string, unknown>>;
|
|
255
|
+
applyControl: (id: string, body: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
256
|
+
controlReceipt: (id: string, controlId: string) => Promise<Record<string, unknown>>;
|
|
257
|
+
workPlan: (id: string) => Promise<Record<string, unknown>>;
|
|
258
|
+
observationSummary: (query?: {
|
|
259
|
+
agentId?: string;
|
|
260
|
+
}) => Promise<Record<string, unknown>>;
|
|
261
|
+
draftObservationProbe: (body: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
262
|
+
observationProbe: (id: string, body?: {
|
|
263
|
+
expectedVersion?: number;
|
|
264
|
+
timeoutMs?: number;
|
|
265
|
+
}) => Promise<Record<string, unknown>>;
|
|
266
|
+
verifyReadiness: (id: string, body: {
|
|
267
|
+
expectedVersion: number;
|
|
268
|
+
timeoutMs?: number;
|
|
269
|
+
}) => Promise<Record<string, unknown>>;
|
|
270
|
+
readinessReceipt: (id: string, receiptId: string) => Promise<Record<string, unknown>>;
|
|
250
271
|
create: (body: Record<string, unknown>) => Promise<Commitment>;
|
|
251
272
|
update: (id: string, body: Record<string, unknown>) => Promise<Commitment>;
|
|
252
273
|
draftPreflight: (body: Record<string, unknown>) => Promise<CommitmentPreflightReport>;
|
|
@@ -629,6 +650,8 @@ export type WatchFlagInputs = {
|
|
|
629
650
|
spaceIds?: string[];
|
|
630
651
|
monitorIds?: string[];
|
|
631
652
|
};
|
|
653
|
+
/** Keep the canonical one-binding-per-source contract without discarding conflicting intent. */
|
|
654
|
+
export declare function normalizeWatchedSourceDeclarations<T>(declarations: T[]): T[];
|
|
632
655
|
export declare function buildWatchedSources(inputs: WatchFlagInputs): Array<Record<string, unknown>> | undefined;
|
|
633
656
|
/** The evidence-health shape carried on a check's `inputs`. */
|
|
634
657
|
export type EvidenceHealthView = {
|
|
@@ -718,6 +741,17 @@ export declare function extractStandstillFromCheck(check?: {
|
|
|
718
741
|
* null rather than printing a guess.
|
|
719
742
|
*/
|
|
720
743
|
export declare function describeExecutorBlocked(commitment: CommitmentView): string | null;
|
|
744
|
+
/**
|
|
745
|
+
* The commitment `show` should render: its stored contract, with the
|
|
746
|
+
* assessment replaced by the one the operating state recomputed for this read
|
|
747
|
+
* when the server sent one (OSK-15989). The stored `commitment.assessment` is
|
|
748
|
+
* what the LAST check wrote; while a run is in flight it can still say
|
|
749
|
+
* `blocked`, and printing it above "Agent is working" made the header
|
|
750
|
+
* contradict the rest of the page. `doctor` already reads the live one first.
|
|
751
|
+
*/
|
|
752
|
+
export declare function withLiveAssessment(commitment: CommitmentView, operatingState?: {
|
|
753
|
+
assessment?: unknown;
|
|
754
|
+
} | null): CommitmentView;
|
|
721
755
|
export declare function renderCommitmentSummary(commitment: CommitmentView, log: (line: string) => void,
|
|
722
756
|
/**
|
|
723
757
|
* The most recent check, when the caller has one. Optional because pause /
|
|
@@ -757,6 +791,7 @@ type ReadModelRecord = Record<string, unknown>;
|
|
|
757
791
|
/** Human view for `commitments ledger`; JSON remains the automation surface. */
|
|
758
792
|
export declare function renderCommitmentLedger(ledger: ReadModelRecord, log: (line: string) => void): void;
|
|
759
793
|
export declare function renderCommitmentTrace(trace: ReadModelRecord, log: (line: string) => void): void;
|
|
794
|
+
export declare function renderProactivenessScorecard(scorecard: ReadModelRecord, log: (line: string) => void): void;
|
|
760
795
|
/**
|
|
761
796
|
* One line per Cycle:
|
|
762
797
|
* `09-22 12:04 ● stopped act commitment_execution_budget_exhausted — Raise maxRunsPerDay…`
|
|
@@ -774,6 +809,17 @@ export declare function renderListPageHint(page: {
|
|
|
774
809
|
has_more?: boolean;
|
|
775
810
|
next_cursor?: string | null;
|
|
776
811
|
} | undefined, log: (line: string) => void): void;
|
|
812
|
+
/**
|
|
813
|
+
* Whether a row's retained evidence can still be reopened (OSK-16125).
|
|
814
|
+
*
|
|
815
|
+
* The count alone read as evidence even when every path pointed into a
|
|
816
|
+
* worktree the daemon had already deleted. `retained` artifacts are git
|
|
817
|
+
* locators on the run's delivery commit; `ephemeral` ones cannot be counted
|
|
818
|
+
* on; `unconfirmed` are locators for a path the run did not change. Refs the
|
|
819
|
+
* server classified as none of these (URLs, hashes, legacy rows) count as
|
|
820
|
+
* `other`. `--json` carries each artifact's `ref`, `locator` and `originalRef`.
|
|
821
|
+
*/
|
|
822
|
+
export declare function describeObservationArtifacts(artifacts: unknown): string;
|
|
777
823
|
export declare function renderCommitmentObservations(response: ReadModelRecord, log: (line: string) => void, options?: {
|
|
778
824
|
emptyMessage?: string;
|
|
779
825
|
}): void;
|