@skrr-ai/cli 0.1.127 → 0.1.129
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 +35 -0
- package/dist/base-command.js +107 -0
- package/dist/commands/agenda/trigger/list.d.ts +2 -1
- package/dist/commands/agenda/trigger/list.js +55 -6
- package/dist/commands/agents/chat.js +7 -0
- package/dist/commands/agents/create.js +3 -1
- package/dist/commands/browser/persistent-profile.d.ts +22 -0
- package/dist/commands/browser/persistent-profile.js +46 -0
- package/dist/commands/commitments/action-history.js +1 -1
- package/dist/commands/commitments/cases.js +3 -3
- package/dist/commands/commitments/check-now.d.ts +10 -2
- package/dist/commands/commitments/check-now.js +53 -3
- package/dist/commands/commitments/create.d.ts +6 -14
- package/dist/commands/commitments/create.js +64 -7
- package/dist/commands/commitments/doctor.js +3 -1
- package/dist/commands/commitments/effective-policy.d.ts +11 -1
- package/dist/commands/commitments/effective-policy.js +90 -4
- package/dist/commands/commitments/explain.js +10 -1
- package/dist/commands/commitments/hypotheses.js +12 -12
- package/dist/commands/commitments/next-tick.js +5 -0
- package/dist/commands/commitments/observations.js +18 -17
- package/dist/commands/commitments/pack/list.js +2 -1
- package/dist/commands/commitments/pack/plan.d.ts +6 -0
- package/dist/commands/commitments/pack/plan.js +19 -0
- package/dist/commands/commitments/plan.d.ts +14 -0
- package/dist/commands/commitments/plan.js +32 -0
- package/dist/commands/commitments/preflight.d.ts +20 -1
- package/dist/commands/commitments/preflight.js +118 -12
- package/dist/commands/commitments/show.d.ts +9 -0
- package/dist/commands/commitments/show.js +14 -1
- package/dist/commands/commitments/trigger-status.js +8 -0
- package/dist/commands/commitments/update.d.ts +1 -0
- package/dist/commands/commitments/update.js +45 -4
- package/dist/commands/commitments/wake-capabilities.js +13 -0
- package/dist/commands/compass/archive.js +4 -0
- package/dist/commands/compass/commitments.js +15 -1
- package/dist/commands/compass/create.js +11 -3
- package/dist/commands/compass/effective-policy.d.ts +1 -0
- package/dist/commands/compass/effective-policy.js +8 -7
- package/dist/commands/compass/revert.d.ts +8 -0
- package/dist/commands/compass/revert.js +25 -1
- package/dist/commands/compass/revisions.d.ts +6 -0
- package/dist/commands/compass/revisions.js +26 -2
- package/dist/commands/compass/tactic.d.ts +10 -3
- package/dist/commands/compass/tactic.js +22 -7
- package/dist/commands/compass/update.js +19 -3
- package/dist/commands/followups/act.js +1 -1
- package/dist/commands/followups/cancel.js +13 -0
- package/dist/commands/followups/observability.js +20 -1
- package/dist/commands/followups/plans/create.js +12 -1
- package/dist/commands/followups/show.js +13 -0
- package/dist/commands/followups/watch.js +1 -1
- package/dist/commands/goals/planner-config.d.ts +11 -0
- package/dist/commands/goals/planner-config.js +16 -0
- package/dist/commands/harnesses/list.js +1 -1
- package/dist/commands/machines/update.d.ts +5 -3
- package/dist/commands/machines/update.js +70 -9
- package/dist/commands/northstars/create.js +3 -1
- package/dist/commands/northstars/governance/configure.d.ts +4 -0
- package/dist/commands/northstars/governance/configure.js +76 -10
- package/dist/commands/northstars/intents/decide.d.ts +6 -0
- package/dist/commands/northstars/intents/decide.js +68 -15
- package/dist/commands/northstars/intents/list.d.ts +2 -1
- package/dist/commands/northstars/intents/list.js +15 -5
- package/dist/commands/northstars/intents.d.ts +26 -0
- package/dist/commands/northstars/intents.js +49 -0
- package/dist/commands/northstars/list.d.ts +1 -0
- package/dist/commands/northstars/list.js +24 -3
- package/dist/commands/northstars/recommendations/list.d.ts +1 -1
- package/dist/commands/northstars/recommendations/list.js +3 -3
- package/dist/commands/northstars/recommendations.d.ts +19 -0
- package/dist/commands/northstars/recommendations.js +42 -0
- package/dist/commands/northstars/review-now.d.ts +1 -0
- package/dist/commands/northstars/review-now.js +15 -4
- package/dist/commands/northstars/reviews.d.ts +1 -0
- package/dist/commands/northstars/reviews.js +34 -6
- package/dist/commands/northstars/update.js +8 -1
- package/dist/commands/proposals/list.js +11 -2
- package/dist/commands/proposals/show.js +9 -1
- package/dist/commands/spaces/auto-executor/preview.d.ts +14 -1
- package/dist/commands/spaces/auto-executor/preview.js +35 -1
- package/dist/commands/spaces/auto-executor/run.d.ts +17 -0
- package/dist/commands/spaces/auto-executor/run.js +60 -2
- package/dist/commands/spaces/auto-executor/runs.d.ts +9 -1
- package/dist/commands/spaces/auto-executor/runs.js +18 -1
- package/dist/commands/spaces/files/upload.js +1 -2
- package/dist/commands/spaces/heartbeats/create.js +7 -5
- package/dist/commands/spaces/heartbeats/update.js +5 -3
- package/dist/commands/spaces/index.js +23 -0
- package/dist/commands/store/artifacts/releases.d.ts +20 -0
- package/dist/commands/store/artifacts/releases.js +85 -0
- package/dist/commands/store/library.d.ts +14 -0
- package/dist/commands/store/library.js +71 -0
- package/dist/commands/tasks/list.d.ts +48 -0
- package/dist/commands/tasks/list.js +141 -9
- package/dist/commands/tasks/remind.js +23 -11
- package/dist/commands/tasks/retry-schedule.js +6 -3
- package/dist/commands/tasks/schedule.js +29 -7
- package/dist/commands/tasks/show.js +4 -0
- package/dist/generated/agent-guides.json +69 -69
- package/dist/lib/agent-trigger-listing.d.ts +26 -0
- package/dist/lib/agent-trigger-listing.js +63 -0
- package/dist/lib/agentic-stream.d.ts +9 -0
- package/dist/lib/agentic-stream.js +152 -41
- package/dist/lib/command-miss.js +11 -2
- package/dist/lib/commitment-attention-copy.d.ts +96 -0
- package/dist/lib/commitment-attention-copy.js +209 -0
- package/dist/lib/commitment-ledgers.js +3 -1
- package/dist/lib/commitment-loop-status.d.ts +6 -0
- package/dist/lib/commitment-loop-status.js +16 -6
- package/dist/lib/commitments.d.ts +112 -0
- package/dist/lib/commitments.js +250 -2
- package/dist/lib/compass-body-help.d.ts +20 -0
- package/dist/lib/compass-body-help.js +61 -0
- package/dist/lib/compass-refusals.d.ts +35 -0
- package/dist/lib/compass-refusals.js +50 -0
- package/dist/lib/compasses.d.ts +82 -4
- package/dist/lib/compasses.js +232 -12
- package/dist/lib/followups.d.ts +22 -1
- package/dist/lib/followups.js +21 -1
- package/dist/lib/format.d.ts +11 -0
- package/dist/lib/format.js +29 -0
- package/dist/lib/initiatives.d.ts +9 -2
- package/dist/lib/initiatives.js +13 -2
- package/dist/lib/iso-instant.d.ts +52 -0
- package/dist/lib/iso-instant.js +162 -0
- package/dist/lib/machines.d.ts +14 -1
- package/dist/lib/machines.js +24 -0
- package/dist/lib/northstars.d.ts +201 -24
- package/dist/lib/northstars.js +655 -27
- package/dist/lib/proposal-decision-command.js +21 -1
- package/dist/lib/proposals.d.ts +26 -1
- package/dist/lib/proposals.js +167 -0
- package/dist/lib/rate-limit-retry.d.ts +5 -0
- package/dist/lib/rate-limit-retry.js +19 -0
- package/dist/lib/roles.d.ts +1 -1
- package/dist/lib/space-charter.js +9 -0
- package/dist/lib/store-artifact-releases.d.ts +39 -0
- package/dist/lib/store-artifact-releases.js +12 -0
- package/dist/lib/store-library.d.ts +37 -0
- package/dist/lib/store-library.js +12 -0
- package/dist/lib/task-asset-upload.js +1 -2
- package/dist/lib/task-calendar.d.ts +19 -0
- package/dist/lib/task-calendar.js +72 -0
- package/dist/lib/task-recurrence-outcome.js +3 -1
- package/dist/lib/task-recurrence-summary.d.ts +15 -0
- package/dist/lib/task-recurrence-summary.js +228 -0
- package/dist/lib/task-reminder.d.ts +28 -0
- package/dist/lib/task-reminder.js +50 -0
- package/dist/lib/triggers.d.ts +13 -2
- package/dist/lib/triggers.js +31 -13
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +11 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.d.ts +123 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.js +160 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +17 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +11 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.d.ts +123 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.js +173 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +6922 -6828
- package/oclif.manifest.json +612 -62
- package/package.json +4 -4
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One reading of "an ISO-8601 UTC instant" for every CLI flag that takes one.
|
|
3
|
+
*
|
|
4
|
+
* `tasks remind --at` and `tasks schedule --at` each had their own: remind ran
|
|
5
|
+
* `new Date(value)` behind a `/^\d{4}-\d{2}-\d{2}T/` check, and schedule forwarded
|
|
6
|
+
* the string and printed the server's zod issue. `new Date()` is the wrong tool
|
|
7
|
+
* for an instant, in two ways that both stored a different time than the one
|
|
8
|
+
* typed and said nothing (OSK-21504, OSK-21506):
|
|
9
|
+
*
|
|
10
|
+
* - a time with no zone is read in the zone of the MACHINE running the CLI, so
|
|
11
|
+
* the same command stored different instants on different laptops;
|
|
12
|
+
* - a day that does not exist overflows into the next month
|
|
13
|
+
* (`2027-02-30` is `2027-03-02`).
|
|
14
|
+
*
|
|
15
|
+
* The rule here is the one `tasks schedule --help` already states and the server's
|
|
16
|
+
* `z.string().datetime()` enforces: a calendar-real date, a time with seconds, and
|
|
17
|
+
* a literal `Z`. A numeric offset is refused too, even though it names an instant:
|
|
18
|
+
* the two commands must agree, and the server's schedule door does not take one.
|
|
19
|
+
*
|
|
20
|
+
* Never reads the machine's zone. Pure.
|
|
21
|
+
*/
|
|
22
|
+
export type InstantProblem = 'not_a_date' | 'date_only' | 'no_zone' | 'numeric_offset' | 'not_a_real_date' | 'not_a_real_time';
|
|
23
|
+
export type InstantParse = {
|
|
24
|
+
ok: true;
|
|
25
|
+
date: Date;
|
|
26
|
+
iso: string;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
problem: InstantProblem;
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Parse a flag value as a UTC instant, or say precisely what is wrong with it.
|
|
34
|
+
*
|
|
35
|
+
* `label` is what the user typed (`--at`, `scheduledFor`), so the message names
|
|
36
|
+
* their input rather than a REST field they never saw.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseUtcInstant(raw: string, label?: string): InstantParse;
|
|
39
|
+
/** `2027-02-02T09:00:00Z` - the instant in UTC, whole seconds when there are no milliseconds. */
|
|
40
|
+
export declare function formatUtcInstant(date: Date): string;
|
|
41
|
+
/**
|
|
42
|
+
* `2027-02-02 01:00:00 PST` - the same instant on this machine's wall clock, with the
|
|
43
|
+
* zone NAMED. `toLocaleString()` printed neither the zone nor anything that mapped back
|
|
44
|
+
* to the instant that was typed (OSK-21505). `timeZone` is for tests and defaults to
|
|
45
|
+
* the machine's own.
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatLocalInstant(date: Date, timeZone?: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* The instant for a person: UTC first (it is what was typed and what is stored), then the
|
|
50
|
+
* local reading with its zone name. A machine already on UTC gets the UTC form alone.
|
|
51
|
+
*/
|
|
52
|
+
export declare function describeInstant(date: Date, timeZone?: string): string;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* One reading of "an ISO-8601 UTC instant" for every CLI flag that takes one.
|
|
4
|
+
*
|
|
5
|
+
* `tasks remind --at` and `tasks schedule --at` each had their own: remind ran
|
|
6
|
+
* `new Date(value)` behind a `/^\d{4}-\d{2}-\d{2}T/` check, and schedule forwarded
|
|
7
|
+
* the string and printed the server's zod issue. `new Date()` is the wrong tool
|
|
8
|
+
* for an instant, in two ways that both stored a different time than the one
|
|
9
|
+
* typed and said nothing (OSK-21504, OSK-21506):
|
|
10
|
+
*
|
|
11
|
+
* - a time with no zone is read in the zone of the MACHINE running the CLI, so
|
|
12
|
+
* the same command stored different instants on different laptops;
|
|
13
|
+
* - a day that does not exist overflows into the next month
|
|
14
|
+
* (`2027-02-30` is `2027-03-02`).
|
|
15
|
+
*
|
|
16
|
+
* The rule here is the one `tasks schedule --help` already states and the server's
|
|
17
|
+
* `z.string().datetime()` enforces: a calendar-real date, a time with seconds, and
|
|
18
|
+
* a literal `Z`. A numeric offset is refused too, even though it names an instant:
|
|
19
|
+
* the two commands must agree, and the server's schedule door does not take one.
|
|
20
|
+
*
|
|
21
|
+
* Never reads the machine's zone. Pure.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.parseUtcInstant = parseUtcInstant;
|
|
25
|
+
exports.formatUtcInstant = formatUtcInstant;
|
|
26
|
+
exports.formatLocalInstant = formatLocalInstant;
|
|
27
|
+
exports.describeInstant = describeInstant;
|
|
28
|
+
const EXAMPLE = '2026-12-01T09:00:00Z';
|
|
29
|
+
const UTC_INSTANT = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?Z$/;
|
|
30
|
+
const ZONELESS = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(\.\d+)?)?$/;
|
|
31
|
+
const OFFSET = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(\.\d+)?)?([+-])(\d{2}):?(\d{2})$/;
|
|
32
|
+
const DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
33
|
+
const MONTH_NAMES = [
|
|
34
|
+
'January',
|
|
35
|
+
'February',
|
|
36
|
+
'March',
|
|
37
|
+
'April',
|
|
38
|
+
'May',
|
|
39
|
+
'June',
|
|
40
|
+
'July',
|
|
41
|
+
'August',
|
|
42
|
+
'September',
|
|
43
|
+
'October',
|
|
44
|
+
'November',
|
|
45
|
+
'December',
|
|
46
|
+
];
|
|
47
|
+
function daysInMonth(year, month) {
|
|
48
|
+
return new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* What is wrong with the calendar part, or `null` when the date exists.
|
|
52
|
+
* Checked by construction rather than by `new Date()`, which accepts the overflow.
|
|
53
|
+
*/
|
|
54
|
+
function calendarProblem(year, month, day) {
|
|
55
|
+
if (month < 1 || month > 12)
|
|
56
|
+
return `month ${String(month).padStart(2, '0')} does not exist`;
|
|
57
|
+
const last = daysInMonth(year, month);
|
|
58
|
+
if (day < 1 || day > last) {
|
|
59
|
+
return `${MONTH_NAMES[month - 1]} ${year} has ${last} days, so day ${String(day).padStart(2, '0')} does not exist`;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
function clockProblem(hour, minute, second) {
|
|
64
|
+
if (hour > 23 || minute > 59 || second > 59) {
|
|
65
|
+
return `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')} is not a time of day`;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
function rule(label) {
|
|
70
|
+
return `${label} must be an ISO-8601 UTC time ending in Z, for example ${EXAMPLE}`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse a flag value as a UTC instant, or say precisely what is wrong with it.
|
|
74
|
+
*
|
|
75
|
+
* `label` is what the user typed (`--at`, `scheduledFor`), so the message names
|
|
76
|
+
* their input rather than a REST field they never saw.
|
|
77
|
+
*/
|
|
78
|
+
function parseUtcInstant(raw, label = '--at') {
|
|
79
|
+
const value = String(raw ?? '').trim();
|
|
80
|
+
const fail = (problem, reason) => ({
|
|
81
|
+
ok: false,
|
|
82
|
+
problem,
|
|
83
|
+
message: `${rule(label)}. ${reason}`,
|
|
84
|
+
});
|
|
85
|
+
const utc = UTC_INSTANT.exec(value);
|
|
86
|
+
if (utc) {
|
|
87
|
+
const [year, month, day, hour, minute, second] = utc.slice(1, 7).map(Number);
|
|
88
|
+
const calendar = calendarProblem(year, month, day);
|
|
89
|
+
if (calendar)
|
|
90
|
+
return fail('not_a_real_date', `"${value}" is not a real date: ${calendar}.`);
|
|
91
|
+
const clock = clockProblem(hour, minute, second);
|
|
92
|
+
if (clock)
|
|
93
|
+
return fail('not_a_real_time', `"${value}" is not a real time: ${clock}.`);
|
|
94
|
+
const date = new Date(value);
|
|
95
|
+
if (Number.isNaN(date.getTime())) {
|
|
96
|
+
return fail('not_a_date', `"${value}" is not a date.`);
|
|
97
|
+
}
|
|
98
|
+
return { ok: true, date, iso: date.toISOString() };
|
|
99
|
+
}
|
|
100
|
+
const zoneless = ZONELESS.exec(value);
|
|
101
|
+
if (zoneless) {
|
|
102
|
+
return fail('no_zone', `"${value}" has no time zone, so it could mean a different moment on each machine. ` +
|
|
103
|
+
`Add Z if it is UTC, or convert it to UTC first.`);
|
|
104
|
+
}
|
|
105
|
+
const offset = OFFSET.exec(value);
|
|
106
|
+
if (offset) {
|
|
107
|
+
const [year, month, day, hour, minute] = offset.slice(1, 6).map(Number);
|
|
108
|
+
const second = Number(offset[6] ?? 0);
|
|
109
|
+
const sign = offset[8] === '-' ? -1 : 1;
|
|
110
|
+
const shiftMinutes = sign * (Number(offset[9]) * 60 + Number(offset[10]));
|
|
111
|
+
let converted = '';
|
|
112
|
+
if (!calendarProblem(year, month, day) && !clockProblem(hour, minute, second)) {
|
|
113
|
+
const at = new Date(Date.UTC(year, month - 1, day, hour, minute, second) - shiftMinutes * 60_000);
|
|
114
|
+
converted = ` (${value} is ${at.toISOString().replace(/\.000Z$/, 'Z')})`;
|
|
115
|
+
}
|
|
116
|
+
return fail('numeric_offset', `Numeric offsets such as ${offset[8]}${offset[9]}:${offset[10]} are not accepted; convert the time to UTC and end it with Z${converted}.`);
|
|
117
|
+
}
|
|
118
|
+
const dateOnly = DATE_ONLY.exec(value);
|
|
119
|
+
if (dateOnly) {
|
|
120
|
+
const calendar = calendarProblem(Number(dateOnly[1]), Number(dateOnly[2]), Number(dateOnly[3]));
|
|
121
|
+
return fail(calendar ? 'not_a_real_date' : 'date_only', calendar
|
|
122
|
+
? `"${value}" is not a real date: ${calendar}.`
|
|
123
|
+
: `"${value}" is a date without a time; add a time of day, e.g. ${value}T09:00:00Z.`);
|
|
124
|
+
}
|
|
125
|
+
return fail('not_a_date', `"${value}" is not an ISO-8601 date and time.`);
|
|
126
|
+
}
|
|
127
|
+
/** `2027-02-02T09:00:00Z` - the instant in UTC, whole seconds when there are no milliseconds. */
|
|
128
|
+
function formatUtcInstant(date) {
|
|
129
|
+
return date.toISOString().replace(/\.000Z$/, 'Z');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* `2027-02-02 01:00:00 PST` - the same instant on this machine's wall clock, with the
|
|
133
|
+
* zone NAMED. `toLocaleString()` printed neither the zone nor anything that mapped back
|
|
134
|
+
* to the instant that was typed (OSK-21505). `timeZone` is for tests and defaults to
|
|
135
|
+
* the machine's own.
|
|
136
|
+
*/
|
|
137
|
+
function formatLocalInstant(date, timeZone) {
|
|
138
|
+
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
139
|
+
...(timeZone ? { timeZone } : {}),
|
|
140
|
+
year: 'numeric',
|
|
141
|
+
month: '2-digit',
|
|
142
|
+
day: '2-digit',
|
|
143
|
+
hour: '2-digit',
|
|
144
|
+
minute: '2-digit',
|
|
145
|
+
second: '2-digit',
|
|
146
|
+
hourCycle: 'h23',
|
|
147
|
+
timeZoneName: 'short',
|
|
148
|
+
}).formatToParts(date);
|
|
149
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? '';
|
|
150
|
+
return `${get('year')}-${get('month')}-${get('day')} ${get('hour')}:${get('minute')}:${get('second')} ${get('timeZoneName')}`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The instant for a person: UTC first (it is what was typed and what is stored), then the
|
|
154
|
+
* local reading with its zone name. A machine already on UTC gets the UTC form alone.
|
|
155
|
+
*/
|
|
156
|
+
function describeInstant(date, timeZone) {
|
|
157
|
+
const utc = formatUtcInstant(date);
|
|
158
|
+
const local = formatLocalInstant(date, timeZone);
|
|
159
|
+
if (/ (UTC|GMT)$/.test(local))
|
|
160
|
+
return utc;
|
|
161
|
+
return `${utc} (${local})`;
|
|
162
|
+
}
|
package/dist/lib/machines.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DaemonContactState, DaemonMaintenanceSummary } from '@skrr-ai/data-provider';
|
|
1
|
+
import type { DaemonContactState, DaemonMaintenanceSummary, MachineIcon, MachineIconPatch } from '@skrr-ai/data-provider';
|
|
2
2
|
/**
|
|
3
3
|
* machines.ts — request client for `/api/machines`.
|
|
4
4
|
*
|
|
@@ -134,6 +134,7 @@ export interface Machine {
|
|
|
134
134
|
name?: string;
|
|
135
135
|
description?: string;
|
|
136
136
|
tags?: string[];
|
|
137
|
+
icon?: MachineIcon;
|
|
137
138
|
};
|
|
138
139
|
lease: Record<string, unknown> | null;
|
|
139
140
|
controls: {
|
|
@@ -271,7 +272,19 @@ export interface MachinePreferencesPatch {
|
|
|
271
272
|
name?: string;
|
|
272
273
|
description?: string;
|
|
273
274
|
tags?: string[];
|
|
275
|
+
/** A preset, or null for the default. An uploaded image is not set by a patch. */
|
|
276
|
+
icon?: MachineIconPatch;
|
|
274
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* The value of `--icon`: a preset's id, or `none` (also `default`) to go back to
|
|
280
|
+
* the default. Throws a sentence that names the valid ids, because the only other
|
|
281
|
+
* way to learn them would be to send a wrong one and read the server's refusal.
|
|
282
|
+
* An uploaded image is a different flag (`--icon-file`): a name that is not a
|
|
283
|
+
* preset is never guessed to be a path.
|
|
284
|
+
*/
|
|
285
|
+
export declare function parseMachineIconFlag(value: string): MachineIconPatch;
|
|
286
|
+
/** What `machines show`/`update` print for an icon: the preset's id, or what kind of image. */
|
|
287
|
+
export declare function describeMachineIcon(icon: MachineIcon | undefined): string;
|
|
275
288
|
/**
|
|
276
289
|
* How many of a machine's harnesses still represent a capability it has.
|
|
277
290
|
*
|
package/dist/lib/machines.js
CHANGED
|
@@ -10,6 +10,8 @@ exports.harnessStateLabel = harnessStateLabel;
|
|
|
10
10
|
exports.summarizeDaemons = summarizeDaemons;
|
|
11
11
|
exports.isThisComputer = isThisComputer;
|
|
12
12
|
exports.machineListView = machineListView;
|
|
13
|
+
exports.parseMachineIconFlag = parseMachineIconFlag;
|
|
14
|
+
exports.describeMachineIcon = describeMachineIcon;
|
|
13
15
|
exports.liveHarnessCount = liveHarnessCount;
|
|
14
16
|
exports.listMachines = listMachines;
|
|
15
17
|
exports.getMachine = getMachine;
|
|
@@ -229,6 +231,28 @@ function machineListView(machine, options) {
|
|
|
229
231
|
...(hidden > 0 ? { hiddenHarnessCount: hidden } : {}),
|
|
230
232
|
};
|
|
231
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* The value of `--icon`: a preset's id, or `none` (also `default`) to go back to
|
|
236
|
+
* the default. Throws a sentence that names the valid ids, because the only other
|
|
237
|
+
* way to learn them would be to send a wrong one and read the server's refusal.
|
|
238
|
+
* An uploaded image is a different flag (`--icon-file`): a name that is not a
|
|
239
|
+
* preset is never guessed to be a path.
|
|
240
|
+
*/
|
|
241
|
+
function parseMachineIconFlag(value) {
|
|
242
|
+
const id = value.trim().toLowerCase();
|
|
243
|
+
if (id === 'none' || id === 'default')
|
|
244
|
+
return null;
|
|
245
|
+
if ((0, data_provider_1.isMachineIconPresetId)(id))
|
|
246
|
+
return { kind: 'preset', id };
|
|
247
|
+
throw new Error(`--icon: "${value}" is not an icon. Choose one of ${data_provider_1.MACHINE_ICON_PRESET_IDS.join(', ')}, ` +
|
|
248
|
+
'or "none" to go back to the default. To use your own image, pass --icon-file <path>.');
|
|
249
|
+
}
|
|
250
|
+
/** What `machines show`/`update` print for an icon: the preset's id, or what kind of image. */
|
|
251
|
+
function describeMachineIcon(icon) {
|
|
252
|
+
if (!icon)
|
|
253
|
+
return 'default';
|
|
254
|
+
return icon.kind === 'preset' ? icon.id : 'uploaded image';
|
|
255
|
+
}
|
|
232
256
|
/**
|
|
233
257
|
* How many of a machine's harnesses still represent a capability it has.
|
|
234
258
|
*
|
package/dist/lib/northstars.d.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* northstars.ts — request-based client for the Northstar portfolio layer
|
|
3
|
-
* (`/api/northstars/*`) and its Portfolio Governor.
|
|
4
|
-
*
|
|
5
|
-
* A **Northstar** groups and prioritizes many Commitments without owning their
|
|
6
|
-
* loop. The **Governor** is a MODE of its periodic review, not a separate
|
|
7
|
-
* entity: a review rolls portfolio health up, allocates each Commitment a
|
|
8
|
-
* cadence band and run budget, and emits TYPED management intents that a single
|
|
9
|
-
* router turns into `CommitmentControl` mutations — advisory, awaiting a human,
|
|
10
|
-
* or (narrowly) automatic.
|
|
11
|
-
*
|
|
12
|
-
* Two dials, deliberately separate:
|
|
13
|
-
* - `analysisMode` — does an Agent get to think about this portfolio?
|
|
14
|
-
* - `executionMode` — how much write authority does the outcome carry?
|
|
15
|
-
*
|
|
16
|
-
* Both default to the safe end (`deterministic` / `advisory`), which is exactly
|
|
17
|
-
* what a Northstar did before the Governor existed.
|
|
18
|
-
*
|
|
19
|
-
* Every vocabulary below is RE-EXPORTED from `@skrr-ai/data-provider`, never
|
|
20
|
-
* re-declared. The API validates against those exact strings; a second copy here
|
|
21
|
-
* is how the CLI silently drifts from the server that rejects it.
|
|
22
|
-
*/
|
|
23
1
|
import { NORTHSTAR_ANALYSIS_MODES, NORTHSTAR_APPROVAL_TRIGGERS, NORTHSTAR_EXECUTION_MODES, NORTHSTAR_INTENT_VERDICTS, NORTHSTAR_MANAGEMENT_INTENT_KINDS, NORTHSTAR_REVIEW_STATUSES } from '@skrr-ai/data-provider';
|
|
24
2
|
import type { Northstar, NorthstarAnalysisMode, NorthstarExecutionMode, NorthstarGovernance, NorthstarGovernanceStatus, NorthstarGovernanceUpdateParams, NorthstarListResponse, NorthstarManagementIntent, NorthstarManagementIntentKind, NorthstarRecommendation, NorthstarReviewRecord, NorthstarStatusResponse } from '@skrr-ai/data-provider';
|
|
25
3
|
import { withQuery } from './triggers';
|
|
@@ -33,6 +11,20 @@ export type { Northstar, NorthstarAnalysisMode, NorthstarExecutionMode, Northsta
|
|
|
33
11
|
export declare const NORTHSTAR_STATUSES: readonly ["active", "paused", "achieved", "archived"];
|
|
34
12
|
export declare const NORTHSTAR_PRIORITY_TIERS: readonly ["critical", "high", "medium", "low"];
|
|
35
13
|
export declare const NORTHSTAR_RECOMMENDATION_STATUSES: readonly ["open", "applied", "dismissed"];
|
|
14
|
+
export declare function intentRisk(intent: {
|
|
15
|
+
riskLevel?: string | null;
|
|
16
|
+
} | null | undefined): string;
|
|
17
|
+
export declare function shortReviewId(id: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* What a configure that changed the allocation inputs (the run budget, the critical reserve, the
|
|
20
|
+
* cadence band) says it did to the linked commitments. Additive on the server: absent from an
|
|
21
|
+
* older server, `allocationsPending` only when non-zero, `allocationsRefreshFailed` only on failure.
|
|
22
|
+
*/
|
|
23
|
+
export type AllocationRefreshFields = {
|
|
24
|
+
allocationsRefreshed?: number;
|
|
25
|
+
allocationsPending?: number;
|
|
26
|
+
allocationsRefreshFailed?: boolean;
|
|
27
|
+
};
|
|
36
28
|
export declare const northstarApi: {
|
|
37
29
|
list: (query?: Parameters<typeof withQuery>[1]) => Promise<NorthstarListResponse>;
|
|
38
30
|
create: (body: Record<string, unknown>) => Promise<Northstar>;
|
|
@@ -51,23 +43,208 @@ export declare const northstarApi: {
|
|
|
51
43
|
northstarId: string;
|
|
52
44
|
northstarVersion: number;
|
|
53
45
|
governance: NorthstarGovernance;
|
|
54
|
-
}>;
|
|
46
|
+
} & AllocationRefreshFields>;
|
|
55
47
|
reviews: (id: string, query?: Parameters<typeof withQuery>[1]) => Promise<{
|
|
56
48
|
data: NorthstarReviewRecord[];
|
|
49
|
+
has_more?: boolean;
|
|
57
50
|
}>;
|
|
58
51
|
review: (id: string, reviewId: string) => Promise<NorthstarReviewRecord>;
|
|
59
52
|
reviewNow: (id: string) => Promise<Record<string, unknown>>;
|
|
60
53
|
intents: (id: string, query?: Parameters<typeof withQuery>[1]) => Promise<{
|
|
61
54
|
data: NorthstarManagementIntent[];
|
|
55
|
+
has_more?: boolean;
|
|
62
56
|
}>;
|
|
63
57
|
decideIntent: (id: string, intentId: string, body: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
64
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* One review, from the id a person typed. The full id is asked for first, exactly as before. Only when
|
|
61
|
+
* the server has no review of that exact id is the typed text read as the start of one, among the
|
|
62
|
+
* northstar's newest 100 reviews: that is what the REVIEW column of `intents list` prints
|
|
63
|
+
* (`shortReviewId`), so the table's own output can be pasted back. A prefix of several reviews is
|
|
64
|
+
* reported, not guessed; one of none, or of a review older than the newest 100, raises the server's
|
|
65
|
+
* original "not found". Both ids are in `--json`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function lookupReview(northstarId: string, typed: string): Promise<{
|
|
68
|
+
review: NorthstarReviewRecord;
|
|
69
|
+
} | {
|
|
70
|
+
ambiguous: string[];
|
|
71
|
+
}>;
|
|
65
72
|
/** ms → a short human duration, for a table cell that must stay narrow. */
|
|
66
73
|
export declare function humanMs(ms?: number): string;
|
|
67
74
|
export declare function shortDate(value?: string): string;
|
|
75
|
+
export declare const NORTHSTAR_REASON_WORDS: Readonly<Record<string, string>>;
|
|
76
|
+
/** A code in words; an unknown code comes back unchanged, an absent one says so. */
|
|
77
|
+
export declare function describeNorthstarReason(code: string | null | undefined): string;
|
|
78
|
+
export type NorthstarDecisionContext = {
|
|
79
|
+
northstarId: string;
|
|
80
|
+
intentId: string;
|
|
81
|
+
decision: 'approve' | 'reject';
|
|
82
|
+
/** The CLI binary name, for the command a sentence tells the reader to run. */
|
|
83
|
+
bin?: string;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* A refused decision, as one sentence with its next step.
|
|
87
|
+
*
|
|
88
|
+
* `body` is the server's refusal (`reason`, plus the context it adds: the two
|
|
89
|
+
* northstar versions, or when and by whom the intent was already decided).
|
|
90
|
+
*/
|
|
91
|
+
export declare function describeDecisionRefusal(body: Record<string, unknown>, ctx: NorthstarDecisionContext): {
|
|
92
|
+
code: string;
|
|
93
|
+
text: string;
|
|
94
|
+
};
|
|
95
|
+
export type NorthstarDecisionOutcome = {
|
|
96
|
+
/** The arrow line (`nsi_x → applied`), printed before any explanation. */
|
|
97
|
+
headline: string;
|
|
98
|
+
/** 0 only when the thing asked for now holds. */
|
|
99
|
+
exitCode: 0 | 1;
|
|
100
|
+
/** What to say after the headline. */
|
|
101
|
+
text?: string;
|
|
102
|
+
/** The raw code behind a non-zero exit, for `--json` and `Code:`. */
|
|
103
|
+
code?: string;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* What a decision that the server ACCEPTED (HTTP 200) actually did.
|
|
107
|
+
*
|
|
108
|
+
* One exit rule: an approval exits 0 only when the intent is `applied`, and a
|
|
109
|
+
* rejection only when it is `rejected`. An approval the version fence
|
|
110
|
+
* invalidated, or one whose change has not landed, used to print a line shaped
|
|
111
|
+
* like success and exit 0, so a script could not tell it from one that worked.
|
|
112
|
+
*/
|
|
113
|
+
export declare function describeDecisionOutcome(result: Record<string, unknown>, ctx: NorthstarDecisionContext): NorthstarDecisionOutcome;
|
|
114
|
+
/** What the server returned before `--limit` existed; sent explicitly so a page is never silently smaller. */
|
|
115
|
+
export declare const NORTHSTAR_LIST_DEFAULT_LIMIT = 50;
|
|
116
|
+
/**
|
|
117
|
+
* The footer under a list that was cut short. `has_more: false` used to be
|
|
118
|
+
* unconditional on these lists, so a page of `--limit` rows read as the whole
|
|
119
|
+
* answer; the server now says when there is more and this says what to do.
|
|
120
|
+
* Empty when the page is complete.
|
|
121
|
+
*
|
|
122
|
+
* `cursor` is true only for a list that can be paged (`northstars list`); the
|
|
123
|
+
* reviews and intents lists have no cursor, so their way on is a larger
|
|
124
|
+
* `--limit`, or a narrower `--status` once `--limit` is at its ceiling.
|
|
125
|
+
*/
|
|
126
|
+
export declare function listFooter(input: {
|
|
127
|
+
shown: number;
|
|
128
|
+
hasMore: boolean;
|
|
129
|
+
limit: number;
|
|
130
|
+
max: number;
|
|
131
|
+
nextCursor?: string | null;
|
|
132
|
+
cursor?: boolean;
|
|
133
|
+
}): string;
|
|
68
134
|
export declare function renderNorthstarList(rows: Northstar[], log: (line: string) => void): void;
|
|
135
|
+
/**
|
|
136
|
+
* The active-commitment cap, in words. `0` is accepted and stored, and a review
|
|
137
|
+
* treats it as "no cap" (it does not flag every commitment over a cap of zero),
|
|
138
|
+
* so the screen says that rather than letting `0` read as a limit.
|
|
139
|
+
*/
|
|
140
|
+
export declare function describeMaxActive(value: number | undefined): string;
|
|
69
141
|
export declare function renderNorthstar(status: NorthstarStatusResponse, log: (line: string) => void): void;
|
|
70
142
|
export declare function renderRecommendationList(rows: NorthstarRecommendation[], log: (line: string) => void): void;
|
|
143
|
+
/**
|
|
144
|
+
* No reviewer configured, a ready one, and an unreachable one are three
|
|
145
|
+
* different answers — and the third is the one an operator needs spelled out,
|
|
146
|
+
* because a scheduled review trigger says nothing about whether the agent that
|
|
147
|
+
* would run it is online.
|
|
148
|
+
*/
|
|
149
|
+
export declare function reviewerReadiness(reviewer: NorthstarGovernanceStatus['reviewer']): string;
|
|
150
|
+
/** The `governance configure` flags that move what a commitment's allocation is computed from. */
|
|
151
|
+
export declare const ALLOCATION_INPUT_FLAGS: readonly ["max-runs-per-day", "clear-max-runs-per-day", "critical-reserve", "min-interval-hours", "max-interval-hours", "max-relative-change"];
|
|
152
|
+
export type AllocationRefresh = {
|
|
153
|
+
refreshed: number;
|
|
154
|
+
pending: number;
|
|
155
|
+
failed: boolean;
|
|
156
|
+
};
|
|
157
|
+
/** The refresh summary a configure response carries, or undefined from a server that sends none. */
|
|
158
|
+
export declare function readAllocationRefresh(response: AllocationRefreshFields | undefined): AllocationRefresh | undefined;
|
|
159
|
+
/**
|
|
160
|
+
* What `governance configure` says about the linked commitments. The server re-applies a changed
|
|
161
|
+
* budget or cadence band to every linked active commitment at once and answers how many it wrote,
|
|
162
|
+
* how many it could not, and whether the refresh itself failed; the command discarded all of it and
|
|
163
|
+
* re-read the status, so "nothing happened" and "applied to three" looked the same (OSK-21245).
|
|
164
|
+
*
|
|
165
|
+
* `inputsSent` is whether this call touched an allocation input: only then is "already up to date" a
|
|
166
|
+
* true statement, since a zero is also what an unrelated change (the analysis mode) answers.
|
|
167
|
+
*/
|
|
168
|
+
export declare function describeAllocationRefresh(refresh: AllocationRefresh | undefined, options: {
|
|
169
|
+
northstarId: string;
|
|
170
|
+
inputsSent: boolean;
|
|
171
|
+
bin?: string;
|
|
172
|
+
}): {
|
|
173
|
+
lines: string[];
|
|
174
|
+
warnings: string[];
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* The `Allocations` line of `review-now`. The count is of commitments WRITTEN, so `0` does not say
|
|
178
|
+
* "nothing happened": it is what a review prints when a configure already applied the budget, or
|
|
179
|
+
* when no active commitment is linked, or when no review row could be opened to write under.
|
|
180
|
+
*/
|
|
181
|
+
export declare function describeReviewAllocations(result: {
|
|
182
|
+
review?: unknown;
|
|
183
|
+
allocations?: unknown;
|
|
184
|
+
attention?: unknown;
|
|
185
|
+
}): string;
|
|
186
|
+
/**
|
|
187
|
+
* The sentence for a portfolio run budget smaller than the number of linked active commitments
|
|
188
|
+
* (OSK-21334): each still gets the floor of 1 run/day, so the ceilings add up to more than the
|
|
189
|
+
* budget. The server derives it once (`portfolioRunBudgetFloor.js`) and carries it, when it
|
|
190
|
+
* applies, on the `governance show` read, the `review-now` result and the effective policy's
|
|
191
|
+
* `portfolio`; every one of those three prints THIS sentence, so none composes its own and they
|
|
192
|
+
* cannot disagree. Absent from an older server, and from a budget that covers every commitment:
|
|
193
|
+
* no line, never a guess.
|
|
194
|
+
*
|
|
195
|
+
* Takes the carried field as it arrives (`unknown`), because two of the three callers read it off
|
|
196
|
+
* an untyped body.
|
|
197
|
+
*/
|
|
198
|
+
export declare function runBudgetFloorNote(value: unknown): string | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* What `critical_commitment` on the always-ask list does and does not do (OSK-21333).
|
|
201
|
+
*
|
|
202
|
+
* The list governs PROMOTION to critical (`critical_promotion`): remove the class and a bounded_auto
|
|
203
|
+
* review applies a small promotion itself. It does not govern the way back: a demotion away from
|
|
204
|
+
* critical is held for a person in `bounded_auto` whatever the list says (`critical_demotion`,
|
|
205
|
+
* `NorthstarGovernancePolicy.classifyIntent`: the demotion rule never reads the list). The behaviour
|
|
206
|
+
* is pinned by `NorthstarGovernancePolicy.spec.js` ("critical_commitment off the approval list"),
|
|
207
|
+
* the words by `cli/src/commands/northstars/__tests__/critical-approval-help.spec.ts`. The flag help
|
|
208
|
+
* and the `Approval for` line of `governance show` both read this one sentence, so neither can
|
|
209
|
+
* drift from the other.
|
|
210
|
+
*/
|
|
211
|
+
export declare const CRITICAL_COMMITMENT_APPROVAL_NOTE = "critical_commitment governs promotion to critical only; demotion away from critical (critical_demotion) is always held for a person, whatever this list says";
|
|
71
212
|
export declare function renderGovernance(status: NorthstarGovernanceStatus, log: (line: string) => void): void;
|
|
213
|
+
/**
|
|
214
|
+
* The automatic-change budget line.
|
|
215
|
+
*
|
|
216
|
+
* `0/day` is a MODE (automatic changes off, everything waits for approval), and `used` can
|
|
217
|
+
* legitimately exceed any cap, because the changes were made before the owner lowered it. A bare
|
|
218
|
+
* `2/0 used today · 0 left` collapses both into a ratio over 100% that says neither (OSK-21233).
|
|
219
|
+
*/
|
|
220
|
+
export declare function describeAutoBudget(budget: NorthstarGovernanceStatus['mutationBudget']): string;
|
|
221
|
+
/** One cell of words for what a review did beyond "it ran"; empty when there is nothing to add. */
|
|
222
|
+
export declare function reviewNote(review: NorthstarReviewRecord): string;
|
|
223
|
+
/** `Reason` line of one review: the words, with the raw code kept beside them for grep. */
|
|
224
|
+
export declare function describeReviewReason(reason: string): string;
|
|
72
225
|
export declare function renderReviewList(reviews: NorthstarReviewRecord[], log: (line: string) => void): void;
|
|
73
|
-
|
|
226
|
+
/** `--wide` on every command that prints the intents table. */
|
|
227
|
+
export declare const northstarWideFlag: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
228
|
+
export type IntentTableOptions = {
|
|
229
|
+
/** Never clip the reason, and keep the machine code beside it as `[code]`. */
|
|
230
|
+
wide?: boolean;
|
|
231
|
+
/** Terminal width to fit the table to; defaults to the real terminal, else 250. */
|
|
232
|
+
columns?: number;
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* The intents table.
|
|
236
|
+
*
|
|
237
|
+
* WHY is the HUMAN reason the governor wrote (`reason`), not the machine code in
|
|
238
|
+
* `verdictReason`, which says why an intent needed approval (`execution_mode_approval`)
|
|
239
|
+
* and is no reason for the change itself. The code stays in `--json`, and beside
|
|
240
|
+
* the sentence as `[code]` under `--wide`. By default the sentence is cut at a
|
|
241
|
+
* word boundary to what the terminal leaves after the other columns.
|
|
242
|
+
*/
|
|
243
|
+
export declare function renderIntentList(intents: NorthstarManagementIntent[], log: (line: string) => void, options?: IntentTableOptions): void;
|
|
244
|
+
/**
|
|
245
|
+
* The line that says a review's intent budget cut something off. A cap of 0
|
|
246
|
+
* records nothing at all, which a screen reading "No management intents." made
|
|
247
|
+
* indistinguishable from a review with nothing to say; the count was only in
|
|
248
|
+
* `--json` (`deterministicSnapshot.truncatedIntents`).
|
|
249
|
+
*/
|
|
250
|
+
export declare function intentBudgetNote(truncated: unknown, cap?: unknown): string;
|