@skrr-ai/cli 0.1.8 → 0.1.9
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 +27 -0
- package/dist/base-command.js +83 -11
- package/dist/commands/agent/message/send.js +1 -1
- package/dist/commands/agents/chat.d.ts +1 -1
- package/dist/commands/agents/chat.js +1 -1
- package/dist/commands/browser/install.d.ts +1 -1
- package/dist/commands/browser/install.js +10 -2
- package/dist/commands/browser/mcp-config.js +3 -1
- package/dist/commands/browser/skill/show.js +1 -1
- package/dist/commands/browser/status.js +4 -1
- package/dist/commands/browser/uninstall.d.ts +1 -1
- package/dist/commands/browser/uninstall.js +10 -2
- package/dist/commands/browser.d.ts +1 -1
- package/dist/commands/browser.js +3 -3
- package/dist/commands/code/index.js +6 -3
- package/dist/commands/code/install.d.ts +61 -0
- package/dist/commands/code/install.js +247 -0
- package/dist/commands/code/oversky-agent.d.ts +2 -1
- package/dist/commands/code/oversky-agent.js +12 -8
- package/dist/commands/commands.js +1 -1
- package/dist/commands/context.js +1 -1
- package/dist/commands/create-token.js +1 -1
- package/dist/commands/daemon/byok.d.ts +1 -0
- package/dist/commands/daemon/byok.js +14 -1
- package/dist/commands/daemon/index.js +18 -7
- package/dist/commands/daemon/install.d.ts +1 -0
- package/dist/commands/daemon/install.js +22 -3
- package/dist/commands/daemon/logs.d.ts +1 -0
- package/dist/commands/daemon/logs.js +4 -0
- package/dist/commands/daemon/start.d.ts +1 -0
- package/dist/commands/daemon/start.js +15 -2
- package/dist/commands/daemon/status.d.ts +1 -0
- package/dist/commands/daemon/status.js +14 -1
- package/dist/commands/daemon/stop.d.ts +1 -0
- package/dist/commands/daemon/stop.js +14 -1
- package/dist/commands/daemon/uninstall.d.ts +1 -0
- package/dist/commands/daemon/uninstall.js +15 -2
- package/dist/commands/daemon/usage.d.ts +1 -0
- package/dist/commands/daemon/usage.js +5 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/github/allow-tools.d.ts +1 -0
- package/dist/commands/github/app/install.d.ts +1 -0
- package/dist/commands/github/app/status.d.ts +1 -0
- package/dist/commands/github/connect.d.ts +1 -0
- package/dist/commands/github/connections.d.ts +1 -0
- package/dist/commands/github/disconnect.d.ts +1 -0
- package/dist/commands/github/finalize.d.ts +1 -0
- package/dist/commands/github/reconnect.d.ts +1 -0
- package/dist/commands/github/run.d.ts +1 -0
- package/dist/commands/github/tools.d.ts +1 -0
- package/dist/commands/goals/create.js +2 -2
- package/dist/commands/goals/show.js +5 -0
- package/dist/commands/harnesses/list.js +14 -3
- package/dist/commands/harnesses/show.js +14 -0
- package/dist/commands/instructions/activate.js +1 -1
- package/dist/commands/instructions/archive-version.js +1 -1
- package/dist/commands/instructions/delete.js +1 -1
- package/dist/commands/instructions/diff.js +1 -1
- package/dist/commands/instructions/install.js +7 -1
- package/dist/commands/instructions/restore.js +1 -1
- package/dist/commands/instructions/show.js +17 -1
- package/dist/commands/instructions/update.js +1 -1
- package/dist/commands/integrations/connections/connect.d.ts +1 -0
- package/dist/commands/integrations/connections/disconnect.d.ts +1 -0
- package/dist/commands/integrations/connections/finalize.d.ts +1 -0
- package/dist/commands/integrations/connections/list.d.ts +1 -0
- package/dist/commands/integrations/connections/reconnect.d.ts +1 -0
- package/dist/commands/integrations/execute.d.ts +1 -0
- package/dist/commands/integrations/search.d.ts +1 -0
- package/dist/commands/integrations/toolkits.d.ts +1 -0
- package/dist/commands/integrations/tools/allow.d.ts +1 -0
- package/dist/commands/integrations/tools/list.d.ts +1 -0
- package/dist/commands/list-daemons.d.ts +2 -7
- package/dist/commands/list-daemons.js +13 -13
- package/dist/commands/login.js +73 -31
- package/dist/commands/logout.js +52 -1
- package/dist/commands/machines/hosted/start.js +1 -1
- package/dist/commands/pair.js +2 -2
- package/dist/commands/projects/create.js +6 -1
- package/dist/commands/projects/tasks.js +6 -1
- package/dist/commands/revoke-daemon.js +6 -2
- package/dist/commands/set-capabilities.js +6 -2
- package/dist/commands/skills/install.js +1 -1
- package/dist/commands/skills/library.js +2 -2
- package/dist/commands/spaces/create.js +6 -2
- package/dist/commands/tasks/complete.d.ts +1 -1
- package/dist/commands/tasks/complete.js +21 -8
- package/dist/commands/tasks/create.js +4 -1
- package/dist/commands/tasks/current.js +1 -1
- package/dist/commands/tasks/delete.d.ts +1 -0
- package/dist/commands/tasks/delete.js +9 -0
- package/dist/commands/tasks/export.js +5 -1
- package/dist/commands/tasks/follow-up.js +2 -1
- package/dist/commands/tasks/list.js +5 -1
- package/dist/commands/tasks/pr.js +1 -1
- package/dist/commands/tasks/show.js +10 -1
- package/dist/commands/tasks/triage.js +2 -1
- package/dist/commands/tasks/update.js +4 -1
- package/dist/commands/tasks/upsert.js +4 -1
- package/dist/commands/usage.js +1 -1
- package/dist/lib/agentic-stream.js +21 -1
- package/dist/lib/api-fetch.d.ts +1 -1
- package/dist/lib/api-fetch.js +1 -1
- package/dist/lib/auth-core-init.js +23 -3
- package/dist/lib/auth-storage.d.ts +0 -12
- package/dist/lib/auth-storage.js +37 -2
- package/dist/lib/config.d.ts +3 -3
- package/dist/lib/config.js +327 -26
- package/dist/lib/created-line.d.ts +22 -0
- package/dist/lib/created-line.js +25 -0
- package/dist/lib/daemon-binding.d.ts +29 -0
- package/dist/lib/daemon-binding.js +63 -0
- package/dist/lib/daemon-ref.d.ts +31 -0
- package/dist/lib/daemon-ref.js +47 -0
- package/dist/lib/daemonBroker.js +1 -1
- package/dist/lib/delegated-cli.js +3 -3
- package/dist/lib/exec-oversky.d.ts +18 -1
- package/dist/lib/exec-oversky.js +21 -4
- package/dist/lib/html-text.d.ts +15 -0
- package/dist/lib/html-text.js +40 -0
- package/dist/lib/keychain.d.ts +43 -0
- package/dist/lib/keychain.js +145 -4
- package/dist/lib/login.js +3 -3
- package/dist/lib/node-adapter.js +1 -1
- package/dist/lib/oauthLogin.js +17 -6
- package/dist/lib/sky-code-agent.d.ts +1 -1
- package/dist/lib/sky-code-agent.js +8 -8
- package/dist/lib/sky-code-broker.js +18 -2
- package/dist/lib/sky-code-doctor.js +120 -4
- package/dist/lib/sky-code-managed.d.ts +12 -0
- package/dist/lib/sky-code-managed.js +21 -7
- package/dist/lib/sky-code.d.ts +16 -1
- package/dist/lib/sky-code.js +102 -4
- package/dist/lib/task-execution.js +4 -11
- package/dist/lib/tasks.d.ts +1 -0
- package/dist/lib/tasks.js +9 -6
- package/dist/lib/update-check.js +1 -1
- package/dist/lib/usage-discovery.js +1 -1
- package/dist/lib/web-url.js +12 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.js +2 -2
- 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 +13 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.js +16 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.d.ts +0 -9
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.js +18 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loginLocalhost.js +3 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +3 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/runtime.d.ts +7 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.d.ts +96 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.js +115 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.js +2 -2
- 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 +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/linux.js +16 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.d.ts +0 -9
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.js +18 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loginLocalhost.js +3 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +3 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/runtime.d.ts +7 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.d.ts +96 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.js +107 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +4206 -4191
- package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/managed-inference-broker.js +2 -2
- package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/managed-inference-broker.js +2 -2
- package/oclif.manifest.json +9924 -3352
- package/package.json +22 -19
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One shape for "you just created a thing".
|
|
3
|
+
*
|
|
4
|
+
* The four core entities each printed a different confirmation: the identifier
|
|
5
|
+
* was a human ref for a project, a raw uuid for a goal and a space, and both for
|
|
6
|
+
* a task; the separator was an em dash for two and a hyphen for the other two;
|
|
7
|
+
* and goals and spaces appended context (`in space <uuid>`,
|
|
8
|
+
* `(subspace of <uuid>)`) that the link on the next line already carries.
|
|
9
|
+
*
|
|
10
|
+
* Reading four of these in a row, you cannot tell what you are being handed —
|
|
11
|
+
* which is what makes the difference between "did this work" and "what do I
|
|
12
|
+
* paste into the next command" harder than it should be.
|
|
13
|
+
*
|
|
14
|
+
* The rule: prefer the ref a person can type, fall back to the id, and put the
|
|
15
|
+
* title after a single em dash. The `View it at <url>` line that follows is
|
|
16
|
+
* already consistent and is left alone.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createdLine(entity: string, opts: {
|
|
19
|
+
ref?: string | null;
|
|
20
|
+
id?: string | null;
|
|
21
|
+
title?: string | null;
|
|
22
|
+
}): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createdLine = createdLine;
|
|
4
|
+
/**
|
|
5
|
+
* One shape for "you just created a thing".
|
|
6
|
+
*
|
|
7
|
+
* The four core entities each printed a different confirmation: the identifier
|
|
8
|
+
* was a human ref for a project, a raw uuid for a goal and a space, and both for
|
|
9
|
+
* a task; the separator was an em dash for two and a hyphen for the other two;
|
|
10
|
+
* and goals and spaces appended context (`in space <uuid>`,
|
|
11
|
+
* `(subspace of <uuid>)`) that the link on the next line already carries.
|
|
12
|
+
*
|
|
13
|
+
* Reading four of these in a row, you cannot tell what you are being handed —
|
|
14
|
+
* which is what makes the difference between "did this work" and "what do I
|
|
15
|
+
* paste into the next command" harder than it should be.
|
|
16
|
+
*
|
|
17
|
+
* The rule: prefer the ref a person can type, fall back to the id, and put the
|
|
18
|
+
* title after a single em dash. The `View it at <url>` line that follows is
|
|
19
|
+
* already consistent and is left alone.
|
|
20
|
+
*/
|
|
21
|
+
function createdLine(entity, opts) {
|
|
22
|
+
const label = (opts.ref ?? '').trim() || (opts.id ?? '').trim() || '?';
|
|
23
|
+
const title = (opts.title ?? '').trim() || '(no title)';
|
|
24
|
+
return `Created ${entity} ${label} — ${title}`;
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defaults for the flags that decide WHICH deployment and WHICH profile a
|
|
3
|
+
* newly installed daemon binds to.
|
|
4
|
+
*
|
|
5
|
+
* `skrr daemon *` are pass-throughs to the `skrrd` binary, and the two
|
|
6
|
+
* programs keep SEPARATE configuration: the CLI's deployment and profile live
|
|
7
|
+
* in `cli-config.json`, the daemon's in `daemon.json`. Nothing has ever made
|
|
8
|
+
* one follow the other, so the ordinary way to end up split is to do nothing
|
|
9
|
+
* unusual at all — log the CLI into one deployment and leave the daemon on
|
|
10
|
+
* whichever it was installed against. That is OSK-279, observed on this
|
|
11
|
+
* machine as a daemon on dev serving a CLI on prod.
|
|
12
|
+
*
|
|
13
|
+
* The fix is deliberately scoped to INSTALL, the moment a daemon is created
|
|
14
|
+
* and the only moment its binding is not yet somebody's decision. `start` is
|
|
15
|
+
* left alone on purpose: it starts a daemon that already has a binding, and
|
|
16
|
+
* silently overriding it would break the operator who split the two knowingly
|
|
17
|
+
* — running a dev daemon against a prod CLI is a legitimate thing to do, and
|
|
18
|
+
* it is not this function's place to overrule it. `skrr daemon status` reports
|
|
19
|
+
* a split instead of correcting one.
|
|
20
|
+
*/
|
|
21
|
+
/** Whether `argv` already carries `--name` or `--name=value` (or `-alias`). */
|
|
22
|
+
export declare function hasFlag(argv: readonly string[], name: string, alias?: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Append `--server` / `--profile` describing the CLI's own session, for any
|
|
25
|
+
* the caller did not pass. An explicit flag always wins — this only fills a
|
|
26
|
+
* silence, so `skrr daemon install --env prod` still installs against prod
|
|
27
|
+
* while the CLI sits on dev.
|
|
28
|
+
*/
|
|
29
|
+
export declare function bindToCliSession(argv: readonly string[]): string[];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasFlag = hasFlag;
|
|
4
|
+
exports.bindToCliSession = bindToCliSession;
|
|
5
|
+
const config_1 = require("./config");
|
|
6
|
+
const keychain_1 = require("./keychain");
|
|
7
|
+
/**
|
|
8
|
+
* Defaults for the flags that decide WHICH deployment and WHICH profile a
|
|
9
|
+
* newly installed daemon binds to.
|
|
10
|
+
*
|
|
11
|
+
* `skrr daemon *` are pass-throughs to the `skrrd` binary, and the two
|
|
12
|
+
* programs keep SEPARATE configuration: the CLI's deployment and profile live
|
|
13
|
+
* in `cli-config.json`, the daemon's in `daemon.json`. Nothing has ever made
|
|
14
|
+
* one follow the other, so the ordinary way to end up split is to do nothing
|
|
15
|
+
* unusual at all — log the CLI into one deployment and leave the daemon on
|
|
16
|
+
* whichever it was installed against. That is OSK-279, observed on this
|
|
17
|
+
* machine as a daemon on dev serving a CLI on prod.
|
|
18
|
+
*
|
|
19
|
+
* The fix is deliberately scoped to INSTALL, the moment a daemon is created
|
|
20
|
+
* and the only moment its binding is not yet somebody's decision. `start` is
|
|
21
|
+
* left alone on purpose: it starts a daemon that already has a binding, and
|
|
22
|
+
* silently overriding it would break the operator who split the two knowingly
|
|
23
|
+
* — running a dev daemon against a prod CLI is a legitimate thing to do, and
|
|
24
|
+
* it is not this function's place to overrule it. `skrr daemon status` reports
|
|
25
|
+
* a split instead of correcting one.
|
|
26
|
+
*/
|
|
27
|
+
/** Whether `argv` already carries `--name` or `--name=value` (or `-alias`). */
|
|
28
|
+
function hasFlag(argv, name, alias) {
|
|
29
|
+
return argv.some((arg) => {
|
|
30
|
+
if (arg === '--')
|
|
31
|
+
return false;
|
|
32
|
+
return (arg === name ||
|
|
33
|
+
arg.startsWith(`${name}=`) ||
|
|
34
|
+
(alias !== undefined && (arg === alias || arg.startsWith(`${alias}=`))));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Append `--server` / `--profile` describing the CLI's own session, for any
|
|
39
|
+
* the caller did not pass. An explicit flag always wins — this only fills a
|
|
40
|
+
* silence, so `skrr daemon install --env prod` still installs against prod
|
|
41
|
+
* while the CLI sits on dev.
|
|
42
|
+
*/
|
|
43
|
+
function bindToCliSession(argv) {
|
|
44
|
+
const extra = [];
|
|
45
|
+
// `--env` resolves to a server URL inside the daemon, so passing one is
|
|
46
|
+
// passing the other. Adding `--server` beside it would be an ambiguous
|
|
47
|
+
// instruction where the daemon's own precedence, not ours, decides.
|
|
48
|
+
if (!hasFlag(argv, '--server', '-s') && !hasFlag(argv, '--env', '-e')) {
|
|
49
|
+
const { baseURL } = (0, config_1.loadConfig)();
|
|
50
|
+
if (baseURL)
|
|
51
|
+
extra.push('--server', baseURL);
|
|
52
|
+
}
|
|
53
|
+
if (!hasFlag(argv, '--profile')) {
|
|
54
|
+
// The CLI's own profile, resolved the same way `BaseCommand` resolves it.
|
|
55
|
+
// These commands extend `Command`, so `init()` never ran and the module
|
|
56
|
+
// state `getActiveProfile()` reads was never set — asking it here would
|
|
57
|
+
// report `default` no matter what the user typed.
|
|
58
|
+
const profile = (0, keychain_1.resolveProfileFromArgv)(argv) ?? process.env.OVERSKY_PROFILE ?? null;
|
|
59
|
+
if (profile && profile !== keychain_1.DEFAULT_PROFILE)
|
|
60
|
+
extra.push('--profile', profile);
|
|
61
|
+
}
|
|
62
|
+
return [...argv, ...extra];
|
|
63
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two halves of the daemon-reference contract: how a daemon id is DISPLAYED
|
|
3
|
+
* and how a displayed one is READ BACK.
|
|
4
|
+
*
|
|
5
|
+
* `list-daemons` prints a decorated short form — `d_6a323ae4...` — and the two
|
|
6
|
+
* commands that consume a daemon reference (`revoke-daemon`,
|
|
7
|
+
* `set-capabilities`) matched the raw argument against `id.startsWith(prefix)`.
|
|
8
|
+
* So the value the product printed in a column literally headed DAEMON REF was
|
|
9
|
+
* rejected by every command that takes one, and the failure looked like "no such
|
|
10
|
+
* daemon" rather than "that is not the format I want". The sibling
|
|
11
|
+
* `machines show` accepts what `machines list` prints, which is the behaviour
|
|
12
|
+
* people reasonably expect here too.
|
|
13
|
+
*
|
|
14
|
+
* Keeping the decoration and accepting it back is the right trade: the `d_`
|
|
15
|
+
* prefix and the ellipsis are what tell a reader the value is truncated, and
|
|
16
|
+
* dropping them would make an 8-character fragment look like a full id.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Format a full daemon ObjectId as a short readable label:
|
|
20
|
+
* `d_xY3p...` — prefix + first 8 hex chars + an ellipsis.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatDaemonRef(id: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Read back anything `formatDaemonRef` may have produced, plus what a person
|
|
25
|
+
* plausibly pastes: with or without the `d_`, with or without a trailing `...`
|
|
26
|
+
* or a real ellipsis character, and with surrounding whitespace.
|
|
27
|
+
*
|
|
28
|
+
* A value that was never decorated passes through untouched, so a full id and a
|
|
29
|
+
* hand-typed prefix keep working exactly as before.
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeDaemonRef(input: string): string;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The two halves of the daemon-reference contract: how a daemon id is DISPLAYED
|
|
4
|
+
* and how a displayed one is READ BACK.
|
|
5
|
+
*
|
|
6
|
+
* `list-daemons` prints a decorated short form — `d_6a323ae4...` — and the two
|
|
7
|
+
* commands that consume a daemon reference (`revoke-daemon`,
|
|
8
|
+
* `set-capabilities`) matched the raw argument against `id.startsWith(prefix)`.
|
|
9
|
+
* So the value the product printed in a column literally headed DAEMON REF was
|
|
10
|
+
* rejected by every command that takes one, and the failure looked like "no such
|
|
11
|
+
* daemon" rather than "that is not the format I want". The sibling
|
|
12
|
+
* `machines show` accepts what `machines list` prints, which is the behaviour
|
|
13
|
+
* people reasonably expect here too.
|
|
14
|
+
*
|
|
15
|
+
* Keeping the decoration and accepting it back is the right trade: the `d_`
|
|
16
|
+
* prefix and the ellipsis are what tell a reader the value is truncated, and
|
|
17
|
+
* dropping them would make an 8-character fragment look like a full id.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.formatDaemonRef = formatDaemonRef;
|
|
21
|
+
exports.normalizeDaemonRef = normalizeDaemonRef;
|
|
22
|
+
/** Prefix the short form carries so a truncated id is visibly truncated. */
|
|
23
|
+
const DISPLAY_PREFIX = 'd_';
|
|
24
|
+
/**
|
|
25
|
+
* Format a full daemon ObjectId as a short readable label:
|
|
26
|
+
* `d_xY3p...` — prefix + first 8 hex chars + an ellipsis.
|
|
27
|
+
*/
|
|
28
|
+
function formatDaemonRef(id) {
|
|
29
|
+
if (!id || id.length < 8)
|
|
30
|
+
return id || '—';
|
|
31
|
+
return `${DISPLAY_PREFIX}${id.slice(0, 8)}...`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read back anything `formatDaemonRef` may have produced, plus what a person
|
|
35
|
+
* plausibly pastes: with or without the `d_`, with or without a trailing `...`
|
|
36
|
+
* or a real ellipsis character, and with surrounding whitespace.
|
|
37
|
+
*
|
|
38
|
+
* A value that was never decorated passes through untouched, so a full id and a
|
|
39
|
+
* hand-typed prefix keep working exactly as before.
|
|
40
|
+
*/
|
|
41
|
+
function normalizeDaemonRef(input) {
|
|
42
|
+
let out = input.trim();
|
|
43
|
+
if (out.toLowerCase().startsWith(DISPLAY_PREFIX))
|
|
44
|
+
out = out.slice(DISPLAY_PREFIX.length);
|
|
45
|
+
out = out.replace(/(?:\.{3}|…)$/, '');
|
|
46
|
+
return out.trim();
|
|
47
|
+
}
|
package/dist/lib/daemonBroker.js
CHANGED
|
@@ -286,7 +286,7 @@ async function attemptDaemonBrokerLogin(opts) {
|
|
|
286
286
|
return {
|
|
287
287
|
ok: false,
|
|
288
288
|
reason: 'base_url_mismatch',
|
|
289
|
-
detail: `No local
|
|
289
|
+
detail: `No local skrr runtime is logged in to ${opts.baseURL}; available daemon is logged in to ${mismatchedBootstrap.serverUrl}.`,
|
|
290
290
|
daemonServerUrl: mismatchedBootstrap.serverUrl,
|
|
291
291
|
};
|
|
292
292
|
}
|
|
@@ -22,7 +22,7 @@ function isDelegatedCliSession(env = process.env) {
|
|
|
22
22
|
function trustedLoopbackUrl(raw) {
|
|
23
23
|
const url = new URL(raw);
|
|
24
24
|
if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost', '::1'].includes(url.hostname)) {
|
|
25
|
-
throw new Error('Delegated
|
|
25
|
+
throw new Error('Delegated skrr CLI broker must be a loopback HTTP URL.');
|
|
26
26
|
}
|
|
27
27
|
return url.toString();
|
|
28
28
|
}
|
|
@@ -82,11 +82,11 @@ async function fetchDelegatedCliCredential(env = process.env, options = {}) {
|
|
|
82
82
|
if (body?.code === 'DELEGATED_CLI_CAPABILITY_REJECTED')
|
|
83
83
|
return null;
|
|
84
84
|
}
|
|
85
|
-
throw new Error(`Delegated
|
|
85
|
+
throw new Error(`Delegated skrr CLI credential broker returned HTTP ${res.status}.`);
|
|
86
86
|
}
|
|
87
87
|
const body = (await res.json());
|
|
88
88
|
if (typeof body.accessToken !== 'string' || body.accessToken.length === 0) {
|
|
89
|
-
throw new Error('Delegated
|
|
89
|
+
throw new Error('Delegated skrr CLI credential broker returned no access token.');
|
|
90
90
|
}
|
|
91
91
|
const credential = {
|
|
92
92
|
token: body.accessToken,
|
|
@@ -3,8 +3,25 @@ export declare const RUNTIME_BINARY_NAMES: readonly ["skrrd", "oversky"];
|
|
|
3
3
|
/** Resolve the absolute path of `oversky` if it exists, else return null. */
|
|
4
4
|
export declare function findOverskyBinary(): string | null;
|
|
5
5
|
/**
|
|
6
|
-
* Pretty hint shown when
|
|
6
|
+
* Pretty hint shown when the runtime isn't installed. Kept short — points
|
|
7
7
|
* users at the canonical install paths rather than enumerating them.
|
|
8
|
+
*
|
|
9
|
+
* THE ADDRESSES BELOW STILL SAY `oversky`, ON PURPOSE.
|
|
10
|
+
* ---------------------------------------------------
|
|
11
|
+
* The rename moved this text to `skrr` and pointed it at
|
|
12
|
+
* `dush1023/skrr/skrrd`, `raw.githubusercontent.com/dush1023/skrr/...` and
|
|
13
|
+
* `github.com/dush1023/skrr` — none of which exist. The tap
|
|
14
|
+
* `dush1023/homebrew-skrr` 404s; only `dush1023/homebrew-oversky` is
|
|
15
|
+
* published, and the repository is still `dush1023/OverSky`.
|
|
16
|
+
*
|
|
17
|
+
* An install instruction is only worth what it installs. Renaming these
|
|
18
|
+
* before the tap and repository move produces a message that reads correct
|
|
19
|
+
* and fails when followed — the same defect as the "install it with
|
|
20
|
+
* `sky code install`" hint, which named a command that never existed.
|
|
21
|
+
*
|
|
22
|
+
* They move when the Homebrew tap is published (that work is tracked
|
|
23
|
+
* separately) and when the repository is renamed — not before, and not as
|
|
24
|
+
* part of a copy sweep.
|
|
8
25
|
*/
|
|
9
26
|
export declare function notInstalledMessage(): string;
|
|
10
27
|
/**
|
package/dist/lib/exec-oversky.js
CHANGED
|
@@ -76,17 +76,34 @@ function isExecutable(p) {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
|
-
* Pretty hint shown when
|
|
79
|
+
* Pretty hint shown when the runtime isn't installed. Kept short — points
|
|
80
80
|
* users at the canonical install paths rather than enumerating them.
|
|
81
|
+
*
|
|
82
|
+
* THE ADDRESSES BELOW STILL SAY `oversky`, ON PURPOSE.
|
|
83
|
+
* ---------------------------------------------------
|
|
84
|
+
* The rename moved this text to `skrr` and pointed it at
|
|
85
|
+
* `dush1023/skrr/skrrd`, `raw.githubusercontent.com/dush1023/skrr/...` and
|
|
86
|
+
* `github.com/dush1023/skrr` — none of which exist. The tap
|
|
87
|
+
* `dush1023/homebrew-skrr` 404s; only `dush1023/homebrew-oversky` is
|
|
88
|
+
* published, and the repository is still `dush1023/OverSky`.
|
|
89
|
+
*
|
|
90
|
+
* An install instruction is only worth what it installs. Renaming these
|
|
91
|
+
* before the tap and repository move produces a message that reads correct
|
|
92
|
+
* and fails when followed — the same defect as the "install it with
|
|
93
|
+
* `sky code install`" hint, which named a command that never existed.
|
|
94
|
+
*
|
|
95
|
+
* They move when the Homebrew tap is published (that work is tracked
|
|
96
|
+
* separately) and when the repository is renamed — not before, and not as
|
|
97
|
+
* part of a copy sweep.
|
|
81
98
|
*/
|
|
82
99
|
function notInstalledMessage() {
|
|
83
100
|
return [
|
|
84
101
|
'The skrr local runtime is not installed on this machine.',
|
|
85
102
|
'',
|
|
86
103
|
'Install:',
|
|
87
|
-
' macOS: brew install dush1023/
|
|
88
|
-
' Linux: curl -fsSL https://raw.githubusercontent.com/dush1023/
|
|
89
|
-
' Other: https://github.com/dush1023/
|
|
104
|
+
' macOS: brew install dush1023/oversky/oversky',
|
|
105
|
+
' Linux: curl -fsSL https://raw.githubusercontent.com/dush1023/OverSky/main/scripts/install-daemon.sh | bash',
|
|
106
|
+
' Other: https://github.com/dush1023/OverSky#installation',
|
|
90
107
|
'',
|
|
91
108
|
'Once installed, re-run your command.',
|
|
92
109
|
].join('\n');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render server-stored rich text as something a terminal can read.
|
|
3
|
+
*
|
|
4
|
+
* Task, goal and project descriptions are persisted as HTML — `--description
|
|
5
|
+
* -format markdown` is converted on the way in — so a CLI that prints the field
|
|
6
|
+
* verbatim shows the user `<p>…</p>` and `<code>…</code>` around their own
|
|
7
|
+
* words. They wrote markdown and got tags back.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately NOT a general HTML renderer. It converts the block boundaries
|
|
10
|
+
* that carry meaning in a paragraph of prose, drops the rest of the tags, and
|
|
11
|
+
* decodes the entity set the server actually emits. Anything that does not look
|
|
12
|
+
* like markup is returned untouched, so a plain-text description keeps its own
|
|
13
|
+
* whitespace instead of being reflowed by a converter it never needed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function htmlToDisplayText(value: string): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Render server-stored rich text as something a terminal can read.
|
|
4
|
+
*
|
|
5
|
+
* Task, goal and project descriptions are persisted as HTML — `--description
|
|
6
|
+
* -format markdown` is converted on the way in — so a CLI that prints the field
|
|
7
|
+
* verbatim shows the user `<p>…</p>` and `<code>…</code>` around their own
|
|
8
|
+
* words. They wrote markdown and got tags back.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately NOT a general HTML renderer. It converts the block boundaries
|
|
11
|
+
* that carry meaning in a paragraph of prose, drops the rest of the tags, and
|
|
12
|
+
* decodes the entity set the server actually emits. Anything that does not look
|
|
13
|
+
* like markup is returned untouched, so a plain-text description keeps its own
|
|
14
|
+
* whitespace instead of being reflowed by a converter it never needed.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.htmlToDisplayText = htmlToDisplayText;
|
|
18
|
+
/** Cheap, deliberate: a tag-shaped substring is the only trigger. */
|
|
19
|
+
function looksLikeHtml(value) {
|
|
20
|
+
return /<\/?[a-z][^>]*>/i.test(value);
|
|
21
|
+
}
|
|
22
|
+
function htmlToDisplayText(value) {
|
|
23
|
+
if (!looksLikeHtml(value))
|
|
24
|
+
return value;
|
|
25
|
+
return (value
|
|
26
|
+
.replace(/<br\s*\/?>/gi, '\n')
|
|
27
|
+
.replace(/<\/(p|div|li|h[1-6])>/gi, '\n')
|
|
28
|
+
.replace(/<li[^>]*>/gi, ' - ')
|
|
29
|
+
.replace(/<[^>]+>/g, '')
|
|
30
|
+
.replace(/ /g, ' ')
|
|
31
|
+
.replace(/'/g, "'")
|
|
32
|
+
.replace(/"/g, '"')
|
|
33
|
+
.replace(/</g, '<')
|
|
34
|
+
.replace(/>/g, '>')
|
|
35
|
+
// `&` LAST, or `&lt;` would decode twice into a bare `<`.
|
|
36
|
+
.replace(/&/g, '&')
|
|
37
|
+
.replace(/[ \t]+/g, ' ')
|
|
38
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
39
|
+
.trim());
|
|
40
|
+
}
|
package/dist/lib/keychain.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
/** Pre-Phase-K namespace; reserved for a future migration helper. */
|
|
2
|
+
export declare const DEFAULT_PROFILE = "default";
|
|
1
3
|
export declare function setActiveProfile(profile: string): void;
|
|
4
|
+
/**
|
|
5
|
+
* Whether the profile has been chosen for this process.
|
|
6
|
+
*
|
|
7
|
+
* Borrowed from `daemon/src/config.ts`, which warns when a writer runs before
|
|
8
|
+
* `setActiveProfile()` and says why: such a caller "is a bug — they're writing
|
|
9
|
+
* to the legacy single-tenant root instead of the active profile's dir". The
|
|
10
|
+
* failure is silent and permanent, so it needs to be noisy once.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isProfileResolved(): boolean;
|
|
2
13
|
export declare function getActiveProfile(): string;
|
|
3
14
|
/** @internal exposed for tests / diagnostics. */
|
|
4
15
|
export declare function __currentServiceForTest(): string;
|
|
@@ -38,8 +49,40 @@ export declare function writeServerOrigin(origin: string): boolean;
|
|
|
38
49
|
export declare function deleteServerOrigin(): void;
|
|
39
50
|
export declare function deleteToken(): void;
|
|
40
51
|
export declare function deleteRefreshToken(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Remove the credentials this product wrote under its previous brand.
|
|
54
|
+
*
|
|
55
|
+
* `logout` used to delete only the CURRENT service and report an unqualified
|
|
56
|
+
* "Signed out." On a machine carried through the rename that left the
|
|
57
|
+
* pre-rename CLI credential, the pre-rename daemon credentials, and BOTH KEKs
|
|
58
|
+
* in place — so the sealed envelope and the key that unwraps it were still
|
|
59
|
+
* sitting there after the product said you were signed out. `logout --help`
|
|
60
|
+
* offers `--all-devices` for "a stolen-laptop incident", which is the one
|
|
61
|
+
* situation where that is exactly wrong.
|
|
62
|
+
*
|
|
63
|
+
* Returns the services it actually removed something from, so the caller can
|
|
64
|
+
* say what happened instead of destroying credentials silently.
|
|
65
|
+
*
|
|
66
|
+
* NOTE this also signs out the retired `oversky` binary, if one is still
|
|
67
|
+
* installed. That is the intent — same account, same machine — and the cutover
|
|
68
|
+
* runbook already lists these items for removal.
|
|
69
|
+
*/
|
|
70
|
+
export declare function deleteLegacyBrandEntries(): string[];
|
|
41
71
|
/**
|
|
42
72
|
* Remove every CLI keychain slot for the active profile. Used by `skrr logout`.
|
|
43
73
|
* Safe to call on a clean system — missing items are not an error.
|
|
44
74
|
*/
|
|
45
75
|
export declare function deleteAll(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Pull `--profile` out of raw argv.
|
|
78
|
+
*
|
|
79
|
+
* Deliberately minimal: it recognises `--profile x` and `--profile=x` and
|
|
80
|
+
* nothing else. This runs before any validation, so it must not throw, must not
|
|
81
|
+
* consume anything it does not own, and must not care about flag ordering —
|
|
82
|
+
* anything it gets wrong is corrected microseconds later when oclif parses the
|
|
83
|
+
* same argv properly and rejects a malformed invocation.
|
|
84
|
+
*
|
|
85
|
+
* Returns null rather than the default, so the caller can fall through to
|
|
86
|
+
* `OVERSKY_PROFILE` without a flag having to out-rank an env var it never saw.
|
|
87
|
+
*/
|
|
88
|
+
export declare function resolveProfileFromArgv(argv: readonly string[] | undefined): string | null;
|
package/dist/lib/keychain.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_PROFILE = void 0;
|
|
3
4
|
exports.setActiveProfile = setActiveProfile;
|
|
5
|
+
exports.isProfileResolved = isProfileResolved;
|
|
4
6
|
exports.getActiveProfile = getActiveProfile;
|
|
5
7
|
exports.__currentServiceForTest = __currentServiceForTest;
|
|
6
8
|
exports.isAvailable = isAvailable;
|
|
@@ -14,7 +16,9 @@ exports.writeServerOrigin = writeServerOrigin;
|
|
|
14
16
|
exports.deleteServerOrigin = deleteServerOrigin;
|
|
15
17
|
exports.deleteToken = deleteToken;
|
|
16
18
|
exports.deleteRefreshToken = deleteRefreshToken;
|
|
19
|
+
exports.deleteLegacyBrandEntries = deleteLegacyBrandEntries;
|
|
17
20
|
exports.deleteAll = deleteAll;
|
|
21
|
+
exports.resolveProfileFromArgv = resolveProfileFromArgv;
|
|
18
22
|
/**
|
|
19
23
|
* keychain.ts — macOS Keychain-backed token storage for the Sky CLI.
|
|
20
24
|
*
|
|
@@ -44,10 +48,11 @@ exports.deleteAll = deleteAll;
|
|
|
44
48
|
*/
|
|
45
49
|
const node_child_process_1 = require("node:child_process");
|
|
46
50
|
const cred_envelope_1 = require("./cred-envelope");
|
|
51
|
+
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
47
52
|
/** Service-name prefix. Always followed by `.<profile>`. */
|
|
48
53
|
const SERVICE_BASE = 'ai.skrr.cli';
|
|
49
54
|
/** Pre-Phase-K namespace; reserved for a future migration helper. */
|
|
50
|
-
|
|
55
|
+
exports.DEFAULT_PROFILE = 'default';
|
|
51
56
|
const ACCOUNT_TOKEN = 'cli-token';
|
|
52
57
|
const ACCOUNT_EXPIRES = 'cli-token-expires';
|
|
53
58
|
const ACCOUNT_REFRESH = 'cli-refresh';
|
|
@@ -58,14 +63,35 @@ const SECURITY_ITEM_NOT_FOUND = 44;
|
|
|
58
63
|
/** Cached availability — probed once at first call. */
|
|
59
64
|
let _availability = null;
|
|
60
65
|
/**
|
|
61
|
-
* Active profile for this process.
|
|
62
|
-
*
|
|
66
|
+
* Active profile for this process.
|
|
67
|
+
*
|
|
68
|
+
* Wired from `--profile` / `OVERSKY_PROFILE` in `BaseCommand.init()`, before
|
|
69
|
+
* anything reads a credential. The comment here used to say "Phase K will wire
|
|
70
|
+
* `setActiveProfile('work')` onto a `--profile` flag; today everything resolves
|
|
71
|
+
* to `default`" — and that stayed true long enough to cost something: with one
|
|
72
|
+
* slot, signing into a second deployment EVICTED the first, so a round trip
|
|
73
|
+
* meant two interactive logins and an agent could not make one at all
|
|
74
|
+
* (OSK-290).
|
|
63
75
|
*/
|
|
64
|
-
let _activeProfile = DEFAULT_PROFILE;
|
|
76
|
+
let _activeProfile = exports.DEFAULT_PROFILE;
|
|
77
|
+
/** True once a caller has chosen, so a writer can tell "default" from "unset". */
|
|
78
|
+
let _profileResolved = false;
|
|
65
79
|
function setActiveProfile(profile) {
|
|
80
|
+
_profileResolved = true;
|
|
66
81
|
if (profile && profile.length > 0)
|
|
67
82
|
_activeProfile = profile;
|
|
68
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Whether the profile has been chosen for this process.
|
|
86
|
+
*
|
|
87
|
+
* Borrowed from `daemon/src/config.ts`, which warns when a writer runs before
|
|
88
|
+
* `setActiveProfile()` and says why: such a caller "is a bug — they're writing
|
|
89
|
+
* to the legacy single-tenant root instead of the active profile's dir". The
|
|
90
|
+
* failure is silent and permanent, so it needs to be noisy once.
|
|
91
|
+
*/
|
|
92
|
+
function isProfileResolved() {
|
|
93
|
+
return _profileResolved;
|
|
94
|
+
}
|
|
69
95
|
function getActiveProfile() {
|
|
70
96
|
return _activeProfile;
|
|
71
97
|
}
|
|
@@ -307,6 +333,88 @@ function deleteRefreshToken() {
|
|
|
307
333
|
deleteSlot(ACCOUNT_REFRESH);
|
|
308
334
|
deleteSlot(ACCOUNT_REFRESH_EXPIRES);
|
|
309
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Every Keychain service this product wrote under its PREVIOUS brand.
|
|
338
|
+
*
|
|
339
|
+
* Discovered rather than enumerated, because the daemon's services carry a
|
|
340
|
+
* per-profile hash (`ai.oversky.daemon.dev-f00ad7c1`) that cannot be
|
|
341
|
+
* reconstructed from a name. Metadata only — `dump-keychain` without `-d`
|
|
342
|
+
* prints service names and does not prompt for or reveal any secret.
|
|
343
|
+
*
|
|
344
|
+
* Filtered to `LEGACY_NATIVE_ID_PREFIXES` followed by a dot, so a third-party
|
|
345
|
+
* item that merely starts with the same letters is never in scope.
|
|
346
|
+
*/
|
|
347
|
+
function discoverLegacyBrandServices() {
|
|
348
|
+
let dump;
|
|
349
|
+
try {
|
|
350
|
+
dump = (0, node_child_process_1.execFileSync)('security', ['dump-keychain'], {
|
|
351
|
+
encoding: 'utf-8',
|
|
352
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
const found = new Set();
|
|
359
|
+
for (const match of dump.matchAll(/"svce"<blob>="([^"]*)"/g)) {
|
|
360
|
+
const service = match[1];
|
|
361
|
+
if (auth_core_1.LEGACY_NATIVE_ID_PREFIXES.some((prefix) => service.startsWith(`${prefix}.`))) {
|
|
362
|
+
found.add(service);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return [...found].sort();
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Delete every item under one service, without needing its account names.
|
|
369
|
+
*
|
|
370
|
+
* `delete-generic-password -s <svc>` removes ONE matching item, so a service
|
|
371
|
+
* holding a token, its expiry and a refresh pair needs several passes. Bounded,
|
|
372
|
+
* because a delete that never reports "not found" would otherwise spin.
|
|
373
|
+
*/
|
|
374
|
+
function deleteEntireService(service) {
|
|
375
|
+
let removedAny = false;
|
|
376
|
+
for (let i = 0; i < 32; i += 1) {
|
|
377
|
+
try {
|
|
378
|
+
(0, node_child_process_1.execFileSync)('security', ['delete-generic-password', '-s', service], {
|
|
379
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
380
|
+
});
|
|
381
|
+
removedAny = true;
|
|
382
|
+
}
|
|
383
|
+
catch (err) {
|
|
384
|
+
const status = err.status;
|
|
385
|
+
if (status === SECURITY_ITEM_NOT_FOUND)
|
|
386
|
+
return removedAny;
|
|
387
|
+
if (process.env.DEBUG) {
|
|
388
|
+
console.error(`[cli/keychain] legacy sweep failed for ${service} (status=${status ?? 'unknown'})`);
|
|
389
|
+
}
|
|
390
|
+
return removedAny;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return removedAny;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Remove the credentials this product wrote under its previous brand.
|
|
397
|
+
*
|
|
398
|
+
* `logout` used to delete only the CURRENT service and report an unqualified
|
|
399
|
+
* "Signed out." On a machine carried through the rename that left the
|
|
400
|
+
* pre-rename CLI credential, the pre-rename daemon credentials, and BOTH KEKs
|
|
401
|
+
* in place — so the sealed envelope and the key that unwraps it were still
|
|
402
|
+
* sitting there after the product said you were signed out. `logout --help`
|
|
403
|
+
* offers `--all-devices` for "a stolen-laptop incident", which is the one
|
|
404
|
+
* situation where that is exactly wrong.
|
|
405
|
+
*
|
|
406
|
+
* Returns the services it actually removed something from, so the caller can
|
|
407
|
+
* say what happened instead of destroying credentials silently.
|
|
408
|
+
*
|
|
409
|
+
* NOTE this also signs out the retired `oversky` binary, if one is still
|
|
410
|
+
* installed. That is the intent — same account, same machine — and the cutover
|
|
411
|
+
* runbook already lists these items for removal.
|
|
412
|
+
*/
|
|
413
|
+
function deleteLegacyBrandEntries() {
|
|
414
|
+
if (!isAvailable())
|
|
415
|
+
return [];
|
|
416
|
+
return discoverLegacyBrandServices().filter((service) => deleteEntireService(service));
|
|
417
|
+
}
|
|
310
418
|
/**
|
|
311
419
|
* Remove every CLI keychain slot for the active profile. Used by `skrr logout`.
|
|
312
420
|
* Safe to call on a clean system — missing items are not an error.
|
|
@@ -316,3 +424,36 @@ function deleteAll() {
|
|
|
316
424
|
deleteRefreshToken();
|
|
317
425
|
deleteServerOrigin();
|
|
318
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Pull `--profile` out of raw argv.
|
|
429
|
+
*
|
|
430
|
+
* Deliberately minimal: it recognises `--profile x` and `--profile=x` and
|
|
431
|
+
* nothing else. This runs before any validation, so it must not throw, must not
|
|
432
|
+
* consume anything it does not own, and must not care about flag ordering —
|
|
433
|
+
* anything it gets wrong is corrected microseconds later when oclif parses the
|
|
434
|
+
* same argv properly and rejects a malformed invocation.
|
|
435
|
+
*
|
|
436
|
+
* Returns null rather than the default, so the caller can fall through to
|
|
437
|
+
* `OVERSKY_PROFILE` without a flag having to out-rank an env var it never saw.
|
|
438
|
+
*/
|
|
439
|
+
function resolveProfileFromArgv(argv) {
|
|
440
|
+
// `undefined` is a real input, not a defensive flourish: a command
|
|
441
|
+
// constructed directly — as several suites do — has no argv yet when `init()`
|
|
442
|
+
// runs. The contract above says this must not throw, and it did.
|
|
443
|
+
if (!Array.isArray(argv))
|
|
444
|
+
return null;
|
|
445
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
446
|
+
const token = argv[i];
|
|
447
|
+
if (token === '--')
|
|
448
|
+
break;
|
|
449
|
+
if (token === '--profile') {
|
|
450
|
+
const value = argv[i + 1];
|
|
451
|
+
return value && !value.startsWith('-') ? value : null;
|
|
452
|
+
}
|
|
453
|
+
if (token.startsWith('--profile=')) {
|
|
454
|
+
const value = token.slice('--profile='.length);
|
|
455
|
+
return value.length > 0 ? value : null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return null;
|
|
459
|
+
}
|
package/dist/lib/login.js
CHANGED
|
@@ -82,7 +82,7 @@ async function cliLogin(opts = {}) {
|
|
|
82
82
|
});
|
|
83
83
|
if (brokerResult.ok) {
|
|
84
84
|
console.log('');
|
|
85
|
-
console.log(' Authorized via the local
|
|
85
|
+
console.log(' Authorized via the local skrr runtime (no browser needed).');
|
|
86
86
|
return {
|
|
87
87
|
token: brokerResult.accessToken,
|
|
88
88
|
refreshToken: brokerResult.refreshToken,
|
|
@@ -105,7 +105,7 @@ async function cliLogin(opts = {}) {
|
|
|
105
105
|
// broker failures — missing bootstrap, network blip, server 5xx —
|
|
106
106
|
// silently fall through to PKCE / device-code below.
|
|
107
107
|
if (brokerResult.reason === 'ci_token_refused') {
|
|
108
|
-
throw new Error('The local
|
|
108
|
+
throw new Error('The local skrr runtime is bootstrapped from a CI token, which cannot broker an interactive CLI login. ' +
|
|
109
109
|
'Use `skrr create-token --name <name>` to mint a long-lived CI credential directly, ' +
|
|
110
110
|
'or run `skrr login` on a machine where the daemon was authenticated interactively.');
|
|
111
111
|
}
|
|
@@ -116,7 +116,7 @@ async function cliLogin(opts = {}) {
|
|
|
116
116
|
// "I'm logging into a different server than the daemon".
|
|
117
117
|
if (brokerResult.reason === 'base_url_mismatch' && brokerResult.daemonServerUrl) {
|
|
118
118
|
console.log('');
|
|
119
|
-
console.log(` The local
|
|
119
|
+
console.log(` The local skrr runtime is logged in to ${brokerResult.daemonServerUrl}, but skrr is configured for ${serverUrl}.`);
|
|
120
120
|
console.log(` Skipping the daemon-broker handoff. Run \`skrr login --base-url ${brokerResult.daemonServerUrl}\` to use the daemon instead.`);
|
|
121
121
|
}
|
|
122
122
|
}
|