@skrr-ai/cli 0.1.9 → 0.1.11
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 -13
- package/dist/base-command.js +78 -1
- package/dist/commands/browser/skill/show.js +7 -1
- package/dist/commands/code/index.d.ts +1 -0
- package/dist/commands/code/index.js +9 -1
- package/dist/commands/commitments/analytics/index.js +2 -0
- package/dist/commands/daemon/byok.d.ts +1 -0
- package/dist/commands/daemon/byok.js +2 -1
- package/dist/commands/daemon/install.d.ts +1 -0
- package/dist/commands/daemon/install.js +2 -1
- package/dist/commands/daemon/login.d.ts +31 -0
- package/dist/commands/daemon/login.js +56 -0
- package/dist/commands/daemon/restart.d.ts +9 -0
- package/dist/commands/daemon/restart.js +36 -0
- package/dist/commands/daemon/start.d.ts +1 -0
- package/dist/commands/daemon/start.js +2 -1
- package/dist/commands/daemon/status.d.ts +1 -0
- package/dist/commands/daemon/status.js +2 -1
- package/dist/commands/daemon/stop.d.ts +1 -0
- package/dist/commands/daemon/stop.js +2 -1
- package/dist/commands/daemon/uninstall.d.ts +1 -0
- package/dist/commands/daemon/uninstall.js +2 -1
- package/dist/commands/daemon/unlock.d.ts +9 -0
- package/dist/commands/daemon/unlock.js +33 -0
- package/dist/commands/goals/key-results/create.js +32 -1
- package/dist/commands/goals/key-results/update.d.ts +11 -0
- package/dist/commands/goals/key-results/update.js +80 -2
- package/dist/commands/goals/plan-now.d.ts +54 -2
- package/dist/commands/goals/plan-now.js +175 -18
- package/dist/commands/goals/planner-config.d.ts +60 -9
- package/dist/commands/goals/planner-config.js +82 -34
- package/dist/commands/goals/revisions.js +17 -0
- package/dist/commands/goals/show.d.ts +17 -0
- package/dist/commands/goals/show.js +90 -3
- package/dist/commands/login.js +36 -3
- package/dist/commands/spaces/create.js +2 -1
- package/dist/commands/spaces/index.js +9 -1
- package/dist/commands/spaces/list.d.ts +18 -0
- package/dist/commands/spaces/list.js +57 -7
- package/dist/commands/spaces/show.js +4 -1
- package/dist/commands/spaces/summary.d.ts +4 -0
- package/dist/commands/spaces/summary.js +77 -1
- package/dist/commands/spaces/update.d.ts +4 -0
- package/dist/commands/spaces/update.js +38 -1
- package/dist/commands/tasks/actionability.js +40 -1
- package/dist/commands/tasks/activity.d.ts +29 -0
- package/dist/commands/tasks/activity.js +47 -0
- package/dist/commands/tasks/complete.d.ts +47 -0
- package/dist/commands/tasks/complete.js +159 -12
- package/dist/commands/tasks/create.d.ts +26 -0
- package/dist/commands/tasks/create.js +60 -1
- package/dist/commands/tasks/events/append.d.ts +2 -0
- package/dist/commands/tasks/events/append.js +41 -10
- package/dist/commands/tasks/events/list.js +60 -9
- package/dist/commands/tasks/output.js +22 -2
- package/dist/commands/tasks/ready.d.ts +38 -0
- package/dist/commands/tasks/ready.js +37 -0
- package/dist/commands/tasks/runs.d.ts +22 -0
- package/dist/commands/tasks/runs.js +110 -2
- package/dist/commands/tasks/show.d.ts +28 -0
- package/dist/commands/tasks/show.js +61 -0
- package/dist/commands/tasks/timeline.d.ts +7 -0
- package/dist/commands/tasks/timeline.js +34 -3
- package/dist/commands/tasks/update.d.ts +20 -0
- package/dist/commands/tasks/update.js +38 -1
- package/dist/commands/whoami.d.ts +40 -0
- package/dist/commands/whoami.js +61 -10
- package/dist/commands/wiki/ls.d.ts +23 -0
- package/dist/commands/wiki/ls.js +63 -10
- package/dist/commands/wiki/mv.d.ts +70 -0
- package/dist/commands/wiki/mv.js +198 -4
- package/dist/commands/wiki/rm.js +12 -1
- package/dist/commands/wiki/write.js +35 -3
- package/dist/help.d.ts +27 -0
- package/dist/help.js +48 -0
- package/dist/hooks/command-not-found.d.ts +31 -0
- package/dist/hooks/command-not-found.js +12 -80
- package/dist/lib/command-miss.d.ts +60 -0
- package/dist/lib/command-miss.js +128 -0
- package/dist/lib/commitment-analytics.d.ts +10 -0
- package/dist/lib/commitment-analytics.js +10 -0
- package/dist/lib/config.d.ts +40 -0
- package/dist/lib/config.js +72 -9
- package/dist/lib/daemonBroker.d.ts +7 -1
- package/dist/lib/daemonBroker.js +71 -0
- package/dist/lib/daemonHandoff.d.ts +38 -0
- package/dist/lib/daemonHandoff.js +297 -0
- package/dist/lib/exec-oversky.d.ts +30 -0
- package/dist/lib/exec-oversky.js +41 -0
- package/dist/lib/format.d.ts +7 -0
- package/dist/lib/format.js +27 -5
- package/dist/lib/login.js +22 -2
- package/dist/lib/sky-code.js +9 -4
- package/dist/lib/task-transcript.d.ts +9 -0
- package/dist/lib/task-transcript.js +13 -2
- package/dist/lib/tasks.d.ts +34 -0
- package/dist/lib/tasks.js +70 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/configRoot.d.ts +50 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/configRoot.js +67 -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 +7 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/configRoot.d.ts +50 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/configRoot.js +59 -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 +3 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +15 -4
- package/oclif.manifest.json +15713 -15480
- package/package.json +5 -3
package/dist/base-command.d.ts
CHANGED
|
@@ -367,19 +367,7 @@ export declare function withSubject(subject: string | undefined, message: string
|
|
|
367
367
|
* Exported for tests.
|
|
368
368
|
*/
|
|
369
369
|
export declare function describeHarnessUnavailable(body: Record<string, unknown> | null, bin?: string): string;
|
|
370
|
-
|
|
371
|
-
* Enrich the server's `ASSIGNEE_NOT_IN_SPACE` rejection with the same
|
|
372
|
-
* copy-pasteable remedy the by-name resolution failure already gives (OSK-4864).
|
|
373
|
-
*
|
|
374
|
-
* When a caller names an assignee that is not a member of the space, the CLI's
|
|
375
|
-
* own name-resolution path (`ASSIGNEE_NOT_FOUND`) says "add one with
|
|
376
|
-
* `skrr spaces members add`". The server's id-based rejection reaches
|
|
377
|
-
* `handleApiError` as a bare sentence that interpolates ids and offers no next
|
|
378
|
-
* step, so the two paths for the same mistake read very differently. Append the
|
|
379
|
-
* remedy unless the server already named it.
|
|
380
|
-
*
|
|
381
|
-
* Exported for tests.
|
|
382
|
-
*/
|
|
370
|
+
export declare function describeResourceNotFound(serverMessage: string | undefined, bin?: string, baseURL?: string): string | null;
|
|
383
371
|
export declare function describeAssigneeNotInSpace(serverMessage: string | undefined, bin?: string): string;
|
|
384
372
|
/**
|
|
385
373
|
* Whether an automated retry of the IDENTICAL request could plausibly succeed.
|
package/dist/base-command.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.assigneePayloadNeedsResolution = assigneePayloadNeedsResolution;
|
|
|
5
5
|
exports.parseGlobalFlags = parseGlobalFlags;
|
|
6
6
|
exports.withSubject = withSubject;
|
|
7
7
|
exports.describeHarnessUnavailable = describeHarnessUnavailable;
|
|
8
|
+
exports.describeResourceNotFound = describeResourceNotFound;
|
|
8
9
|
exports.describeAssigneeNotInSpace = describeAssigneeNotInSpace;
|
|
9
10
|
exports.describeForbidden = describeForbidden;
|
|
10
11
|
exports.isRetryableFailure = isRetryableFailure;
|
|
@@ -288,6 +289,16 @@ class BaseCommand extends core_1.Command {
|
|
|
288
289
|
kind: (0, auth_core_1.classifyTokenKind)(accessToken),
|
|
289
290
|
};
|
|
290
291
|
}
|
|
292
|
+
else if (autoResult.outcome.reason === 'rate_limited') {
|
|
293
|
+
// Otherwise the only thing the user sees is "Not signed in", which is
|
|
294
|
+
// true and points at the wrong repair: they are signed in, the local
|
|
295
|
+
// broker is just being throttled, and the fix is to wait rather than
|
|
296
|
+
// to log in again. Reachable in the ordinary way — a cold machine
|
|
297
|
+
// running several skrr commands at once has every process brokering,
|
|
298
|
+
// because none of them has a token yet.
|
|
299
|
+
process.stderr.write('[skrr] The local skrr runtime is being rate-limited while brokering logins. ' +
|
|
300
|
+
'This is transient — retry in a few minutes, or run `skrr login` to sign in directly.\n');
|
|
301
|
+
}
|
|
291
302
|
else if (autoResult.outcome.reason === 'base_url_mismatch' &&
|
|
292
303
|
autoResult.outcome.daemonServerUrl) {
|
|
293
304
|
// The user is about to see "Not signed in" — give them the
|
|
@@ -869,7 +880,15 @@ class BaseCommand extends core_1.Command {
|
|
|
869
880
|
}
|
|
870
881
|
else if (e.status === 404) {
|
|
871
882
|
this.failWithCliError({
|
|
872
|
-
|
|
883
|
+
// Give the by-id path the remedy the by-name path already carries.
|
|
884
|
+
// The server answers a stale id with a bare `Space not found`, while
|
|
885
|
+
// a typo'd NAME gets a message naming `spaces list` and `--q`. A
|
|
886
|
+
// pasted stale id is the MORE common mistake and got the worse
|
|
887
|
+
// message, because a UUID short-circuits the resolver and the
|
|
888
|
+
// failure only surfaces here as a 404.
|
|
889
|
+
message: say(describeResourceNotFound(bodyMessage, this.config.bin, this.cliConfig?.baseURL) ||
|
|
890
|
+
bodyMessage ||
|
|
891
|
+
'Not found.'),
|
|
873
892
|
code: bodyCode || 'NOT_FOUND',
|
|
874
893
|
status: e.status,
|
|
875
894
|
exit: 4,
|
|
@@ -1222,6 +1241,64 @@ function describeHarnessUnavailable(body, bin = 'skrr') {
|
|
|
1222
1241
|
*
|
|
1223
1242
|
* Exported for tests.
|
|
1224
1243
|
*/
|
|
1244
|
+
/**
|
|
1245
|
+
* A bare `<Thing> not found` from the server, given the remedy the by-name
|
|
1246
|
+
* path already carries.
|
|
1247
|
+
*
|
|
1248
|
+
* `skrr spaces show <stale-uuid>` answered `Space not found` / NOT_FOUND and
|
|
1249
|
+
* stopped there, while a typo'd NAME got a genuinely good error naming
|
|
1250
|
+
* `spaces list` and `spaces list --q`. The by-id path is the MORE common
|
|
1251
|
+
* mistake — a stale or mistyped id pasted from somewhere — and it got the
|
|
1252
|
+
* worse message, because a UUID short-circuits the resolver and the failure
|
|
1253
|
+
* only surfaces later as a server 404.
|
|
1254
|
+
*
|
|
1255
|
+
* Same shape and same remedy as `describeAssigneeNotInSpace` above, whose own
|
|
1256
|
+
* comment records the identical asymmetry for assignees (OSK-4864).
|
|
1257
|
+
*
|
|
1258
|
+
* Keyed on the server's exact sentence rather than the code, because
|
|
1259
|
+
* `NOT_FOUND` is generic across resources and the sentence is what says which
|
|
1260
|
+
* one. An unrecognised subject falls through unchanged — a wrong hint is worse
|
|
1261
|
+
* than none.
|
|
1262
|
+
*/
|
|
1263
|
+
const NOT_FOUND_REMEDIES = {
|
|
1264
|
+
'Space not found': 'spaces list',
|
|
1265
|
+
'Task not found': 'tasks list',
|
|
1266
|
+
'Goal not found': 'goals list',
|
|
1267
|
+
'Agent not found': 'agents list',
|
|
1268
|
+
};
|
|
1269
|
+
/**
|
|
1270
|
+
* Subjects whose ids are DEPLOYMENT-SCOPED, where "not found" most often means
|
|
1271
|
+
* "not found HERE" rather than "does not exist".
|
|
1272
|
+
*
|
|
1273
|
+
* An agent id minted on one deployment cannot resolve on another, and the
|
|
1274
|
+
* machine's own managed `CLAUDE.md` identity block prints agent ids without
|
|
1275
|
+
* recording which deployment they belong to. So a machine whose CLI default
|
|
1276
|
+
* moves between deployments keeps a platform-authored instruction telling its
|
|
1277
|
+
* local coding agent to run `agent message send --agent <id>` with ids that
|
|
1278
|
+
* cannot resolve — and the failure lands on the one sanctioned agent-to-user
|
|
1279
|
+
* path, where it reads as "the agent silently stopped being able to reach its
|
|
1280
|
+
* owner".
|
|
1281
|
+
*
|
|
1282
|
+
* Naming the server turns that into a diagnosable error. It does not FIX the
|
|
1283
|
+
* stale block — the block should record its own deployment, which is a
|
|
1284
|
+
* server-side change — but it stops the symptom being mute.
|
|
1285
|
+
*/
|
|
1286
|
+
const DEPLOYMENT_SCOPED_SUBJECTS = new Set(['Agent not found']);
|
|
1287
|
+
function describeResourceNotFound(serverMessage, bin = 'skrr', baseURL) {
|
|
1288
|
+
const base = serverMessage?.trim();
|
|
1289
|
+
if (!base)
|
|
1290
|
+
return null;
|
|
1291
|
+
const listCommand = NOT_FOUND_REMEDIES[base];
|
|
1292
|
+
if (!listCommand)
|
|
1293
|
+
return null;
|
|
1294
|
+
const where = DEPLOYMENT_SCOPED_SUBJECTS.has(base) && baseURL ? ` on ${baseURL}` : '';
|
|
1295
|
+
const scoped = DEPLOYMENT_SCOPED_SUBJECTS.has(base)
|
|
1296
|
+
? `\n → ids are per-deployment, so one from another server (or from a stale managed ` +
|
|
1297
|
+
`\`CLAUDE.md\` identity block) will not resolve here. \`${bin} context\` names this server.`
|
|
1298
|
+
: '';
|
|
1299
|
+
return (`${base}${where}\n → list what you can see with \`${bin} ${listCommand}\`, ` +
|
|
1300
|
+
`or search with \`${bin} ${listCommand} --q "<text>"\`.${scoped}`);
|
|
1301
|
+
}
|
|
1225
1302
|
function describeAssigneeNotInSpace(serverMessage, bin = 'skrr') {
|
|
1226
1303
|
const base = serverMessage?.trim() || 'That assignee is not a member of this space.';
|
|
1227
1304
|
if (base.includes(`${bin} spaces members add`))
|
|
@@ -5,7 +5,13 @@ const browser_1 = require("../../browser");
|
|
|
5
5
|
class BrowserSkillShow extends core_1.Command {
|
|
6
6
|
static description = 'Print the version-matched skrr Browser agent skill';
|
|
7
7
|
static args = {
|
|
8
|
-
|
|
8
|
+
// `ignoreStdin` or oclif fills this positional from STDIN whenever stdin is
|
|
9
|
+
// not a TTY — so `echo x | skrr browser skill show` took the piped bytes as
|
|
10
|
+
// the skill name and failed with "Unknown skrr Browser skill: x", while the
|
|
11
|
+
// identical command with stdin closed printed the skill. `skrr commands
|
|
12
|
+
// --audit` names this rule (ARG_IMPLICIT_STDIN_ENABLED) and this was its
|
|
13
|
+
// only error.
|
|
14
|
+
name: core_1.Args.string({ description: 'Skill name (core)', ignoreStdin: true }),
|
|
9
15
|
};
|
|
10
16
|
async run() {
|
|
11
17
|
const { args } = await this.parse(BrowserSkillShow);
|
|
@@ -11,6 +11,7 @@ import { Command } from '@oclif/core';
|
|
|
11
11
|
* that parses successfully and is then silently dropped.
|
|
12
12
|
*/
|
|
13
13
|
export default class Code extends Command {
|
|
14
|
+
static summary: string;
|
|
14
15
|
static description: string;
|
|
15
16
|
static strict: boolean;
|
|
16
17
|
static examples: string[];
|
|
@@ -17,7 +17,15 @@ const sky_code_managed_1 = require("../../lib/sky-code-managed");
|
|
|
17
17
|
* that parses successfully and is then silently dropped.
|
|
18
18
|
*/
|
|
19
19
|
class Code extends core_1.Command {
|
|
20
|
-
|
|
20
|
+
// oclif renders `summary` in a command listing and `description` only in the
|
|
21
|
+
// command's own help. Without one, the forwarding note below — which has to
|
|
22
|
+
// be long, because it is explaining an absent FLAGS section — was printed in
|
|
23
|
+
// full inside `skrr --help`, twice (under TOPICS and again under COMMANDS),
|
|
24
|
+
// turning the top-level index into prose. Same trade the `skrr daemon`
|
|
25
|
+
// pass-throughs make: the note reaches whoever asks about this command, and
|
|
26
|
+
// nobody else.
|
|
27
|
+
static summary = 'Start the skrr Code interactive coding agent in this directory';
|
|
28
|
+
static description = 'Everything after ' +
|
|
21
29
|
`\`code\` is forwarded to the engine unchanged, so engine flags are not listed here — ` +
|
|
22
30
|
`run \`skrr code run --help\` for this wrapper, or the engine's own help for its ` +
|
|
23
31
|
`flags. ${sky_code_managed_1.SKRR_AGENT_FLAG} is the one flag this wrapper consumes itself.`;
|
|
@@ -26,7 +26,9 @@ const REPORT_RUNNERS = {
|
|
|
26
26
|
decision,
|
|
27
27
|
}),
|
|
28
28
|
distribution: ({ days, workspace }) => commitment_analytics_1.commitmentAnalyticsApi.distribution({ days, workspaceId: workspace }),
|
|
29
|
+
'distribution-tripwire': ({ limit, workspace }) => commitment_analytics_1.commitmentAnalyticsApi.distributionTripwire({ limit, workspaceId: workspace }),
|
|
29
30
|
'attention-budget': ({ days, limit }) => commitment_analytics_1.commitmentAnalyticsApi.attentionBudget({ days, limit }),
|
|
31
|
+
'decision-inbox': () => commitment_analytics_1.commitmentAnalyticsApi.decisionInbox(),
|
|
30
32
|
'action-adapters-audit': () => commitment_analytics_1.commitmentAnalyticsApi.actionAdapterAudit(),
|
|
31
33
|
'recovery-metrics': ({ limit }) => commitment_analytics_1.commitmentAnalyticsApi.recoveryMetrics({ limit }),
|
|
32
34
|
recovery: ({ limit }) => commitment_analytics_1.commitmentAnalyticsApi.recovery({ limit }),
|
|
@@ -12,7 +12,8 @@ class DaemonByok extends core_1.Command {
|
|
|
12
12
|
// whole topic, and without a per-command alias only the bare topic
|
|
13
13
|
// resolved: every subcommand under it failed.
|
|
14
14
|
static aliases = ['daemons:byok'];
|
|
15
|
-
static
|
|
15
|
+
static summary = 'Manage local BYOK provider credentials in the daemon profile Keychain';
|
|
16
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('byok');
|
|
16
17
|
static strict = false;
|
|
17
18
|
static examples = [
|
|
18
19
|
'<%= config.bin %> daemon byok status',
|
|
@@ -20,7 +20,8 @@ class DaemonInstall extends core_1.Command {
|
|
|
20
20
|
// whole topic, and without a per-command alias only the bare topic
|
|
21
21
|
// resolved: every subcommand under it failed.
|
|
22
22
|
static aliases = ['daemons:install'];
|
|
23
|
-
static
|
|
23
|
+
static summary = 'Install the local skrr runtime as a background service';
|
|
24
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('install', { binds: true });
|
|
24
25
|
static strict = false; // forward all args verbatim — see run()
|
|
25
26
|
async run() {
|
|
26
27
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr daemon login` — authenticate the local runtime.
|
|
4
|
+
*
|
|
5
|
+
* Exists because the CLI and the daemon deliberately keep SEPARATE credentials
|
|
6
|
+
* (distinct keychain namespaces, distinct refresh families, independent
|
|
7
|
+
* revocation), and nothing made that legible. `skrr login` mints a cli-scope
|
|
8
|
+
* credential; the daemon reads a daemon-scope one. So the daemon would refuse to
|
|
9
|
+
* start, print `AUTH_BINDING_MISMATCH`, and the operator would run `skrr login`,
|
|
10
|
+
* complete a full browser flow, and get the identical error back — because the
|
|
11
|
+
* only command that could clear it lived on a second binary they had no reason to
|
|
12
|
+
* know existed (OSK-303).
|
|
13
|
+
*
|
|
14
|
+
* This does not merge the two credentials, and should not: daemon scope is
|
|
15
|
+
* deliberately LOWER-privileged than cli scope (`requireHumanScope` refuses it
|
|
16
|
+
* from billing, account management, password change and deletion), and separate
|
|
17
|
+
* revocation means losing a machine is not losing your session. What it removes
|
|
18
|
+
* is the user having to PERFORM that separation.
|
|
19
|
+
*
|
|
20
|
+
* `--env` / `--server` default to the deployment the CLI is on, for the same
|
|
21
|
+
* reason `install` does: a daemon authenticated against a different deployment
|
|
22
|
+
* than its CLI is the split OSK-279 exists to prevent, and picking it up from the
|
|
23
|
+
* session is how one command stops producing two answers.
|
|
24
|
+
*/
|
|
25
|
+
export default class DaemonLogin extends Command {
|
|
26
|
+
static aliases: string[];
|
|
27
|
+
static summary: string;
|
|
28
|
+
static description: string;
|
|
29
|
+
static strict: boolean;
|
|
30
|
+
run(): Promise<void>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const daemon_binding_1 = require("../../lib/daemon-binding");
|
|
5
|
+
const exec_oversky_1 = require("../../lib/exec-oversky");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr daemon login` — authenticate the local runtime.
|
|
8
|
+
*
|
|
9
|
+
* Exists because the CLI and the daemon deliberately keep SEPARATE credentials
|
|
10
|
+
* (distinct keychain namespaces, distinct refresh families, independent
|
|
11
|
+
* revocation), and nothing made that legible. `skrr login` mints a cli-scope
|
|
12
|
+
* credential; the daemon reads a daemon-scope one. So the daemon would refuse to
|
|
13
|
+
* start, print `AUTH_BINDING_MISMATCH`, and the operator would run `skrr login`,
|
|
14
|
+
* complete a full browser flow, and get the identical error back — because the
|
|
15
|
+
* only command that could clear it lived on a second binary they had no reason to
|
|
16
|
+
* know existed (OSK-303).
|
|
17
|
+
*
|
|
18
|
+
* This does not merge the two credentials, and should not: daemon scope is
|
|
19
|
+
* deliberately LOWER-privileged than cli scope (`requireHumanScope` refuses it
|
|
20
|
+
* from billing, account management, password change and deletion), and separate
|
|
21
|
+
* revocation means losing a machine is not losing your session. What it removes
|
|
22
|
+
* is the user having to PERFORM that separation.
|
|
23
|
+
*
|
|
24
|
+
* `--env` / `--server` default to the deployment the CLI is on, for the same
|
|
25
|
+
* reason `install` does: a daemon authenticated against a different deployment
|
|
26
|
+
* than its CLI is the split OSK-279 exists to prevent, and picking it up from the
|
|
27
|
+
* session is how one command stops producing two answers.
|
|
28
|
+
*/
|
|
29
|
+
class DaemonLogin extends core_1.Command {
|
|
30
|
+
static aliases = ['daemons:login'];
|
|
31
|
+
static summary = 'Authenticate the local skrr runtime (separate from `skrr login`)';
|
|
32
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('login', { binds: true });
|
|
33
|
+
static strict = false; // forward all args verbatim — see run()
|
|
34
|
+
async run() {
|
|
35
|
+
// `this.argv`, NOT `this.parse()` — `strict = false` relaxes POSITIONAL
|
|
36
|
+
// arity and oclif still rejects any flag this command has not declared
|
|
37
|
+
// (OSK-296).
|
|
38
|
+
const argv = this.argv;
|
|
39
|
+
try {
|
|
40
|
+
// `--cwd` is deliberately NOT defaulted here. `skrrd login` resolves it
|
|
41
|
+
// from the installed service definition, which is the only authoritative
|
|
42
|
+
// answer; guessing it from the CLI's cwd is exactly the mistake that made
|
|
43
|
+
// the old default wrong.
|
|
44
|
+
const code = await (0, exec_oversky_1.execOversky)(['login', ...(0, daemon_binding_1.bindToCliSession)(argv)]);
|
|
45
|
+
this.exit(code);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err.message === 'oversky-not-installed') {
|
|
49
|
+
this.log((0, exec_oversky_1.notInstalledMessage)());
|
|
50
|
+
this.exit(127);
|
|
51
|
+
}
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.default = DaemonLogin;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const exec_oversky_1 = require("../../lib/exec-oversky");
|
|
5
|
+
class DaemonRestart extends core_1.Command {
|
|
6
|
+
// `skrr daemons <sub>` — the plural is advertised as an alias for the
|
|
7
|
+
// whole topic, and without a per-command alias only the bare topic
|
|
8
|
+
// resolved: every subcommand under it failed.
|
|
9
|
+
static aliases = ['daemons:restart'];
|
|
10
|
+
static summary = 'Restart the local skrr daemon, preserving its current supervision mode';
|
|
11
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('restart');
|
|
12
|
+
static strict = false; // forward all args verbatim — see run()
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> daemon restart',
|
|
15
|
+
'<%= config.bin %> daemon restart --profile work',
|
|
16
|
+
];
|
|
17
|
+
async run() {
|
|
18
|
+
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
19
|
+
// arity and oclif still rejects any flag this command has not declared —
|
|
20
|
+
// so every `skrrd` flag would be unreachable through the wrapper that
|
|
21
|
+
// exists to reach it (OSK-296).
|
|
22
|
+
const argv = this.argv;
|
|
23
|
+
try {
|
|
24
|
+
const code = await (0, exec_oversky_1.execOversky)(['restart', ...argv]);
|
|
25
|
+
this.exit(code);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
if (err.message === 'oversky-not-installed') {
|
|
29
|
+
this.log((0, exec_oversky_1.notInstalledMessage)());
|
|
30
|
+
this.exit(127);
|
|
31
|
+
}
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.default = DaemonRestart;
|
|
@@ -7,7 +7,8 @@ class DaemonStart extends core_1.Command {
|
|
|
7
7
|
// whole topic, and without a per-command alias only the bare topic
|
|
8
8
|
// resolved: every subcommand under it failed.
|
|
9
9
|
static aliases = ['daemons:start'];
|
|
10
|
-
static
|
|
10
|
+
static summary = 'Start the local skrr daemon';
|
|
11
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('start');
|
|
11
12
|
static strict = false; // forward all args verbatim — see run()
|
|
12
13
|
async run() {
|
|
13
14
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -7,7 +7,8 @@ class DaemonStatus extends core_1.Command {
|
|
|
7
7
|
// whole topic, and without a per-command alias only the bare topic
|
|
8
8
|
// resolved: every subcommand under it failed.
|
|
9
9
|
static aliases = ['daemons:status'];
|
|
10
|
-
static
|
|
10
|
+
static summary = 'Show skrr daemon status (config, connection, services)';
|
|
11
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('status');
|
|
11
12
|
static strict = false;
|
|
12
13
|
async run() {
|
|
13
14
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -7,7 +7,8 @@ class DaemonStop extends core_1.Command {
|
|
|
7
7
|
// whole topic, and without a per-command alias only the bare topic
|
|
8
8
|
// resolved: every subcommand under it failed.
|
|
9
9
|
static aliases = ['daemons:stop'];
|
|
10
|
-
static
|
|
10
|
+
static summary = 'Stop the local skrr daemon';
|
|
11
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('stop');
|
|
11
12
|
static strict = false;
|
|
12
13
|
async run() {
|
|
13
14
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -19,7 +19,8 @@ class DaemonUninstall extends core_1.Command {
|
|
|
19
19
|
// whole topic, and without a per-command alias only the bare topic
|
|
20
20
|
// resolved: every subcommand under it failed.
|
|
21
21
|
static aliases = ['daemons:uninstall'];
|
|
22
|
-
static
|
|
22
|
+
static summary = "Remove the local skrr runtime's background service (local state is left alone)";
|
|
23
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('uninstall');
|
|
23
24
|
static strict = false; // forward all args verbatim — see run()
|
|
24
25
|
async run() {
|
|
25
26
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const exec_oversky_1 = require("../../lib/exec-oversky");
|
|
5
|
+
class DaemonUnlock extends core_1.Command {
|
|
6
|
+
// `skrr daemons <sub>` — the plural is advertised as an alias for the
|
|
7
|
+
// whole topic, and without a per-command alias only the bare topic
|
|
8
|
+
// resolved: every subcommand under it failed.
|
|
9
|
+
static aliases = ['daemons:unlock'];
|
|
10
|
+
static summary = 'Clear a stranded singleton lock (daemon.lock) left by a crashed skrr daemon';
|
|
11
|
+
static description = (0, exec_oversky_1.forwardedFlagsNote)('unlock');
|
|
12
|
+
static strict = false; // forward all args verbatim — see run()
|
|
13
|
+
static examples = ['<%= config.bin %> daemon unlock'];
|
|
14
|
+
async run() {
|
|
15
|
+
// Recovery verbs are the ones that most need to be reachable from the
|
|
16
|
+
// wrapper: you go looking for `unlock` exactly when the daemon is wedged,
|
|
17
|
+
// which is the worst moment to discover the CLI cannot reach it and that
|
|
18
|
+
// the verb lives on a second binary you have to learn about first.
|
|
19
|
+
const argv = this.argv;
|
|
20
|
+
try {
|
|
21
|
+
const code = await (0, exec_oversky_1.execOversky)(['unlock', ...argv]);
|
|
22
|
+
this.exit(code);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err.message === 'oversky-not-installed') {
|
|
26
|
+
this.log((0, exec_oversky_1.notInstalledMessage)());
|
|
27
|
+
this.exit(127);
|
|
28
|
+
}
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.default = DaemonUnlock;
|
|
@@ -28,7 +28,16 @@ class GoalsKeyResultsCreate extends base_command_1.BaseCommand {
|
|
|
28
28
|
}),
|
|
29
29
|
title: core_1.Flags.string({ description: 'Key result title (required unless set via --from-json)' }),
|
|
30
30
|
description: core_1.Flags.string({ description: 'Key result description' }),
|
|
31
|
-
|
|
31
|
+
// The bound is declared, not just described. `--progress 150` and
|
|
32
|
+
// `--progress -5` both came back as a bare `Invalid request data /
|
|
33
|
+
// HTTP_400` from the server — byte-identical for two different mistakes,
|
|
34
|
+
// in a CLI that gives excellent field-level errors for enums. oclif
|
|
35
|
+
// refuses an out-of-range value naming the range, before the round trip.
|
|
36
|
+
progress: core_1.Flags.integer({
|
|
37
|
+
description: 'Progress 0–100 (used in manual mode)',
|
|
38
|
+
min: 0,
|
|
39
|
+
max: 100,
|
|
40
|
+
}),
|
|
32
41
|
'progress-mode': core_1.Flags.string({
|
|
33
42
|
description: 'How progress is tracked',
|
|
34
43
|
options: [...data_provider_1.KEY_RESULT_PROGRESS_MODES],
|
|
@@ -78,6 +87,28 @@ class GoalsKeyResultsCreate extends base_command_1.BaseCommand {
|
|
|
78
87
|
}
|
|
79
88
|
const k = created;
|
|
80
89
|
this.log(`Created key result ${k.id ?? '?'} on goal ${args.goalId} - ${k.title ?? '(no title)'}`);
|
|
90
|
+
if (k.progressMode === 'auto')
|
|
91
|
+
this.warn(AUTO_MODE_NOTE);
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
exports.default = GoalsKeyResultsCreate;
|
|
95
|
+
/**
|
|
96
|
+
* Why an `auto` key result reads as `-` from the CLI.
|
|
97
|
+
*
|
|
98
|
+
* Auto progress is computed from tasks linked to THIS key result
|
|
99
|
+
* (`Task.keyResultIds`), and the task↔key-result link is a DOCUMENTED
|
|
100
|
+
* omission from the CLI surface — it sits in `domain-api-parity.spec.ts`'s
|
|
101
|
+
* allowlist with a stated reason. So `--progress-mode auto` is offered by a
|
|
102
|
+
* surface that cannot make it move, and `resolveKeyResultProgress` renders
|
|
103
|
+
* `_computedProgress ?? null` for auto, i.e. `-`, while a `--progress` value
|
|
104
|
+
* you set is stored and returned by `update`.
|
|
105
|
+
*
|
|
106
|
+
* The result was one CLI reporting two different values for one field: the
|
|
107
|
+
* write echoed 40 and the list showed `-`. Saying so at the point of use is
|
|
108
|
+
* the honest fix; silently rendering the stored number instead would hide a
|
|
109
|
+
* real distinction (a manual value is not a computed one), and adding the
|
|
110
|
+
* link command would reverse a recorded decision.
|
|
111
|
+
*/
|
|
112
|
+
const AUTO_MODE_NOTE = 'Auto progress is computed from tasks linked to this key result, and linking a task to a key ' +
|
|
113
|
+
'result is deliberately not in the CLI — so this reads as "-" here until it is linked ' +
|
|
114
|
+
'elsewhere. Use --progress-mode manual to track a number from the CLI.';
|
|
@@ -25,3 +25,14 @@ export default class GoalsKeyResultsUpdate extends BaseCommand {
|
|
|
25
25
|
};
|
|
26
26
|
run(): Promise<void>;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* The sentence to print when `done` and a sub-100 progress are made to
|
|
30
|
+
* disagree, or `null` when they do not. Exported for `update.spec.ts`.
|
|
31
|
+
*
|
|
32
|
+
* Returns a warning rather than reconciling the two: pulling progress to 100
|
|
33
|
+
* would be the CLI inventing a policy the server does not have, and it would
|
|
34
|
+
* destroy the recorded number on the way.
|
|
35
|
+
*/
|
|
36
|
+
export declare function describeDoneDisagreement(status: string | undefined, progress: number | null): string | null;
|
|
37
|
+
/** How the server now holds one patched field, for the confirmation line. */
|
|
38
|
+
export declare function describeField(kr: Record<string, unknown>, field: string): string;
|