@skrr-ai/cli 0.1.50 → 0.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.js +59 -2
- package/dist/commands/agents/chat.d.ts +14 -0
- package/dist/commands/agents/chat.js +37 -1
- package/dist/commands/agents/show.d.ts +9 -0
- package/dist/commands/agents/show.js +53 -0
- package/dist/commands/agents/update.d.ts +9 -0
- package/dist/commands/agents/update.js +27 -0
- package/dist/commands/balance/show.d.ts +34 -0
- package/dist/commands/balance/show.js +92 -2
- package/dist/commands/commitments/doctor.d.ts +1 -0
- package/dist/commands/commitments/doctor.js +19 -4
- package/dist/commands/commitments/effective-policy.js +15 -1
- package/dist/commands/commitments/next-tick.js +3 -1
- package/dist/commands/commitments/preflight.js +10 -0
- package/dist/commands/commitments/show.js +11 -1
- package/dist/commands/daemon/config.d.ts +15 -0
- package/dist/commands/daemon/config.js +38 -0
- package/dist/commands/daemon/index.js +1 -0
- package/dist/commands/daemon/status.js +15 -1
- package/dist/commands/harnesses/models.d.ts +54 -0
- package/dist/commands/harnesses/models.js +100 -7
- package/dist/commands/harnesses/show.d.ts +11 -0
- package/dist/commands/harnesses/show.js +35 -0
- package/dist/commands/harnesses/update.d.ts +28 -1
- package/dist/commands/harnesses/update.js +73 -10
- package/dist/commands/outbox/list.d.ts +12 -1
- package/dist/commands/outbox/list.js +31 -2
- package/dist/commands/revoke-daemon.js +9 -0
- package/dist/commands/spaces/create.d.ts +1 -0
- package/dist/commands/spaces/create.js +17 -0
- package/dist/commands/spaces/show.js +5 -0
- package/dist/commands/spaces/update.d.ts +1 -0
- package/dist/commands/spaces/update.js +16 -0
- package/dist/commands/tasks/create.d.ts +1 -0
- package/dist/commands/tasks/create.js +5 -0
- package/dist/commands/tasks/show.js +45 -0
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +21 -0
- package/dist/commands/tasks/upsert.d.ts +1 -0
- package/dist/commands/tasks/upsert.js +16 -0
- package/dist/lib/agentic-stream.d.ts +68 -1
- package/dist/lib/agentic-stream.js +294 -7
- package/dist/lib/auth-core-init.d.ts +2 -10
- package/dist/lib/auth-core-init.js +20 -67
- package/dist/lib/auth-failure.d.ts +33 -0
- package/dist/lib/auth-failure.js +65 -0
- package/dist/lib/commitments.d.ts +21 -1
- package/dist/lib/commitments.js +34 -0
- package/dist/lib/daemonBroker.d.ts +14 -0
- package/dist/lib/daemonBroker.js +64 -12
- package/dist/lib/delegated-cli.js +4 -1
- package/dist/lib/exec-runtime-binary.d.ts +3 -1
- package/dist/lib/exec-runtime-binary.js +4 -2
- package/dist/lib/first-party-harness-broker.js +4 -1
- package/dist/lib/harnesses.d.ts +10 -0
- package/dist/lib/live-runtime-binary.d.ts +40 -0
- package/dist/lib/live-runtime-binary.js +193 -0
- package/dist/lib/login.d.ts +23 -0
- package/dist/lib/login.js +44 -10
- package/dist/lib/message-intent.js +3 -1
- package/dist/lib/tasks.d.ts +20 -0
- package/dist/lib/tasks.js +54 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.js +26 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.d.ts +28 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +23 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +41 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +25 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loopbackHttp.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loopbackHttp.js +268 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.d.ts +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.js +11 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +36 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +156 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.d.ts +8 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.js +8 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +22 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +61 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.js +25 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.d.ts +28 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +22 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +41 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +10 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loopbackHttp.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loopbackHttp.js +257 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.d.ts +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.js +11 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +36 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +147 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.d.ts +8 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.js +8 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +22 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +58 -1
- package/dist/node_modules/@skrr-ai/auth-core/package.json +21 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +1928 -1924
- package/oclif.manifest.json +23832 -23688
- package/package.json +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* auth-failure.ts — say WHY a request was refused on authentication (OSK-12116).
|
|
4
|
+
*
|
|
5
|
+
* A 401 reaches the CLI after its own renewal has already failed: the access
|
|
6
|
+
* token expired, the refresh was refused, and the retry went out with the dead
|
|
7
|
+
* token. The server's answer to that retry is `TOKEN_EXPIRED`, which is true and
|
|
8
|
+
* useless — the expiry is routine, the refusal to RENEW is the fault, and it was
|
|
9
|
+
* visible only as an `[auth-core warn]` line on stderr.
|
|
10
|
+
*
|
|
11
|
+
* auth-core latches every permanent refresh refusal (`needs-reauth.json`, the
|
|
12
|
+
* same record `skrr whoami` prints as "Refresh state"). This module reads that
|
|
13
|
+
* latch and turns it into the sentence the error should have carried.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.describeRefreshRefusal = describeRefreshRefusal;
|
|
17
|
+
/**
|
|
18
|
+
* Explain one refresh refusal in terms of what the reader can do about it.
|
|
19
|
+
* Returns null when there is no latched refusal, so the caller keeps its
|
|
20
|
+
* generic wording rather than inventing a cause.
|
|
21
|
+
*/
|
|
22
|
+
function describeRefreshRefusal(refusal, opts) {
|
|
23
|
+
if (!refusal?.reason)
|
|
24
|
+
return null;
|
|
25
|
+
const { bin } = opts;
|
|
26
|
+
const code = refusal.reason;
|
|
27
|
+
const said = refusal.message ? ` (${code}: ${refusal.message})` : ` (${code})`;
|
|
28
|
+
const relogin = `Run \`${bin} login\` to sign in again.`;
|
|
29
|
+
const message = refusal.message ?? '';
|
|
30
|
+
// The row the stored refresh token belongs to was minted for a different CLI
|
|
31
|
+
// identity than the one this config presents. The keychain slot is keyed by
|
|
32
|
+
// profile, while the CLI ID lives in the config directory — so a second skrr
|
|
33
|
+
// configuration on this machine (a different HOME or config dir sharing the
|
|
34
|
+
// same login Keychain) can write this profile's credential under its own ID.
|
|
35
|
+
// Observed: a token minted for `cli_devin_dogfood` sitting in the default
|
|
36
|
+
// profile's slot.
|
|
37
|
+
if (/bound to a different daemon/i.test(message)) {
|
|
38
|
+
return {
|
|
39
|
+
code,
|
|
40
|
+
message: `This profile's stored sign-in could not be renewed${said}. The credential in its ` +
|
|
41
|
+
`Keychain slot was issued to a different CLI identity than this one` +
|
|
42
|
+
`${opts.cliId ? ` (${opts.cliId})` : ''} — usually another skrr configuration on this ` +
|
|
43
|
+
`machine (a different HOME or config directory) signed in and wrote over it. ${relogin}`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (code === 'SESSION_REVOKED') {
|
|
47
|
+
return {
|
|
48
|
+
code,
|
|
49
|
+
message: `This sign-in was revoked${said}. Signing out elsewhere revokes it, and so does ` +
|
|
50
|
+
`revoking a daemon that brokered it (\`${bin} login\` without a browser signs in ` +
|
|
51
|
+
`through this machine's daemon). ${relogin}`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (code === 'REFRESH_REUSED') {
|
|
55
|
+
return {
|
|
56
|
+
code,
|
|
57
|
+
message: `This sign-in was ended because its refresh token was presented twice${said}; the ` +
|
|
58
|
+
`server treats that as possible theft and revokes the whole family. ${relogin}`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
code,
|
|
63
|
+
message: `This sign-in could not be renewed${said}. ${relogin}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* "hold this state", derived from a Compass invariant — not authored here).
|
|
18
18
|
*/
|
|
19
19
|
import { COMMITMENT_WATCHED_SOURCES, COMMITMENT_TEMPLATE_IDS, COMMITMENT_CADENCE_MODES, COMMITMENT_CADENCE_TIME_PATTERN, COMMITMENT_CADENCE_MAX_TIMES, COMMITMENT_AUTONOMY_MODES, COMMITMENT_EXECUTION_ISOLATION_MODES, COMMITMENT_STATUSES, COMMITMENT_KIND_VALUES } from '@skrr-ai/data-provider';
|
|
20
|
-
import type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, CommitmentExecutionReceiptListResponse, CommitmentExecutionReceiptQuarterlyMetricsResponse, CommitmentCapabilitySource, CommitmentDeliveryPatchResponse, CommitmentDeliveryBundleResponse, CommitmentCyclesResponse, CommitmentExplanationResponse } from '@skrr-ai/data-provider';
|
|
20
|
+
import type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, CommitmentExecutionReceiptListResponse, CommitmentExecutionReceiptQuarterlyMetricsResponse, CommitmentCapabilitySource, CommitmentDeliveryPatchResponse, CommitmentDeliveryBundleResponse, CommitmentCyclesResponse, CommitmentExplanationResponse, CommitmentRunPermissions } from '@skrr-ai/data-provider';
|
|
21
21
|
import { withQuery } from './triggers';
|
|
22
22
|
export { COMMITMENT_WATCHED_SOURCES, COMMITMENT_TEMPLATE_IDS, COMMITMENT_CADENCE_MODES, COMMITMENT_CADENCE_TIME_PATTERN, COMMITMENT_CADENCE_MAX_TIMES, COMMITMENT_STATUSES, COMMITMENT_KIND_VALUES, };
|
|
23
23
|
export type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, };
|
|
@@ -99,7 +99,27 @@ export type CommitmentPreflightReport = {
|
|
|
99
99
|
suppressedBy?: string | null;
|
|
100
100
|
[key: string]: unknown;
|
|
101
101
|
};
|
|
102
|
+
/** Whose permissions a run uses (OSK-11975). Absent from older servers. */
|
|
103
|
+
permissions?: CommitmentRunPermissions | null;
|
|
104
|
+
/** `retired` names the fence fields OSK-11975 made inert (OSK-12065). */
|
|
105
|
+
execution?: {
|
|
106
|
+
retired?: string[];
|
|
107
|
+
retiredReason?: string;
|
|
108
|
+
} & Record<string, unknown>;
|
|
102
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* The lines every Commitment read surface prints for "whose permissions does a
|
|
112
|
+
* run use?" — `show`, `effective-policy` and `preflight` share it so the three
|
|
113
|
+
* cannot phrase it three ways (OSK-12065). The sentence and the warnings are
|
|
114
|
+
* the server's; this only lays them out. `null` (an older server that does not
|
|
115
|
+
* report it) prints nothing rather than a guess.
|
|
116
|
+
*/
|
|
117
|
+
export declare function permissionLines(permissions: CommitmentRunPermissions | null | undefined): string[];
|
|
118
|
+
/**
|
|
119
|
+
* One line naming fields that are still in the JSON but decide nothing any
|
|
120
|
+
* more. Deprecation, not removal: `--json` keeps them for scripts.
|
|
121
|
+
*/
|
|
122
|
+
export declare function retiredFieldsLine(retired: string[] | undefined, reason: string | undefined): string | null;
|
|
103
123
|
/**
|
|
104
124
|
* A Commitment Pack's readiness receipt.
|
|
105
125
|
*
|
package/dist/lib/commitments.js
CHANGED
|
@@ -4,6 +4,8 @@ exports.COMMITMENT_CLI_EVALUATORS = exports.COMMITMENT_CREATE_KEYS = exports.COM
|
|
|
4
4
|
exports.storedAutonomyModeForAuthoring = storedAutonomyModeForAuthoring;
|
|
5
5
|
exports.authoringAutonomyModeForStored = authoringAutonomyModeForStored;
|
|
6
6
|
exports.commitmentAutonomyLabel = commitmentAutonomyLabel;
|
|
7
|
+
exports.permissionLines = permissionLines;
|
|
8
|
+
exports.retiredFieldsLine = retiredFieldsLine;
|
|
7
9
|
exports.readCommitmentAgentDirective = readCommitmentAgentDirective;
|
|
8
10
|
exports.normalizeCreateBody = normalizeCreateBody;
|
|
9
11
|
exports.parseCommitmentConcurrencyLimit = parseCommitmentConcurrencyLimit;
|
|
@@ -109,6 +111,33 @@ function commitmentAutonomyLabel(mode) {
|
|
|
109
111
|
*/
|
|
110
112
|
exports.MIN_COMMITMENT_INTERVAL_MS = 60_000;
|
|
111
113
|
exports.MAX_COMMITMENT_INTERVAL_MS = 365 * 24 * 60 * 60 * 1000;
|
|
114
|
+
/**
|
|
115
|
+
* The lines every Commitment read surface prints for "whose permissions does a
|
|
116
|
+
* run use?" — `show`, `effective-policy` and `preflight` share it so the three
|
|
117
|
+
* cannot phrase it three ways (OSK-12065). The sentence and the warnings are
|
|
118
|
+
* the server's; this only lays them out. `null` (an older server that does not
|
|
119
|
+
* report it) prints nothing rather than a guess.
|
|
120
|
+
*/
|
|
121
|
+
function permissionLines(permissions) {
|
|
122
|
+
if (!permissions?.summary)
|
|
123
|
+
return [];
|
|
124
|
+
const lines = [`Permissions: ${permissions.summary}`];
|
|
125
|
+
for (const warning of permissions.warnings || []) {
|
|
126
|
+
lines.push(`Warning: ${warning.message}`);
|
|
127
|
+
if (warning.fix)
|
|
128
|
+
lines.push(` Fix: ${warning.fix}`);
|
|
129
|
+
}
|
|
130
|
+
return lines;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* One line naming fields that are still in the JSON but decide nothing any
|
|
134
|
+
* more. Deprecation, not removal: `--json` keeps them for scripts.
|
|
135
|
+
*/
|
|
136
|
+
function retiredFieldsLine(retired, reason) {
|
|
137
|
+
if (!Array.isArray(retired) || !retired.length)
|
|
138
|
+
return null;
|
|
139
|
+
return `Retired fields (no effect): ${retired.join(', ')}${reason ? ` — ${reason}` : ''}`;
|
|
140
|
+
}
|
|
112
141
|
function base(id) {
|
|
113
142
|
return `/api/commitments/${encodeURIComponent(id)}`;
|
|
114
143
|
}
|
|
@@ -1013,6 +1042,11 @@ function describeWakeDecision(check) {
|
|
|
1013
1042
|
if (verdict === 'skipped') {
|
|
1014
1043
|
const reason = typeof entry.reason === 'string' ? entry.reason : '';
|
|
1015
1044
|
if (reason === 'posture_does_not_admit_agent_run') {
|
|
1045
|
+
// The server names the commonest cause on the check's `stop`: nothing
|
|
1046
|
+
// was open to act on. "record_only" alone read as a setting to change
|
|
1047
|
+
// when the remedy was to give the Commitment some work (OSK-12090).
|
|
1048
|
+
if (check.stop?.reason === 'no_open_loop')
|
|
1049
|
+
return 'no — nothing open';
|
|
1016
1050
|
const posture = typeof entry.posture === 'string' ? entry.posture : '';
|
|
1017
1051
|
return posture ? `no — ${posture}` : 'no — posture';
|
|
1018
1052
|
}
|
|
@@ -138,6 +138,12 @@ export interface DaemonBrokerFailure {
|
|
|
138
138
|
* the daemon".
|
|
139
139
|
*/
|
|
140
140
|
daemonServerUrl?: string;
|
|
141
|
+
/**
|
|
142
|
+
* For `base_url_mismatch` found locally: the descriptor file that named
|
|
143
|
+
* `daemonServerUrl`, so a message can say what was read rather than assert
|
|
144
|
+
* where "the" daemon is logged in (OSK-12117).
|
|
145
|
+
*/
|
|
146
|
+
descriptorPath?: string;
|
|
141
147
|
}
|
|
142
148
|
export type DaemonBrokerOutcome = (DaemonBrokerResult & {
|
|
143
149
|
ok: true;
|
|
@@ -224,6 +230,14 @@ export declare function resolveBootstrapCandidatePaths(profile?: string): string
|
|
|
224
230
|
export declare const DEDICATED_RUNTIME_CLI_HANDOFF_DESCRIPTOR = "/run/skrr-dedicated-runtime/cli-handoff/descriptor.json";
|
|
225
231
|
/** Where the cli-handoff broker looks, in order. */
|
|
226
232
|
export declare function resolveCliHandoffCandidatePaths(profile?: string): string[];
|
|
233
|
+
/**
|
|
234
|
+
* The island files that belong to exactly `profile` — its canonical path and
|
|
235
|
+
* the pre-rename darwin location — and never another profile's. The broker's
|
|
236
|
+
* candidate list for `default` deliberately falls through to any running
|
|
237
|
+
* profile, which is right for borrowing a credential and wrong for naming
|
|
238
|
+
* which daemon a profile's status describes (OSK-12102).
|
|
239
|
+
*/
|
|
240
|
+
export declare function resolveExactProfileBootstrapPaths(profile?: string): string[];
|
|
227
241
|
/**
|
|
228
242
|
* Resolve the first live daemon bootstrap for a profile. Message-intent
|
|
229
243
|
* submission reuses the same authenticated loopback discovery as the login
|
package/dist/lib/daemonBroker.js
CHANGED
|
@@ -77,6 +77,7 @@ exports.resolveBootstrapPath = resolveBootstrapPath;
|
|
|
77
77
|
exports.resolveProfileBootstrapPaths = resolveProfileBootstrapPaths;
|
|
78
78
|
exports.resolveBootstrapCandidatePaths = resolveBootstrapCandidatePaths;
|
|
79
79
|
exports.resolveCliHandoffCandidatePaths = resolveCliHandoffCandidatePaths;
|
|
80
|
+
exports.resolveExactProfileBootstrapPaths = resolveExactProfileBootstrapPaths;
|
|
80
81
|
exports.findLiveDaemonBootstrap = findLiveDaemonBootstrap;
|
|
81
82
|
exports.readBootstrap = readBootstrap;
|
|
82
83
|
exports.attemptDaemonBrokerLogin = attemptDaemonBrokerLogin;
|
|
@@ -91,6 +92,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
91
92
|
const path = __importStar(require("node:path"));
|
|
92
93
|
const os = __importStar(require("node:os"));
|
|
93
94
|
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
95
|
+
const loopback_http_1 = require("@skrr-ai/auth-core/loopback-http");
|
|
94
96
|
const cli_handoff_wire_1 = require("@skrr-ai/auth-core/cli-handoff-wire");
|
|
95
97
|
const auth_storage_1 = require("./auth-storage");
|
|
96
98
|
const config_1 = require("./config");
|
|
@@ -139,6 +141,16 @@ function resolveProfileBootstrapPaths(primary, entryNames) {
|
|
|
139
141
|
.map((name) => path.join(path.dirname(primary), name));
|
|
140
142
|
return [primary, ...extras];
|
|
141
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Legacy bootstrap directory (darwin): pre-rename daemons wrote under
|
|
146
|
+
* `~/Library/Application Support/OverSky/` while this reader looked under
|
|
147
|
+
* `skrr/` — a drift that silently killed island bootstrapping on macOS
|
|
148
|
+
* (OSK-12057). New daemons dual-write both; old daemons keep writing only
|
|
149
|
+
* `OverSky/`, so these stay consulted as fallbacks.
|
|
150
|
+
*/
|
|
151
|
+
function legacyDarwinBootstrapDir() {
|
|
152
|
+
return path.join(os.homedir(), 'Library', 'Application Support', 'OverSky');
|
|
153
|
+
}
|
|
142
154
|
/**
|
|
143
155
|
* List the bootstrap files that a Sky CLI may use for a local daemon
|
|
144
156
|
* handoff. `default` stays first for backwards compatibility; any other
|
|
@@ -150,16 +162,31 @@ function resolveProfileBootstrapPaths(primary, entryNames) {
|
|
|
150
162
|
*/
|
|
151
163
|
function resolveBootstrapCandidatePaths(profile = 'default') {
|
|
152
164
|
const primary = resolveBootstrapPath(profile);
|
|
153
|
-
if (profile !== 'default')
|
|
154
|
-
|
|
165
|
+
if (profile !== 'default') {
|
|
166
|
+
const legacy = process.platform === 'darwin'
|
|
167
|
+
? [path.join(legacyDarwinBootstrapDir(), `daemon-island.${profile}.json`)]
|
|
168
|
+
: [];
|
|
169
|
+
return [primary, ...legacy];
|
|
170
|
+
}
|
|
155
171
|
try {
|
|
156
172
|
if (process.platform === 'darwin') {
|
|
157
|
-
const
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
173
|
+
const candidates = [primary];
|
|
174
|
+
for (const dir of [path.dirname(primary), legacyDarwinBootstrapDir()]) {
|
|
175
|
+
let entryNames = [];
|
|
176
|
+
try {
|
|
177
|
+
entryNames = fs
|
|
178
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
179
|
+
.filter((entry) => entry.isFile())
|
|
180
|
+
.map((entry) => entry.name);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
for (const p of resolveProfileBootstrapPaths(path.join(dir, 'daemon-island.default.json'), entryNames)) {
|
|
186
|
+
candidates.push(p);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return [...new Set(candidates)];
|
|
163
190
|
}
|
|
164
191
|
const profilesDir = path.dirname(path.dirname(primary));
|
|
165
192
|
const extras = fs
|
|
@@ -208,6 +235,20 @@ function resolveCliHandoffCandidatePaths(profile = 'default') {
|
|
|
208
235
|
function legacyBootstrapPath() {
|
|
209
236
|
return path.join(os.homedir(), '.skrr', 'daemon-island.json');
|
|
210
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* The island files that belong to exactly `profile` — its canonical path and
|
|
240
|
+
* the pre-rename darwin location — and never another profile's. The broker's
|
|
241
|
+
* candidate list for `default` deliberately falls through to any running
|
|
242
|
+
* profile, which is right for borrowing a credential and wrong for naming
|
|
243
|
+
* which daemon a profile's status describes (OSK-12102).
|
|
244
|
+
*/
|
|
245
|
+
function resolveExactProfileBootstrapPaths(profile = 'default') {
|
|
246
|
+
const primary = resolveBootstrapPath(profile);
|
|
247
|
+
if (process.platform === 'darwin') {
|
|
248
|
+
return [primary, path.join(legacyDarwinBootstrapDir(), `daemon-island.${profile}.json`)];
|
|
249
|
+
}
|
|
250
|
+
return profile === 'default' ? [primary, legacyBootstrapPath()] : [primary];
|
|
251
|
+
}
|
|
211
252
|
/**
|
|
212
253
|
* Resolve the first live daemon bootstrap for a profile. Message-intent
|
|
213
254
|
* submission reuses the same authenticated loopback discovery as the login
|
|
@@ -301,6 +342,7 @@ async function attemptDaemonBrokerLogin(opts) {
|
|
|
301
342
|
const usable = [];
|
|
302
343
|
const unbound = [];
|
|
303
344
|
let mismatchedBootstrap = null;
|
|
345
|
+
let mismatchedPath = null;
|
|
304
346
|
for (const candidate of candidates) {
|
|
305
347
|
const candidateBootstrap = readBootstrap(candidate);
|
|
306
348
|
if (!candidateBootstrap)
|
|
@@ -310,7 +352,10 @@ async function attemptDaemonBrokerLogin(opts) {
|
|
|
310
352
|
typeof opts.baseURL === 'string' &&
|
|
311
353
|
opts.baseURL.length > 0 &&
|
|
312
354
|
normalizeBaseUrl(opts.baseURL) !== normalizeBaseUrl(candidateBootstrap.serverUrl)) {
|
|
313
|
-
mismatchedBootstrap
|
|
355
|
+
if (!mismatchedBootstrap) {
|
|
356
|
+
mismatchedBootstrap = candidateBootstrap;
|
|
357
|
+
mismatchedPath = candidate;
|
|
358
|
+
}
|
|
314
359
|
continue;
|
|
315
360
|
}
|
|
316
361
|
if (typeof candidateBootstrap.serverUrl !== 'string' ||
|
|
@@ -326,8 +371,11 @@ async function attemptDaemonBrokerLogin(opts) {
|
|
|
326
371
|
return {
|
|
327
372
|
ok: false,
|
|
328
373
|
reason: 'base_url_mismatch',
|
|
329
|
-
|
|
374
|
+
// What was READ, not a claim about the daemon: the descriptor may be
|
|
375
|
+
// another profile's (OSK-12117).
|
|
376
|
+
detail: `The daemon descriptor ${mismatchedPath ?? ''} is for ${mismatchedBootstrap.serverUrl}, not ${opts.baseURL}.`,
|
|
330
377
|
daemonServerUrl: mismatchedBootstrap.serverUrl,
|
|
378
|
+
...(mismatchedPath ? { descriptorPath: mismatchedPath } : {}),
|
|
331
379
|
};
|
|
332
380
|
}
|
|
333
381
|
return {
|
|
@@ -415,7 +463,9 @@ async function redeemCliHandoffToken(bootstrap, opts = {}) {
|
|
|
415
463
|
const abortTimer = setTimeout(() => controller.abort(), timeoutMs);
|
|
416
464
|
let response;
|
|
417
465
|
try {
|
|
418
|
-
|
|
466
|
+
// The descriptor secret is a loopback-only credential: never `fetch`, which
|
|
467
|
+
// sends 127.0.0.1 to HTTP_PROXY under Bun and NODE_USE_ENV_PROXY (OSK-12134).
|
|
468
|
+
response = await (0, loopback_http_1.loopbackFetch)(url, {
|
|
419
469
|
method: 'POST',
|
|
420
470
|
headers: {
|
|
421
471
|
Authorization: `Bearer ${bootstrap.secret}`,
|
|
@@ -497,7 +547,9 @@ async function mintRefreshFamilyThrough(bootstrap, opts) {
|
|
|
497
547
|
const abortTimer = setTimeout(() => controller.abort(), timeoutMs);
|
|
498
548
|
let response;
|
|
499
549
|
try {
|
|
500
|
-
|
|
550
|
+
// The descriptor secret is a loopback-only credential: never `fetch`, which
|
|
551
|
+
// sends 127.0.0.1 to HTTP_PROXY under Bun and NODE_USE_ENV_PROXY (OSK-12134).
|
|
552
|
+
response = await (0, loopback_http_1.loopbackFetch)(url, {
|
|
501
553
|
method: 'POST',
|
|
502
554
|
headers: {
|
|
503
555
|
Authorization: `Bearer ${bootstrap.secret}`,
|
|
@@ -49,6 +49,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
49
49
|
const os = __importStar(require("node:os"));
|
|
50
50
|
const path = __importStar(require("node:path"));
|
|
51
51
|
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
52
|
+
const loopback_http_1 = require("@skrr-ai/auth-core/loopback-http");
|
|
52
53
|
function isDelegatedCliSession(env = process.env) {
|
|
53
54
|
return Boolean(env.OVERSKY_AUTONOMOUS_SESSION === '1' &&
|
|
54
55
|
env.OVERSKY_DELEGATED_CLI_BROKER_URL?.trim() &&
|
|
@@ -213,7 +214,9 @@ async function fetchDelegatedCliCredential(env = process.env, options = {}) {
|
|
|
213
214
|
try {
|
|
214
215
|
let res;
|
|
215
216
|
try {
|
|
216
|
-
|
|
217
|
+
// Proxy-free and loopback-only (OSK-12134): the capability and the
|
|
218
|
+
// credential it returns must never reach HTTP_PROXY.
|
|
219
|
+
res = await (0, loopback_http_1.loopbackFetch)(brokerUrl, {
|
|
217
220
|
method: 'POST',
|
|
218
221
|
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
|
219
222
|
body: JSON.stringify({
|
|
@@ -71,7 +71,9 @@ export declare function notInstalledMessage(): string;
|
|
|
71
71
|
* preserving "exit code = the daemon's exit code" semantics that scripts
|
|
72
72
|
* may depend on.
|
|
73
73
|
*/
|
|
74
|
-
export declare function execRuntimeBinary(args: string[]
|
|
74
|
+
export declare function execRuntimeBinary(args: string[], opts?: {
|
|
75
|
+
binary?: string;
|
|
76
|
+
}): Promise<number>;
|
|
75
77
|
/** Output from a short-lived runtime probe such as `skrrd status --json`. */
|
|
76
78
|
export type RuntimeBinaryOutput = {
|
|
77
79
|
code: number;
|
|
@@ -212,9 +212,11 @@ function notInstalledMessage() {
|
|
|
212
212
|
* preserving "exit code = the daemon's exit code" semantics that scripts
|
|
213
213
|
* may depend on.
|
|
214
214
|
*/
|
|
215
|
-
function execRuntimeBinary(args) {
|
|
215
|
+
function execRuntimeBinary(args, opts = {}) {
|
|
216
216
|
return new Promise((resolve, reject) => {
|
|
217
|
-
|
|
217
|
+
// `binary` lets `status` render from the LIVE daemon's program rather than
|
|
218
|
+
// the first one on PATH (OSK-12102); every other verb forwards to PATH.
|
|
219
|
+
const bin = opts.binary ?? findRuntimeBinary();
|
|
218
220
|
if (!bin) {
|
|
219
221
|
reject(new Error('runtime-binary-not-installed'));
|
|
220
222
|
return;
|
|
@@ -259,7 +259,10 @@ async function acquireManagedSession(input = {}, deps = {}) {
|
|
|
259
259
|
sessionToken,
|
|
260
260
|
model: input.model?.trim() || AUTOMATIC_MODEL,
|
|
261
261
|
localRuntimeId: (deps.localRuntimeId ?? localRuntimeId)(),
|
|
262
|
-
|
|
262
|
+
// The hardware id every Daemon row is keyed on — the same function
|
|
263
|
+
// the daemon calls — not the minted `~/.skrr/daemon.id` UUIDv7,
|
|
264
|
+
// so the reservation's attribution joins to this machine (OSK-12063).
|
|
265
|
+
machineUuid: (deps.machineUuid ?? auth_core_1.getMachineUuid)(),
|
|
263
266
|
}, fetchImpl, acquisition.signal);
|
|
264
267
|
}
|
|
265
268
|
catch (err) {
|
package/dist/lib/harnesses.d.ts
CHANGED
|
@@ -64,6 +64,16 @@ export interface Harness {
|
|
|
64
64
|
version?: number;
|
|
65
65
|
claudeEngine?: 'cli' | 'sdk';
|
|
66
66
|
lastSeenAt?: string;
|
|
67
|
+
/** This harness's own stored permission-mode fallback, when set. */
|
|
68
|
+
defaultPermissionMode?: string | null;
|
|
69
|
+
/**
|
|
70
|
+
* The permission modes this harness can honour, and where the answer came
|
|
71
|
+
* from — sent by `GET /api/harnesses/:id` for a local row (OSK-12130).
|
|
72
|
+
*/
|
|
73
|
+
permissionModes?: {
|
|
74
|
+
modes: string[];
|
|
75
|
+
source: 'daemon' | 'daemon_record' | 'static' | 'vocabulary' | string;
|
|
76
|
+
};
|
|
67
77
|
/**
|
|
68
78
|
* Registration metadata. A managed machine's rows carry `machineProduct` and
|
|
69
79
|
* `machineLeaseId`, which is the only link from a lease to the harness rows its
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface LiveProgram {
|
|
2
|
+
/** The executable the OS reports for the live pid. */
|
|
3
|
+
exec: string;
|
|
4
|
+
/** For an interpreter-launched daemon, the script it runs. */
|
|
5
|
+
script: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface LiveRuntimeDeps {
|
|
8
|
+
/** pid of the live daemon for `profile`, or null. */
|
|
9
|
+
livePid(profile: string): number | null;
|
|
10
|
+
/** The live pid's program, or null when the OS will not say. */
|
|
11
|
+
programOf(pid: number): LiveProgram | null;
|
|
12
|
+
realpath(p: string): string;
|
|
13
|
+
isExecutable(p: string): boolean;
|
|
14
|
+
}
|
|
15
|
+
export type StatusBinaryDecision = {
|
|
16
|
+
kind: 'same';
|
|
17
|
+
binary: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'unknown';
|
|
20
|
+
binary: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'forward-live';
|
|
23
|
+
binary: string;
|
|
24
|
+
pathBinary: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'mismatch';
|
|
27
|
+
binary: string;
|
|
28
|
+
live: string;
|
|
29
|
+
};
|
|
30
|
+
/** The profile a forwarded argv names, `default` otherwise. */
|
|
31
|
+
export declare function profileFromArgs(args: readonly string[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Decide which binary renders `status`. Never throws: a probe that cannot
|
|
34
|
+
* answer leaves the PATH binary in place (`unknown`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function decideStatusBinary(pathBinary: string, profile: string, deps: LiveRuntimeDeps): StatusBinaryDecision;
|
|
37
|
+
/** One stderr line naming the binary that rendered status, when it is not obvious. */
|
|
38
|
+
export declare function describeStatusBinary(decision: StatusBinaryDecision): string | null;
|
|
39
|
+
export declare function scriptFromArgs(exec: string, args: string): string | null;
|
|
40
|
+
export declare function defaultLiveRuntimeDeps(): LiveRuntimeDeps;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.profileFromArgs = profileFromArgs;
|
|
7
|
+
exports.decideStatusBinary = decideStatusBinary;
|
|
8
|
+
exports.describeStatusBinary = describeStatusBinary;
|
|
9
|
+
exports.scriptFromArgs = scriptFromArgs;
|
|
10
|
+
exports.defaultLiveRuntimeDeps = defaultLiveRuntimeDeps;
|
|
11
|
+
/**
|
|
12
|
+
* Which runtime binary is the LIVE daemon running, and is it the one
|
|
13
|
+
* `skrr daemon status` is about to forward to? (OSK-12102)
|
|
14
|
+
*
|
|
15
|
+
* `execRuntimeBinary` forwards to the first `skrrd` on PATH. That is right for
|
|
16
|
+
* lifecycle verbs, where PATH order is the person's choice of install. It is
|
|
17
|
+
* wrong for `status`, whose whole subject is the daemon that is running: with
|
|
18
|
+
* an old dev build early on PATH and the release daemon live, the header named
|
|
19
|
+
* `.../releases/0.8.62/skrrd` while the body was rendered by the dev build —
|
|
20
|
+
* its old layout, no per-category permission table — and nothing on screen
|
|
21
|
+
* said two binaries were involved.
|
|
22
|
+
*
|
|
23
|
+
* The live daemon's pid comes from its island bootstrap file (the same
|
|
24
|
+
* discovery the CLI's login broker uses); the program from the OS. When the
|
|
25
|
+
* live program is itself a runtime executable, status is forwarded to it.
|
|
26
|
+
* When it cannot be exec'd directly (a `node .../dist/index.js` dev daemon),
|
|
27
|
+
* status stays on the PATH binary and says so.
|
|
28
|
+
*/
|
|
29
|
+
const node_child_process_1 = require("node:child_process");
|
|
30
|
+
const node_fs_1 = require("node:fs");
|
|
31
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
32
|
+
const daemonBroker_1 = require("./daemonBroker");
|
|
33
|
+
const exec_runtime_binary_1 = require("./exec-runtime-binary");
|
|
34
|
+
function safeRealpath(deps, p) {
|
|
35
|
+
try {
|
|
36
|
+
return deps.realpath(p);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return p;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isRuntimeName(p) {
|
|
43
|
+
const base = node_path_1.default
|
|
44
|
+
.basename(p)
|
|
45
|
+
.toLowerCase()
|
|
46
|
+
.replace(/\.(exe|cmd)$/, '');
|
|
47
|
+
return exec_runtime_binary_1.RUNTIME_BINARY_NAMES.some((name) => base === name || base.startsWith(`${name}-`));
|
|
48
|
+
}
|
|
49
|
+
/** The profile a forwarded argv names, `default` otherwise. */
|
|
50
|
+
function profileFromArgs(args) {
|
|
51
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
52
|
+
const arg = args[i];
|
|
53
|
+
if (arg === '--')
|
|
54
|
+
break;
|
|
55
|
+
if (arg === '--profile' && args[i + 1] && !args[i + 1].startsWith('-'))
|
|
56
|
+
return args[i + 1];
|
|
57
|
+
if (arg.startsWith('--profile=') && arg.length > '--profile='.length) {
|
|
58
|
+
return arg.slice('--profile='.length);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return 'default';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Decide which binary renders `status`. Never throws: a probe that cannot
|
|
65
|
+
* answer leaves the PATH binary in place (`unknown`).
|
|
66
|
+
*/
|
|
67
|
+
function decideStatusBinary(pathBinary, profile, deps) {
|
|
68
|
+
let program = null;
|
|
69
|
+
try {
|
|
70
|
+
const pid = deps.livePid(profile);
|
|
71
|
+
program = pid ? deps.programOf(pid) : null;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
program = null;
|
|
75
|
+
}
|
|
76
|
+
if (!program)
|
|
77
|
+
return { kind: 'unknown', binary: pathBinary };
|
|
78
|
+
const pathReal = safeRealpath(deps, pathBinary);
|
|
79
|
+
const execReal = safeRealpath(deps, program.exec);
|
|
80
|
+
const scriptReal = program.script ? safeRealpath(deps, program.script) : null;
|
|
81
|
+
if (pathReal === execReal || (scriptReal !== null && pathReal === scriptReal)) {
|
|
82
|
+
return { kind: 'same', binary: pathBinary };
|
|
83
|
+
}
|
|
84
|
+
// Only a runtime executable is forwarded to. A `node`/Electron-hosted daemon
|
|
85
|
+
// has an interpreter as its exec, and running the interpreter with status
|
|
86
|
+
// argv would be nonsense.
|
|
87
|
+
const directlyRunnable = program.script === null &&
|
|
88
|
+
(isRuntimeName(program.exec) || isRuntimeName(execReal)) &&
|
|
89
|
+
deps.isExecutable(program.exec);
|
|
90
|
+
if (directlyRunnable) {
|
|
91
|
+
return { kind: 'forward-live', binary: program.exec, pathBinary };
|
|
92
|
+
}
|
|
93
|
+
return { kind: 'mismatch', binary: pathBinary, live: program.script ?? program.exec };
|
|
94
|
+
}
|
|
95
|
+
/** One stderr line naming the binary that rendered status, when it is not obvious. */
|
|
96
|
+
function describeStatusBinary(decision) {
|
|
97
|
+
switch (decision.kind) {
|
|
98
|
+
case 'forward-live':
|
|
99
|
+
return (`Rendered by the live daemon's binary ${decision.binary} ` +
|
|
100
|
+
`(the first skrrd on PATH is ${decision.pathBinary}, a different build).`);
|
|
101
|
+
case 'mismatch':
|
|
102
|
+
return (`Rendered by ${decision.binary}, the first skrrd on PATH — NOT the live daemon's ` +
|
|
103
|
+
`program (${decision.live}). This layout and these checks are that build's, not the live one's.`);
|
|
104
|
+
default:
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function darwinProgramOf(pid) {
|
|
109
|
+
const out = (args) => (0, node_child_process_1.execFileSync)('ps', ['-p', String(pid), '-o', ...args], {
|
|
110
|
+
encoding: 'utf8',
|
|
111
|
+
timeout: 2_000,
|
|
112
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
113
|
+
}).trim();
|
|
114
|
+
const exec = out(['comm=']);
|
|
115
|
+
if (!exec || !node_path_1.default.isAbsolute(exec))
|
|
116
|
+
return null;
|
|
117
|
+
return { exec, script: scriptFromArgs(exec, out(['args='])) };
|
|
118
|
+
}
|
|
119
|
+
function linuxProgramOf(pid) {
|
|
120
|
+
const exec = (0, node_fs_1.readlinkSync)(`/proc/${pid}/exe`);
|
|
121
|
+
let script = null;
|
|
122
|
+
try {
|
|
123
|
+
const cmdline = (0, node_fs_1.readFileSync)(`/proc/${pid}/cmdline`, 'utf8');
|
|
124
|
+
script = scriptFromArgs(exec, cmdline.split('\0').filter(Boolean).join(' '));
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
script = null;
|
|
128
|
+
}
|
|
129
|
+
return { exec, script };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* For an interpreter-hosted daemon (`node --import x.mjs /x/dist/index.js
|
|
133
|
+
* start …`), the script: the first argument after the exec that is neither an
|
|
134
|
+
* option nor the value of a module-loading option. `ps -o args=` is
|
|
135
|
+
* space-joined, so a path containing a space is not recovered — the result is
|
|
136
|
+
* only ever used for display and an equality check, where a miss degrades to
|
|
137
|
+
* the "mismatch" note rather than to a wrong forward.
|
|
138
|
+
*/
|
|
139
|
+
const INTERPRETER_VALUE_OPTIONS = new Set([
|
|
140
|
+
'-r',
|
|
141
|
+
'--require',
|
|
142
|
+
'--import',
|
|
143
|
+
'--loader',
|
|
144
|
+
'--experimental-loader',
|
|
145
|
+
'-e',
|
|
146
|
+
'--eval',
|
|
147
|
+
]);
|
|
148
|
+
function scriptFromArgs(exec, args) {
|
|
149
|
+
if (isRuntimeName(exec))
|
|
150
|
+
return null;
|
|
151
|
+
const rest = args.startsWith(exec) ? args.slice(exec.length) : args.replace(/^\S+/, '');
|
|
152
|
+
const tokens = rest.split(/\s+/).filter(Boolean);
|
|
153
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
154
|
+
const token = tokens[i];
|
|
155
|
+
if (INTERPRETER_VALUE_OPTIONS.has(token)) {
|
|
156
|
+
i += 1;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (token.startsWith('-'))
|
|
160
|
+
continue;
|
|
161
|
+
return token;
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
function defaultLiveRuntimeDeps() {
|
|
166
|
+
return {
|
|
167
|
+
livePid(profile) {
|
|
168
|
+
for (const candidate of (0, daemonBroker_1.resolveExactProfileBootstrapPaths)(profile)) {
|
|
169
|
+
const bootstrap = (0, daemonBroker_1.readBootstrap)(candidate);
|
|
170
|
+
if (typeof bootstrap?.pid === 'number' && bootstrap.pid > 0)
|
|
171
|
+
return bootstrap.pid;
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
},
|
|
175
|
+
programOf(pid) {
|
|
176
|
+
if (process.platform === 'darwin')
|
|
177
|
+
return darwinProgramOf(pid);
|
|
178
|
+
if (process.platform === 'linux')
|
|
179
|
+
return linuxProgramOf(pid);
|
|
180
|
+
return null;
|
|
181
|
+
},
|
|
182
|
+
realpath: (p) => (0, node_fs_1.realpathSync)(p),
|
|
183
|
+
isExecutable(p) {
|
|
184
|
+
try {
|
|
185
|
+
(0, node_fs_1.accessSync)(p, node_fs_1.constants.X_OK);
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|