@skrr-ai/cli 0.1.47 → 0.1.49
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/README.md +1 -1
- package/dist/base-command.d.ts +18 -0
- package/dist/base-command.js +61 -1
- package/dist/commands/agent-worker.d.ts +12 -0
- package/dist/commands/agent-worker.js +140 -0
- package/dist/commands/agents/chat.d.ts +21 -0
- package/dist/commands/agents/chat.js +26 -9
- package/dist/commands/balance/usage/breakdown.d.ts +14 -0
- package/dist/commands/balance/usage/breakdown.js +68 -0
- package/dist/commands/balance/usage.js +24 -0
- package/dist/commands/commerce/entitlements/explain.d.ts +22 -0
- package/dist/commands/commerce/entitlements/explain.js +40 -0
- package/dist/commands/commerce/incidents/audit.d.ts +20 -0
- package/dist/commands/commerce/incidents/audit.js +37 -0
- package/dist/commands/commerce/incidents/list.d.ts +22 -0
- package/dist/commands/commerce/incidents/list.js +49 -0
- package/dist/commands/commerce/incidents/resolve.d.ts +23 -0
- package/dist/commands/commerce/incidents/resolve.js +45 -0
- package/dist/commands/commerce/incidents/retry.d.ts +22 -0
- package/dist/commands/commerce/incidents/retry.js +45 -0
- package/dist/commands/commerce/incidents/show.d.ts +13 -0
- package/dist/commands/commerce/incidents/show.js +30 -0
- package/dist/commands/commerce/offers/approve.d.ts +17 -0
- package/dist/commands/commerce/offers/approve.js +33 -0
- package/dist/commands/commerce/offers/create.d.ts +18 -0
- package/dist/commands/commerce/offers/create.js +34 -0
- package/dist/commands/commerce/offers/publish.d.ts +13 -0
- package/dist/commands/commerce/offers/publish.js +28 -0
- package/dist/commands/commerce/offers/retire.d.ts +17 -0
- package/dist/commands/commerce/offers/retire.js +32 -0
- package/dist/commands/commerce/offers/validate.d.ts +18 -0
- package/dist/commands/commerce/offers/validate.js +33 -0
- package/dist/commands/commerce/products/create.d.ts +10 -0
- package/dist/commands/commerce/products/create.js +25 -0
- package/dist/commands/commerce/promotions/redeem.d.ts +13 -0
- package/dist/commands/commerce/promotions/redeem.js +32 -0
- package/dist/commands/commerce/terms/accept.d.ts +18 -0
- package/dist/commands/commerce/terms/accept.js +39 -0
- package/dist/commands/commerce/terms/show.d.ts +10 -0
- package/dist/commands/commerce/terms/show.js +34 -0
- package/dist/commands/commerce/trials/conversion-preview.d.ts +18 -0
- package/dist/commands/commerce/trials/conversion-preview.js +39 -0
- package/dist/commands/commerce/trials/start.d.ts +23 -0
- package/dist/commands/commerce/trials/start.js +58 -0
- package/dist/commands/commitments/accounting.d.ts +39 -0
- package/dist/commands/commitments/accounting.js +116 -0
- package/dist/commands/commitments/action-history.d.ts +1 -0
- package/dist/commands/commitments/action-history.js +8 -1
- package/dist/commands/commitments/case.d.ts +1 -0
- package/dist/commands/commitments/case.js +19 -3
- package/dist/commands/commitments/cases.d.ts +1 -0
- package/dist/commands/commitments/cases.js +11 -1
- package/dist/commands/commitments/checks.d.ts +1 -0
- package/dist/commands/commitments/checks.js +5 -1
- package/dist/commands/commitments/cost.d.ts +62 -0
- package/dist/commands/commitments/cost.js +130 -0
- package/dist/commands/commitments/create.js +1 -1
- package/dist/commands/commitments/delete.d.ts +1 -0
- package/dist/commands/commitments/delete.js +56 -6
- package/dist/commands/commitments/feedback.js +9 -1
- package/dist/commands/commitments/handover.js +16 -0
- package/dist/commands/commitments/hypotheses.d.ts +1 -0
- package/dist/commands/commitments/hypotheses.js +17 -2
- package/dist/commands/commitments/links/list.js +4 -1
- package/dist/commands/commitments/liveness.d.ts +18 -0
- package/dist/commands/commitments/liveness.js +80 -0
- package/dist/commands/commitments/metrics.d.ts +1 -0
- package/dist/commands/commitments/metrics.js +8 -1
- package/dist/commands/commitments/next-tick.d.ts +39 -0
- package/dist/commands/commitments/next-tick.js +122 -0
- package/dist/commands/commitments/observations.d.ts +1 -0
- package/dist/commands/commitments/observations.js +19 -2
- package/dist/commands/commitments/pause.js +12 -0
- package/dist/commands/commitments/receipt.d.ts +2 -0
- package/dist/commands/commitments/receipt.js +16 -2
- package/dist/commands/commitments/remediation-proposal.js +6 -2
- package/dist/commands/commitments/remediation-proposals.js +5 -1
- package/dist/commands/commitments/restore.d.ts +25 -0
- package/dist/commands/commitments/restore.js +46 -0
- package/dist/commands/commitments/show.js +32 -0
- package/dist/commands/commitments/trigger-status.js +33 -0
- package/dist/commands/commitments/update.d.ts +1 -0
- package/dist/commands/commitments/update.js +31 -5
- package/dist/commands/commitments/wake-capabilities.d.ts +0 -1
- package/dist/commands/commitments/wake-capabilities.js +8 -4
- package/dist/commands/enterprise/budgets/create.d.ts +11 -0
- package/dist/commands/enterprise/budgets/create.js +27 -0
- package/dist/commands/enterprise/budgets/evaluate.d.ts +17 -0
- package/dist/commands/enterprise/budgets/evaluate.js +32 -0
- package/dist/commands/enterprise/budgets/publish.d.ts +14 -0
- package/dist/commands/enterprise/budgets/publish.js +30 -0
- package/dist/commands/enterprise/contracts/activate.d.ts +14 -0
- package/dist/commands/enterprise/contracts/activate.js +30 -0
- package/dist/commands/enterprise/contracts/create.d.ts +14 -0
- package/dist/commands/enterprise/contracts/create.js +32 -0
- package/dist/commands/enterprise/contracts/issue.d.ts +18 -0
- package/dist/commands/enterprise/contracts/issue.js +34 -0
- package/dist/commands/enterprise/domains/begin.d.ts +20 -0
- package/dist/commands/enterprise/domains/begin.js +39 -0
- package/dist/commands/enterprise/domains/verify.d.ts +14 -0
- package/dist/commands/enterprise/domains/verify.js +32 -0
- package/dist/commands/enterprise/external-config/activate.d.ts +22 -0
- package/dist/commands/enterprise/external-config/activate.js +49 -0
- package/dist/commands/enterprise/external-config/set.d.ts +25 -0
- package/dist/commands/enterprise/external-config/set.js +123 -0
- package/dist/commands/enterprise/external-config/show.d.ts +12 -0
- package/dist/commands/enterprise/external-config/show.js +39 -0
- package/dist/commands/enterprise/external-config/suspend.d.ts +13 -0
- package/dist/commands/enterprise/external-config/suspend.js +41 -0
- package/dist/commands/enterprise/finance/close-snapshot.d.ts +11 -0
- package/dist/commands/enterprise/finance/close-snapshot.js +28 -0
- package/dist/commands/enterprise/finance/record-document.d.ts +18 -0
- package/dist/commands/enterprise/finance/record-document.js +35 -0
- package/dist/commands/enterprise/profile.d.ts +20 -0
- package/dist/commands/enterprise/profile.js +38 -0
- package/dist/commands/login.d.ts +13 -0
- package/dist/commands/login.js +77 -0
- package/dist/commands/machines/dedicated/index.js +3 -0
- package/dist/commands/machines/dedicated/service/apply.d.ts +23 -0
- package/dist/commands/machines/dedicated/service/apply.js +99 -0
- package/dist/commands/machines/dedicated/service/approve.d.ts +23 -0
- package/dist/commands/machines/dedicated/service/approve.js +52 -0
- package/dist/commands/machines/dedicated/service/create.d.ts +55 -0
- package/dist/commands/machines/dedicated/service/create.js +222 -0
- package/dist/commands/machines/dedicated/service/edit.d.ts +30 -0
- package/dist/commands/machines/dedicated/service/edit.js +146 -0
- package/dist/commands/machines/dedicated/service/exec.d.ts +26 -0
- package/dist/commands/machines/dedicated/service/exec.js +92 -0
- package/dist/commands/machines/dedicated/service/export.d.ts +29 -0
- package/dist/commands/machines/dedicated/service/export.js +106 -0
- package/dist/commands/machines/dedicated/service/index.d.ts +14 -0
- package/dist/commands/machines/dedicated/service/index.js +49 -0
- package/dist/commands/machines/dedicated/service/logs.d.ts +33 -0
- package/dist/commands/machines/dedicated/service/logs.js +148 -0
- package/dist/commands/machines/dedicated/service/ls.d.ts +20 -0
- package/dist/commands/machines/dedicated/service/ls.js +80 -0
- package/dist/commands/machines/dedicated/service/restart.d.ts +14 -0
- package/dist/commands/machines/dedicated/service/restart.js +29 -0
- package/dist/commands/machines/dedicated/service/rm.d.ts +20 -0
- package/dist/commands/machines/dedicated/service/rm.js +33 -0
- package/dist/commands/machines/dedicated/service/secret/index.d.ts +14 -0
- package/dist/commands/machines/dedicated/service/secret/index.js +25 -0
- package/dist/commands/machines/dedicated/service/secret/rm.d.ts +22 -0
- package/dist/commands/machines/dedicated/service/secret/rm.js +54 -0
- package/dist/commands/machines/dedicated/service/secret/set.d.ts +22 -0
- package/dist/commands/machines/dedicated/service/secret/set.js +93 -0
- package/dist/commands/machines/dedicated/service/start.d.ts +14 -0
- package/dist/commands/machines/dedicated/service/start.js +29 -0
- package/dist/commands/machines/dedicated/service/status.d.ts +21 -0
- package/dist/commands/machines/dedicated/service/status.js +85 -0
- package/dist/commands/machines/dedicated/service/stop.d.ts +20 -0
- package/dist/commands/machines/dedicated/service/stop.js +35 -0
- package/dist/commands/machines/dedicated/service/top.d.ts +22 -0
- package/dist/commands/machines/dedicated/service/top.js +120 -0
- package/dist/commands/machines/dedicated/sign-in-status.d.ts +22 -0
- package/dist/commands/machines/dedicated/sign-in-status.js +79 -0
- package/dist/commands/machines/dedicated/ssh-config.d.ts +28 -0
- package/dist/commands/machines/dedicated/ssh-config.js +66 -0
- package/dist/commands/machines/dedicated/ssh-proxy.d.ts +22 -0
- package/dist/commands/machines/dedicated/ssh-proxy.js +62 -0
- package/dist/commands/machines/dedicated/ssh.d.ts +29 -0
- package/dist/commands/machines/dedicated/ssh.js +121 -0
- package/dist/commands/native/allow-all.d.ts +14 -0
- package/dist/commands/native/allow-all.js +25 -0
- package/dist/commands/native/allow.d.ts +24 -0
- package/dist/commands/native/allow.js +45 -0
- package/dist/commands/native/deny.d.ts +24 -0
- package/dist/commands/native/deny.js +43 -0
- package/dist/commands/native/disable.d.ts +17 -0
- package/dist/commands/native/disable.js +28 -0
- package/dist/commands/native/enable.d.ts +12 -0
- package/dist/commands/native/enable.js +29 -0
- package/dist/commands/native/list-apps.d.ts +19 -0
- package/dist/commands/native/list-apps.js +30 -0
- package/dist/commands/native/restrict-to.d.ts +22 -0
- package/dist/commands/native/restrict-to.js +41 -0
- package/dist/commands/native/status.d.ts +19 -0
- package/dist/commands/native/status.js +33 -0
- package/dist/commands/native.d.ts +39 -0
- package/dist/commands/native.js +76 -0
- package/dist/commands/service/index.d.ts +14 -0
- package/dist/commands/service/index.js +31 -0
- package/dist/commands/service/logs.d.ts +18 -0
- package/dist/commands/service/logs.js +53 -0
- package/dist/commands/service/ls.d.ts +13 -0
- package/dist/commands/service/ls.js +48 -0
- package/dist/commands/service/propose.d.ts +34 -0
- package/dist/commands/service/propose.js +113 -0
- package/dist/commands/service/status.d.ts +17 -0
- package/dist/commands/service/status.js +56 -0
- package/dist/commands/spaces/auto-executor/runs.d.ts +13 -0
- package/dist/commands/spaces/auto-executor/runs.js +56 -0
- package/dist/commands/store/governance/artifacts.d.ts +25 -0
- package/dist/commands/store/governance/artifacts.js +55 -0
- package/dist/commands/store/governance/assign.d.ts +16 -0
- package/dist/commands/store/governance/assign.js +54 -0
- package/dist/commands/store/governance/create-license.d.ts +18 -0
- package/dist/commands/store/governance/create-license.js +35 -0
- package/dist/commands/store/governance/install-plan.d.ts +25 -0
- package/dist/commands/store/governance/install-plan.js +56 -0
- package/dist/commands/store/governance/license-policy.d.ts +30 -0
- package/dist/commands/store/governance/license-policy.js +69 -0
- package/dist/commands/store/governance/policy.d.ts +25 -0
- package/dist/commands/store/governance/policy.js +65 -0
- package/dist/commands/store/governance/publish-release.d.ts +17 -0
- package/dist/commands/store/governance/publish-release.js +34 -0
- package/dist/commands/tasks/deliverable/add.d.ts +15 -0
- package/dist/commands/tasks/deliverable/add.js +174 -0
- package/dist/commands/tasks/deliverable/archive.d.ts +35 -0
- package/dist/commands/tasks/deliverable/archive.js +205 -0
- package/dist/commands/tasks/labels/detach.js +3 -0
- package/dist/commands/tasks/labels/suggest.d.ts +24 -0
- package/dist/commands/tasks/labels/suggest.js +69 -0
- package/dist/commands/tasks/list.d.ts +16 -2
- package/dist/commands/tasks/list.js +100 -24
- package/dist/commands/tasks/show.d.ts +23 -0
- package/dist/commands/tasks/show.js +51 -1
- package/dist/commands/wiki/rm.d.ts +22 -1
- package/dist/commands/wiki/rm.js +52 -3
- package/dist/lib/agentic-stream.js +10 -2
- package/dist/lib/balance.d.ts +6 -1
- package/dist/lib/balance.js +15 -0
- package/dist/lib/commerce-command.d.ts +48 -0
- package/dist/lib/commerce-command.js +70 -0
- package/dist/lib/commerce.d.ts +93 -0
- package/dist/lib/commerce.js +129 -0
- package/dist/lib/commitment-product.js +1 -1
- package/dist/lib/commitments.d.ts +202 -29
- package/dist/lib/commitments.js +300 -33
- package/dist/lib/daemon-installer.d.ts +6 -5
- package/dist/lib/daemon-installer.js +4 -17
- package/dist/lib/dedicated-lease-command.js +10 -0
- package/dist/lib/dedicated-machines.d.ts +37 -0
- package/dist/lib/dedicated-machines.js +47 -0
- package/dist/lib/dedicated-service-command.d.ts +60 -0
- package/dist/lib/dedicated-service-command.js +182 -0
- package/dist/lib/dedicated-service.d.ts +342 -0
- package/dist/lib/dedicated-service.js +741 -0
- package/dist/lib/dedicated-ssh.d.ts +136 -0
- package/dist/lib/dedicated-ssh.js +387 -0
- package/dist/lib/delegated-cli.js +51 -13
- package/dist/lib/enterprise-commerce.d.ts +67 -0
- package/dist/lib/enterprise-commerce.js +112 -0
- package/dist/lib/enterprise-external-configuration.d.ts +60 -0
- package/dist/lib/enterprise-external-configuration.js +58 -0
- package/dist/lib/first-party-harness.js +17 -3
- package/dist/lib/governed-store.d.ts +110 -0
- package/dist/lib/governed-store.js +79 -0
- package/dist/lib/guest-service-command.d.ts +16 -0
- package/dist/lib/guest-service-command.js +32 -0
- package/dist/lib/guest-service.d.ts +67 -0
- package/dist/lib/guest-service.js +112 -0
- package/dist/lib/prompt.d.ts +1 -0
- package/dist/lib/prompt.js +1 -0
- package/dist/lib/task-asset-upload.d.ts +20 -0
- package/dist/lib/task-asset-upload.js +30 -8
- package/dist/lib/task-extras.d.ts +23 -0
- package/dist/lib/task-extras.js +6 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.d.ts +9 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.js +10 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +8 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +16 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +21 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseManifest.d.ts +38 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseManifest.js +66 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +24 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.d.ts +9 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.js +10 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +16 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +20 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseManifest.d.ts +38 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseManifest.js +64 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +24 -2
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5060 -4827
- package/oclif.manifest.json +35194 -29157
- package/package.json +43 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEDICATED_FILE_MAX_BYTES = exports.DEDICATED_FILE_CHUNK_BYTES = exports.DEDICATED_EXEC_DEFAULT_TIMEOUT_MS = exports.DEDICATED_EXEC_MAX_TIMEOUT_MS = exports.DEDICATED_MACHINE_PRODUCT = exports.DEDICATED_LEASE_ACTIONS = void 0;
|
|
4
|
+
exports.describeDedicatedCheckpoint = describeDedicatedCheckpoint;
|
|
4
5
|
exports.describeDedicatedImageStanding = describeDedicatedImageStanding;
|
|
5
6
|
exports.dedicatedRuntimeCreateInput = dedicatedRuntimeCreateInput;
|
|
6
7
|
exports.isDedicatedRepositoryRef = isDedicatedRepositoryRef;
|
|
@@ -16,6 +17,7 @@ exports.setDedicatedRuntimeSpendingLimit = setDedicatedRuntimeSpendingLimit;
|
|
|
16
17
|
exports.closeDedicatedRuntimeIncidentHold = closeDedicatedRuntimeIncidentHold;
|
|
17
18
|
exports.destroyDedicatedRuntime = destroyDedicatedRuntime;
|
|
18
19
|
exports.execDedicatedRuntime = execDedicatedRuntime;
|
|
20
|
+
exports.getDedicatedRuntimeSignInStatus = getDedicatedRuntimeSignInStatus;
|
|
19
21
|
exports.startDedicatedRuntimeExecution = startDedicatedRuntimeExecution;
|
|
20
22
|
exports.observeDedicatedRuntimeExecution = observeDedicatedRuntimeExecution;
|
|
21
23
|
exports.readDedicatedRuntimeFileChunk = readDedicatedRuntimeFileChunk;
|
|
@@ -46,6 +48,7 @@ exports.dedicatedRuntimeApiErrorCode = dedicatedRuntimeApiErrorCode;
|
|
|
46
48
|
exports.dedicatedRuntimeApiErrorDetails = dedicatedRuntimeApiErrorDetails;
|
|
47
49
|
exports.formatDedicatedRuntimeApiError = formatDedicatedRuntimeApiError;
|
|
48
50
|
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
51
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
49
52
|
const api_fetch_1 = require("./api-fetch");
|
|
50
53
|
const edge_error_page_1 = require("./edge-error-page");
|
|
51
54
|
const harnesses_1 = require("./harnesses");
|
|
@@ -58,6 +61,17 @@ exports.DEDICATED_LEASE_ACTIONS = [
|
|
|
58
61
|
'health-check',
|
|
59
62
|
];
|
|
60
63
|
exports.DEDICATED_MACHINE_PRODUCT = 'dedicated-machine';
|
|
64
|
+
/**
|
|
65
|
+
* What an operation's guest checkpoint says, or null when the lease records
|
|
66
|
+
* none. One line, because the copy — and the judgement that this is a plain
|
|
67
|
+
* fact and not a warning — lives once in `@skrr-ai/data-provider`.
|
|
68
|
+
*/
|
|
69
|
+
function describeDedicatedCheckpoint(lease) {
|
|
70
|
+
const operation = lease?.operation;
|
|
71
|
+
if (!operation)
|
|
72
|
+
return null;
|
|
73
|
+
return (0, data_provider_1.describeMachineCheckpointOutcome)(operation.checkpoint, { action: operation.action });
|
|
74
|
+
}
|
|
61
75
|
/** One line saying where a machine's image stands and what the owner can do. */
|
|
62
76
|
function describeDedicatedImageStanding(image, leaseId) {
|
|
63
77
|
const last = image.lastUpdate;
|
|
@@ -304,6 +318,22 @@ async function execDedicatedRuntime(leaseId, input, scope = {}) {
|
|
|
304
318
|
},
|
|
305
319
|
});
|
|
306
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* `GET /api/machines/dedicated/:leaseId/sign-in-status` — is this machine
|
|
323
|
+
* signed in to gh, Claude Code and Codex?
|
|
324
|
+
*
|
|
325
|
+
* Its own endpoint rather than a caller of `exec`, for the reason recorded
|
|
326
|
+
* beside the route: before it, the only way to find out was to START a sign-in
|
|
327
|
+
* against a credential that was already fine (OSK-10795). Read-only on the
|
|
328
|
+
* guest — three `… status` subcommands, no writes, no tokens read back.
|
|
329
|
+
*
|
|
330
|
+
* The vocabulary (`DedicatedRuntimeSignInStatus`, its states, the probe and its
|
|
331
|
+
* parser) is OWNED by `@skrr-ai/data-provider` and re-exported here. A second
|
|
332
|
+
* declaration is how a surface drifts from the server that answers it.
|
|
333
|
+
*/
|
|
334
|
+
async function getDedicatedRuntimeSignInStatus(leaseId, scope = {}) {
|
|
335
|
+
return (0, api_fetch_1.apiFetch)(withDedicatedScope(`/api/machines/dedicated/${encodeURIComponent(leaseId)}/sign-in-status`, scope));
|
|
336
|
+
}
|
|
307
337
|
/**
|
|
308
338
|
* Start one command. `requestId` is the idempotency key: the same id, for the
|
|
309
339
|
* same command on the same lease, returns the execution it already started —
|
|
@@ -586,6 +616,23 @@ function describeDedicatedLease(lease, harnesses = []) {
|
|
|
586
616
|
if (hold?.status === 'open') {
|
|
587
617
|
row('incident', `hold open since ${hold.heldAt || '?'} — the failed source volume is billed until \`incident-close\``);
|
|
588
618
|
}
|
|
619
|
+
// The lease's last (or current) operation, and — the reason this row exists —
|
|
620
|
+
// whether the machine saved its workspace for it. A stop that paused the work
|
|
621
|
+
// first and a stop that gave up waiting are different facts about whether the
|
|
622
|
+
// owner's last writes landed, and until OSK-11023 the server recorded the
|
|
623
|
+
// difference and no surface printed it. Dated, because on a machine that has
|
|
624
|
+
// since started again the sentence is about a past operation.
|
|
625
|
+
const operation = lease.operation;
|
|
626
|
+
if (operation?.action || operation?.status) {
|
|
627
|
+
const settledAt = operation.completedAt || operation.startedAt;
|
|
628
|
+
// The payload's own spelling, minus the underscore: this row is read by a
|
|
629
|
+
// person, and `in_progress` beside a plain English sentence reads as a code.
|
|
630
|
+
const status = operation.status === 'in_progress' ? 'in progress' : operation.status;
|
|
631
|
+
row('operation', [operation.action, status, settledAt].filter(Boolean).join(' '));
|
|
632
|
+
const checkpoint = describeDedicatedCheckpoint(lease);
|
|
633
|
+
if (checkpoint)
|
|
634
|
+
lines.push(` ${''.padEnd(13)}${checkpoint.sentence}`);
|
|
635
|
+
}
|
|
589
636
|
const engines = dedicatedLeaseHarnesses(lease, harnesses);
|
|
590
637
|
if (engines.length > 0) {
|
|
591
638
|
row('engines', engines.map((harness) => `${harness.provider} (${harness.status || 'unknown'})`).join(', '));
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { DedicatedLeaseCommand } from './dedicated-lease-command';
|
|
2
|
+
import { DedicatedServiceChannel, type ServiceVerb } from './dedicated-service';
|
|
3
|
+
/**
|
|
4
|
+
* The flag set `service create`/`apply` and guest `service propose` share —
|
|
5
|
+
* one definition so the three surfaces cannot drift apart on what a spec
|
|
6
|
+
* accepts. `--file` and the argv tail remain per-command because their
|
|
7
|
+
* mutual-exclusion rules differ.
|
|
8
|
+
*/
|
|
9
|
+
export declare const serviceSpecFlags: {
|
|
10
|
+
name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
cwd: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
env: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
restart: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
notify: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
'stop-timeout': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
'limit-memory': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
|
+
'limit-cpu': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
'limit-pids': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
};
|
|
20
|
+
/** The lease arg every service command takes, with `self` support. */
|
|
21
|
+
export declare const SERVICE_LEASE_ARG_DESCRIPTION = "Dedicated Runtime lease id, or `self` when running on the machine itself";
|
|
22
|
+
/**
|
|
23
|
+
* `stop|restart|remove` wait for the guest's full graceful-stop sequence —
|
|
24
|
+
* up to stopTimeoutSeconds (120s max) plus the kill/confirm tail.
|
|
25
|
+
*/
|
|
26
|
+
export declare const SERVICE_ACTION_TIMEOUT_MS = 150000;
|
|
27
|
+
/**
|
|
28
|
+
* `skrr machines dedicated service …` — commands that act on one lease's
|
|
29
|
+
* declared services through the admitted `dedicated:service:*` socket lane.
|
|
30
|
+
*
|
|
31
|
+
* Unlike the lease REST calls these commands' verbs are socket events with a
|
|
32
|
+
* requestId/ack round-trip, so they open a channel per invocation rather than
|
|
33
|
+
* going through apiFetch. Every refusal — a refused ack, a missing
|
|
34
|
+
* capability, a dropped socket — lands on `this.error` with an actionable
|
|
35
|
+
* sentence, the same convention `callDedicated` gives the REST lane.
|
|
36
|
+
*/
|
|
37
|
+
export declare abstract class DedicatedServiceCommand extends DedicatedLeaseCommand {
|
|
38
|
+
private svcChannel;
|
|
39
|
+
/** The shared channel for this invocation, opened on first use. */
|
|
40
|
+
protected serviceChannel(): Promise<DedicatedServiceChannel>;
|
|
41
|
+
/** Emit one verb and return the daemon's `result`, or throw as a CLI error. */
|
|
42
|
+
protected callService<T = unknown>(verb: ServiceVerb, payload: Record<string, unknown>, timeoutMs?: number): Promise<T | undefined>;
|
|
43
|
+
/**
|
|
44
|
+
* `start|stop|restart|rm` — the shared `dedicated:service:action` round
|
|
45
|
+
* trip and its printout. `rm` maps to the `remove` action on the wire (the
|
|
46
|
+
* doc's verb name); the CLI spells it `rm` because that is what a person
|
|
47
|
+
* deleting a declaration types.
|
|
48
|
+
*/
|
|
49
|
+
protected runServiceAction(leaseId: string, name: string, action: 'start' | 'stop' | 'restart' | 'remove', flags: {
|
|
50
|
+
json?: boolean;
|
|
51
|
+
workspace?: string;
|
|
52
|
+
}): Promise<void>;
|
|
53
|
+
protected closeServiceChannel(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Turn a service-lane failure into the command's exit — the refusal
|
|
56
|
+
* sentence the relay sent, or the clean capability-missing path the SSH
|
|
57
|
+
* lane established for a missing `sshBridge`.
|
|
58
|
+
*/
|
|
59
|
+
protected reportServiceError(err: unknown): never;
|
|
60
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DedicatedServiceCommand = exports.SERVICE_ACTION_TIMEOUT_MS = exports.SERVICE_LEASE_ARG_DESCRIPTION = exports.serviceSpecFlags = void 0;
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const dedicated_lease_command_1 = require("./dedicated-lease-command");
|
|
6
|
+
const dedicated_service_1 = require("./dedicated-service");
|
|
7
|
+
/**
|
|
8
|
+
* The flag set `service create`/`apply` and guest `service propose` share —
|
|
9
|
+
* one definition so the three surfaces cannot drift apart on what a spec
|
|
10
|
+
* accepts. `--file` and the argv tail remain per-command because their
|
|
11
|
+
* mutual-exclusion rules differ.
|
|
12
|
+
*/
|
|
13
|
+
exports.serviceSpecFlags = {
|
|
14
|
+
name: core_1.Flags.string({
|
|
15
|
+
description: 'Service name — ^[a-z0-9][a-z0-9-]{0,62}$, unique per machine',
|
|
16
|
+
}),
|
|
17
|
+
cwd: core_1.Flags.string({
|
|
18
|
+
description: 'Absolute working directory under the workspace, e.g. /workspace/repos/app',
|
|
19
|
+
}),
|
|
20
|
+
env: core_1.Flags.string({
|
|
21
|
+
description: 'Environment variable as NAME=VALUE; repeat for several',
|
|
22
|
+
multiple: true,
|
|
23
|
+
}),
|
|
24
|
+
restart: core_1.Flags.string({
|
|
25
|
+
description: 'Restart policy: always | on-failure | never (default always)',
|
|
26
|
+
options: ['always', 'on-failure', 'never'],
|
|
27
|
+
}),
|
|
28
|
+
notify: core_1.Flags.boolean({
|
|
29
|
+
description: 'Notify the owner when the service reaches failed (default on)',
|
|
30
|
+
allowNo: true,
|
|
31
|
+
}),
|
|
32
|
+
'stop-timeout': core_1.Flags.integer({
|
|
33
|
+
description: 'Seconds SIGTERM gets before the service’s cgroup is killed (1-120, default 10)',
|
|
34
|
+
min: 1,
|
|
35
|
+
max: 120,
|
|
36
|
+
}),
|
|
37
|
+
'limit-memory': core_1.Flags.string({
|
|
38
|
+
description: 'Per-service memory ceiling, e.g. 512M or 2G (clamped to the workload slice)',
|
|
39
|
+
}),
|
|
40
|
+
'limit-cpu': core_1.Flags.integer({
|
|
41
|
+
description: 'Per-service CPU quota as a percent of one core, e.g. 100 for one core',
|
|
42
|
+
min: 1,
|
|
43
|
+
}),
|
|
44
|
+
'limit-pids': core_1.Flags.integer({
|
|
45
|
+
description: 'Per-service max process count',
|
|
46
|
+
min: 1,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
/** The lease arg every service command takes, with `self` support. */
|
|
50
|
+
exports.SERVICE_LEASE_ARG_DESCRIPTION = 'Dedicated Runtime lease id, or `self` when running on the machine itself';
|
|
51
|
+
/**
|
|
52
|
+
* `stop|restart|remove` wait for the guest's full graceful-stop sequence —
|
|
53
|
+
* up to stopTimeoutSeconds (120s max) plus the kill/confirm tail.
|
|
54
|
+
*/
|
|
55
|
+
exports.SERVICE_ACTION_TIMEOUT_MS = 150_000;
|
|
56
|
+
/**
|
|
57
|
+
* `skrr machines dedicated service …` — commands that act on one lease's
|
|
58
|
+
* declared services through the admitted `dedicated:service:*` socket lane.
|
|
59
|
+
*
|
|
60
|
+
* Unlike the lease REST calls these commands' verbs are socket events with a
|
|
61
|
+
* requestId/ack round-trip, so they open a channel per invocation rather than
|
|
62
|
+
* going through apiFetch. Every refusal — a refused ack, a missing
|
|
63
|
+
* capability, a dropped socket — lands on `this.error` with an actionable
|
|
64
|
+
* sentence, the same convention `callDedicated` gives the REST lane.
|
|
65
|
+
*/
|
|
66
|
+
class DedicatedServiceCommand extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
67
|
+
svcChannel = null;
|
|
68
|
+
/** The shared channel for this invocation, opened on first use. */
|
|
69
|
+
async serviceChannel() {
|
|
70
|
+
if (this.svcChannel?.isConnected)
|
|
71
|
+
return this.svcChannel;
|
|
72
|
+
this.svcChannel?.close();
|
|
73
|
+
const channel = new dedicated_service_1.DedicatedServiceChannel({
|
|
74
|
+
baseURL: this.cliConfig.baseURL,
|
|
75
|
+
token: this.resolvedCredential.token,
|
|
76
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
await channel.open();
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
this.reportServiceError(err);
|
|
82
|
+
}
|
|
83
|
+
this.svcChannel = channel;
|
|
84
|
+
return channel;
|
|
85
|
+
}
|
|
86
|
+
/** Emit one verb and return the daemon's `result`, or throw as a CLI error. */
|
|
87
|
+
async callService(verb, payload, timeoutMs) {
|
|
88
|
+
try {
|
|
89
|
+
const channel = await this.serviceChannel();
|
|
90
|
+
const { result } = await channel.call(verb, payload, timeoutMs);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
this.reportServiceError(err);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* `start|stop|restart|rm` — the shared `dedicated:service:action` round
|
|
99
|
+
* trip and its printout. `rm` maps to the `remove` action on the wire (the
|
|
100
|
+
* doc's verb name); the CLI spells it `rm` because that is what a person
|
|
101
|
+
* deleting a declaration types.
|
|
102
|
+
*/
|
|
103
|
+
async runServiceAction(leaseId, name, action, flags) {
|
|
104
|
+
// A graceful stop can take up to stopTimeoutSeconds (max 120s) plus the
|
|
105
|
+
// kill/confirm tail — the action ack waits for all of it, so the call
|
|
106
|
+
// window must outlive the longest legitimate stop or it reports a false
|
|
107
|
+
// connectivity failure while the machine is still working.
|
|
108
|
+
const result = await this.callService('action', {
|
|
109
|
+
leaseId,
|
|
110
|
+
name,
|
|
111
|
+
action,
|
|
112
|
+
...this.scopeFrom(flags),
|
|
113
|
+
}, action === 'start' ? undefined : exports.SERVICE_ACTION_TIMEOUT_MS);
|
|
114
|
+
this.closeServiceChannel();
|
|
115
|
+
if (flags.json) {
|
|
116
|
+
this.log(JSON.stringify(result ?? { name, action }, null, 2));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const sentences = {
|
|
120
|
+
start: {
|
|
121
|
+
done: 'is starting',
|
|
122
|
+
hint: 'The machine will keep it running per its restart policy.',
|
|
123
|
+
},
|
|
124
|
+
stop: {
|
|
125
|
+
done: 'is stopping',
|
|
126
|
+
hint: 'Desired state is stopped — it stays stopped across machine restarts until you `service start` it.',
|
|
127
|
+
},
|
|
128
|
+
restart: { done: 'is restarting' },
|
|
129
|
+
remove: {
|
|
130
|
+
done: 'was removed',
|
|
131
|
+
hint: 'The declaration is gone; the machine will not bring it back.',
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
const sentence = sentences[action];
|
|
135
|
+
this.log(`Service ${name} ${sentence.done}.`);
|
|
136
|
+
if (sentence.hint)
|
|
137
|
+
this.log(sentence.hint);
|
|
138
|
+
}
|
|
139
|
+
closeServiceChannel() {
|
|
140
|
+
this.svcChannel?.close();
|
|
141
|
+
this.svcChannel = null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Turn a service-lane failure into the command's exit — the refusal
|
|
145
|
+
* sentence the relay sent, or the clean capability-missing path the SSH
|
|
146
|
+
* lane established for a missing `sshBridge`.
|
|
147
|
+
*/
|
|
148
|
+
reportServiceError(err) {
|
|
149
|
+
if (err instanceof dedicated_service_1.DedicatedServiceError) {
|
|
150
|
+
if ((0, dedicated_service_1.isServiceUnsupportedCode)(err.code)) {
|
|
151
|
+
this.failWithCliError({
|
|
152
|
+
message: err.message,
|
|
153
|
+
code: 'DEDICATED_RUNTIME_SERVICES_UNSUPPORTED',
|
|
154
|
+
exit: 1,
|
|
155
|
+
retryable: false,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (err.code === 'SERVICE_CONNECT_FAILED') {
|
|
159
|
+
this.failWithCliError({
|
|
160
|
+
message: err.message,
|
|
161
|
+
code: err.code,
|
|
162
|
+
exit: 1,
|
|
163
|
+
retryable: true,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// Usage-shape failures (bad spec, bad flags) are the caller's to fix.
|
|
167
|
+
const usage = [
|
|
168
|
+
'SPEC_JSON',
|
|
169
|
+
'SPEC_INVALID',
|
|
170
|
+
'SPEC_FILE',
|
|
171
|
+
'TEMPLATE_JSON',
|
|
172
|
+
'TEMPLATE_INVALID',
|
|
173
|
+
'TEMPLATE_NAME_INVALID',
|
|
174
|
+
'TEMPLATE_PARAM_MISSING',
|
|
175
|
+
'TEMPLATE_PARAM_UNKNOWN',
|
|
176
|
+
].includes(err.code);
|
|
177
|
+
this.error(err.message, { exit: usage ? 2 : 1, code: err.code });
|
|
178
|
+
}
|
|
179
|
+
this.handleApiError(err);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.DedicatedServiceCommand = DedicatedServiceCommand;
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { io, type Socket } from 'socket.io-client';
|
|
2
|
+
/**
|
|
3
|
+
* Declared services on a Dedicated Runtime — the CLI half of
|
|
4
|
+
* docs/architecture/dedicated-runtime-always-on-workloads-2026-09-21.md (§5.3
|
|
5
|
+
* spec, §5.4 wire surface, §5.6 agent proposals).
|
|
6
|
+
*
|
|
7
|
+
* A service is a spec the daemon keeps reconciling: command, restart policy,
|
|
8
|
+
* env, per-service cgroup limits. The CLI never talks to the machine's
|
|
9
|
+
* registry — every verb rides the same admitted channel the terminal and SSH
|
|
10
|
+
* lanes use, as a `dedicated:service:*` socket event relayed by the API to the
|
|
11
|
+
* lease's daemon. What crosses the wire is exactly what the design doc names;
|
|
12
|
+
* anything not in the spec is refused by the daemon, not by us.
|
|
13
|
+
*
|
|
14
|
+
* Wire vocabulary (client side, mirrored from daemon:service:*):
|
|
15
|
+
*
|
|
16
|
+
* client → API dedicated:service:list|get|create|update|action|logs|
|
|
17
|
+
* logs:stop|approve|secret {…payload, requestId}
|
|
18
|
+
* API → client dedicated:service:ack {requestId, ok, error?, code?, result?}
|
|
19
|
+
* dedicated:service:state {name, status, detail?, ts}
|
|
20
|
+
* dedicated:service:log {name, streamId, data(b64), ts}
|
|
21
|
+
* dedicated:service:log:closed {name, streamId, reason}
|
|
22
|
+
* dedicated:service:proposed {name, spec, createdBy}
|
|
23
|
+
* dedicated:templates:ack {requestId, ok, error?, code?, result?}
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEDICATED_SERVICE_EVENTS: {
|
|
26
|
+
readonly list: "dedicated:service:list";
|
|
27
|
+
readonly get: "dedicated:service:get";
|
|
28
|
+
readonly create: "dedicated:service:create";
|
|
29
|
+
readonly update: "dedicated:service:update";
|
|
30
|
+
readonly action: "dedicated:service:action";
|
|
31
|
+
readonly logs: "dedicated:service:logs";
|
|
32
|
+
readonly logsStop: "dedicated:service:logs:stop";
|
|
33
|
+
readonly approve: "dedicated:service:approve";
|
|
34
|
+
readonly secret: "dedicated:service:secret";
|
|
35
|
+
/** Phase-2 verbs — wired now; an old daemon refuses them cleanly. */
|
|
36
|
+
readonly exec: "dedicated:service:exec";
|
|
37
|
+
readonly templatesList: "dedicated:templates:list";
|
|
38
|
+
readonly templatesGet: "dedicated:templates:get";
|
|
39
|
+
readonly ack: "dedicated:service:ack";
|
|
40
|
+
readonly templatesAck: "dedicated:templates:ack";
|
|
41
|
+
readonly state: "dedicated:service:state";
|
|
42
|
+
readonly log: "dedicated:service:log";
|
|
43
|
+
readonly logClosed: "dedicated:service:log:closed";
|
|
44
|
+
readonly proposed: "dedicated:service:proposed";
|
|
45
|
+
};
|
|
46
|
+
/** How long a verb has to answer before the machine is declared unreachable. */
|
|
47
|
+
export declare const SERVICE_CALL_TIMEOUT_MS = 30000;
|
|
48
|
+
/** §5.3 — the scope name `skrr-svc-<name>` derives from it. */
|
|
49
|
+
export declare const SERVICE_NAME_PATTERN: RegExp;
|
|
50
|
+
/** Secret names — the daemon's grammar; checked client-side so a bad name
|
|
51
|
+
* is a usage error here, not a refusal that names the wrong object. */
|
|
52
|
+
export declare const SERVICE_SECRET_NAME_PATTERN: RegExp;
|
|
53
|
+
/** Leaf names a service may never claim (the wrapper routes them itself). */
|
|
54
|
+
export declare const SERVICE_RESERVED_NAMES: Set<string>;
|
|
55
|
+
export declare const SERVICE_RESTART_POLICIES: Set<string>;
|
|
56
|
+
export declare const SERVICE_ACTIONS: Set<string>;
|
|
57
|
+
/**
|
|
58
|
+
* The declared-service spec — §5.3's record shape. Unknown fields are kept:
|
|
59
|
+
* the forward-compat rule is a read/write rule (a spec written by a newer
|
|
60
|
+
* daemon must round-trip through an older client unmangled), so `apply` and
|
|
61
|
+
* `export` carry whatever the daemon returned rather than a known-fields
|
|
62
|
+
* projection. The phase-2/horizon names (`schedule`, `timezone`,
|
|
63
|
+
* `missedFire`, `probe`, `hooks`, `replicas`, `dependsOn`) are listed only so
|
|
64
|
+
* the type reads them; the index signature is what preserves them.
|
|
65
|
+
*/
|
|
66
|
+
export interface DedicatedServiceSpec {
|
|
67
|
+
version?: number;
|
|
68
|
+
name?: string;
|
|
69
|
+
command?: string[];
|
|
70
|
+
shell?: string;
|
|
71
|
+
cwd?: string;
|
|
72
|
+
env?: Record<string, string>;
|
|
73
|
+
restart?: 'always' | 'on-failure' | 'never' | string;
|
|
74
|
+
backoff?: {
|
|
75
|
+
initialMs?: number;
|
|
76
|
+
maxMs?: number;
|
|
77
|
+
budget?: number;
|
|
78
|
+
windowMs?: number;
|
|
79
|
+
};
|
|
80
|
+
stopTimeoutSeconds?: number;
|
|
81
|
+
notify?: boolean;
|
|
82
|
+
limits?: {
|
|
83
|
+
memoryMax?: string;
|
|
84
|
+
cpuQuotaPercent?: number;
|
|
85
|
+
pidsMax?: number;
|
|
86
|
+
};
|
|
87
|
+
disabled?: boolean;
|
|
88
|
+
createdBy?: string;
|
|
89
|
+
revision?: number;
|
|
90
|
+
createdAt?: string;
|
|
91
|
+
updatedAt?: string;
|
|
92
|
+
schedule?: string;
|
|
93
|
+
timezone?: string;
|
|
94
|
+
missedFire?: string;
|
|
95
|
+
probe?: unknown;
|
|
96
|
+
hooks?: unknown;
|
|
97
|
+
replicas?: number;
|
|
98
|
+
dependsOn?: string[];
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
}
|
|
101
|
+
/** One computed-state row, as `list`/`get` return it. Status is derived, never stored. */
|
|
102
|
+
export interface DedicatedServiceRow {
|
|
103
|
+
/** Present on state pushes and some relay shapes; list/get rows name the service only under `spec.name`. */
|
|
104
|
+
name?: string;
|
|
105
|
+
status?: string;
|
|
106
|
+
/** A plain string or the daemon's structured detail ({reason, exitCode, …}). */
|
|
107
|
+
detail?: string | Record<string, unknown>;
|
|
108
|
+
restart?: string;
|
|
109
|
+
createdBy?: string;
|
|
110
|
+
disabled?: boolean;
|
|
111
|
+
spec?: DedicatedServiceSpec;
|
|
112
|
+
/** Phase-2: per-scope metrics the daemon may attach (`cpu.stat` et al). */
|
|
113
|
+
stats?: DedicatedServiceStats;
|
|
114
|
+
[key: string]: unknown;
|
|
115
|
+
}
|
|
116
|
+
export interface DedicatedServiceStats {
|
|
117
|
+
cpuPercent?: number;
|
|
118
|
+
memoryBytes?: number;
|
|
119
|
+
memoryMaxBytes?: number;
|
|
120
|
+
pidsCurrent?: number;
|
|
121
|
+
pidsMax?: number;
|
|
122
|
+
[key: string]: unknown;
|
|
123
|
+
}
|
|
124
|
+
/** An agent proposal awaiting the owner — `status: proposed`, per §5.6. */
|
|
125
|
+
export interface DedicatedServiceProposal {
|
|
126
|
+
name?: string;
|
|
127
|
+
proposalId?: string;
|
|
128
|
+
spec?: DedicatedServiceSpec;
|
|
129
|
+
createdBy?: string;
|
|
130
|
+
proposedAt?: string;
|
|
131
|
+
[key: string]: unknown;
|
|
132
|
+
}
|
|
133
|
+
export interface DedicatedServiceGetResult {
|
|
134
|
+
spec?: DedicatedServiceSpec;
|
|
135
|
+
status?: string;
|
|
136
|
+
detail?: string | Record<string, unknown>;
|
|
137
|
+
stats?: DedicatedServiceStats;
|
|
138
|
+
/** Bounded ring of recent exits: {exitCode, signal, at}. */
|
|
139
|
+
exits?: Array<{
|
|
140
|
+
exitCode?: number | null;
|
|
141
|
+
signal?: string | null;
|
|
142
|
+
at?: string;
|
|
143
|
+
}>;
|
|
144
|
+
[key: string]: unknown;
|
|
145
|
+
}
|
|
146
|
+
export interface DedicatedServiceAck {
|
|
147
|
+
requestId?: string;
|
|
148
|
+
ok?: boolean;
|
|
149
|
+
error?: string;
|
|
150
|
+
code?: string;
|
|
151
|
+
result?: unknown;
|
|
152
|
+
}
|
|
153
|
+
export declare class DedicatedServiceError extends Error {
|
|
154
|
+
readonly code: string;
|
|
155
|
+
constructor(message: string, code: string);
|
|
156
|
+
}
|
|
157
|
+
/** True for every refusal that says "this machine has no services support". */
|
|
158
|
+
export declare function isServiceUnsupportedCode(code: string | undefined): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* A service refusal in words that say what to do — the same register
|
|
161
|
+
* `describeSshStartRefusal` uses for the SSH lane. The capability-missing
|
|
162
|
+
* branch mirrors the sshBridge fallback: an old image or an old daemon is a
|
|
163
|
+
* named condition with a next step, not a crash.
|
|
164
|
+
*/
|
|
165
|
+
export declare function describeServiceRefusal(ack: Pick<DedicatedServiceAck, 'code' | 'error'>, context?: {
|
|
166
|
+
leaseId?: string;
|
|
167
|
+
verb?: string;
|
|
168
|
+
name?: string;
|
|
169
|
+
}): string;
|
|
170
|
+
/** Validation that costs the daemon nothing to re-check — §5.3's table, enforced client-side first. */
|
|
171
|
+
export declare function validateServiceSpec(doc: unknown, options?: {
|
|
172
|
+
requireName?: boolean;
|
|
173
|
+
requireCommand?: boolean;
|
|
174
|
+
}): string[];
|
|
175
|
+
/**
|
|
176
|
+
* Parse a `service.json` document, refusing with every problem named at once
|
|
177
|
+
* rather than the first — a file you are editing deserves the whole list.
|
|
178
|
+
*/
|
|
179
|
+
export declare function parseServiceSpecDocument(raw: string, source: string, options?: {
|
|
180
|
+
requireName?: boolean;
|
|
181
|
+
requireCommand?: boolean;
|
|
182
|
+
}): DedicatedServiceSpec;
|
|
183
|
+
/** The spec a mutation carries: the document minus the fields the daemon owns. */
|
|
184
|
+
export declare function specPayload(spec: DedicatedServiceSpec): Record<string, unknown>;
|
|
185
|
+
/**
|
|
186
|
+
* The repo `service.json` form of a stored spec — `export`'s output. The
|
|
187
|
+
* document the daemon returned minus its bookkeeping, unknown fields kept
|
|
188
|
+
* verbatim so forward fields survive the round-trip.
|
|
189
|
+
*/
|
|
190
|
+
export declare function specExportDocument(spec: DedicatedServiceSpec): Record<string, unknown>;
|
|
191
|
+
/** `--env KEY=VALUE` entries, one flag instance each. */
|
|
192
|
+
export declare function parseEnvEntries(entries: readonly string[] | undefined): Record<string, string>;
|
|
193
|
+
/** `name=value` pairs for --param; the value stays a string — templates interpolate text. */
|
|
194
|
+
export declare function parseParamEntries(entries: readonly string[] | undefined): Record<string, string>;
|
|
195
|
+
/** A spec assembled from create/propose flags rather than a file. */
|
|
196
|
+
export declare function specFromFlags(input: {
|
|
197
|
+
name?: string;
|
|
198
|
+
argv?: string[];
|
|
199
|
+
cwd?: string;
|
|
200
|
+
env?: Record<string, string>;
|
|
201
|
+
restart?: string;
|
|
202
|
+
notify?: boolean;
|
|
203
|
+
stopTimeoutSeconds?: number;
|
|
204
|
+
limits?: {
|
|
205
|
+
memoryMax?: string;
|
|
206
|
+
cpuQuotaPercent?: number;
|
|
207
|
+
pidsMax?: number;
|
|
208
|
+
};
|
|
209
|
+
}): DedicatedServiceSpec;
|
|
210
|
+
export interface DedicatedServiceSocketOptions {
|
|
211
|
+
baseURL: string;
|
|
212
|
+
token: string;
|
|
213
|
+
/** Injected for tests. */
|
|
214
|
+
connect?: (url: string, opts: Parameters<typeof io>[1]) => Socket;
|
|
215
|
+
}
|
|
216
|
+
export type ServiceVerb = 'list' | 'get' | 'create' | 'update' | 'action' | 'logs' | 'logs:stop' | 'approve' | 'secret' | 'exec';
|
|
217
|
+
/**
|
|
218
|
+
* One admitted socket for a run of service verbs. `call` emits
|
|
219
|
+
* `dedicated:service:<verb>` with a fresh requestId and resolves on the
|
|
220
|
+
* matching `dedicated:service:ack`; push events (`state`, `log`,
|
|
221
|
+
* `log:closed`, `proposed`) are exposed via `on` for the follow loop.
|
|
222
|
+
*/
|
|
223
|
+
export declare class DedicatedServiceChannel {
|
|
224
|
+
private options;
|
|
225
|
+
private socket;
|
|
226
|
+
private connected;
|
|
227
|
+
private dead;
|
|
228
|
+
private pending;
|
|
229
|
+
private onDead;
|
|
230
|
+
constructor(options: DedicatedServiceSocketOptions);
|
|
231
|
+
/** Resolves once the transport is up; rejects on connect failure. */
|
|
232
|
+
open(): Promise<void>;
|
|
233
|
+
/** A socket dying mid-follow ends the follow cleanly rather than hanging. */
|
|
234
|
+
setOnDead(handler: (() => void) | null): void;
|
|
235
|
+
get isConnected(): boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Emit a verb and await its ack. A refusal ack is a DedicatedServiceError
|
|
238
|
+
* whose message is the actionable sentence; the raw code rides along so a
|
|
239
|
+
* caller can branch on `conflict` or a missing capability.
|
|
240
|
+
*/
|
|
241
|
+
call<T = unknown>(verb: ServiceVerb, payload: Record<string, unknown>, timeoutMs?: number): Promise<{
|
|
242
|
+
result: T | undefined;
|
|
243
|
+
ack: DedicatedServiceAck;
|
|
244
|
+
}>;
|
|
245
|
+
/**
|
|
246
|
+
* A read against the template gallery — `dedicated:templates:list|get`,
|
|
247
|
+
* answered on `dedicated:templates:ack`. Same requestId/ack discipline as
|
|
248
|
+
* the service verbs; the event family is the only difference.
|
|
249
|
+
*/
|
|
250
|
+
callTemplates<T = unknown>(verb: 'list' | 'get', payload: Record<string, unknown>, timeoutMs?: number): Promise<{
|
|
251
|
+
result: T | undefined;
|
|
252
|
+
ack: DedicatedServiceAck;
|
|
253
|
+
}>;
|
|
254
|
+
/** The shared request/ack round-trip. */
|
|
255
|
+
private callEvent;
|
|
256
|
+
/** Subscribe to a server-pushed frame (`state`, `log`, `log:closed`, `proposed`). */
|
|
257
|
+
on(event: string, handler: (frame: Record<string, unknown>) => void): void;
|
|
258
|
+
off(event: string, handler: (frame: Record<string, unknown>) => void): void;
|
|
259
|
+
/** Emit without waiting for an ack (logs:stop — the stream may already be gone). */
|
|
260
|
+
send(event: string, payload: Record<string, unknown>): void;
|
|
261
|
+
close(): void;
|
|
262
|
+
}
|
|
263
|
+
export interface ServiceLogFrame {
|
|
264
|
+
name?: string;
|
|
265
|
+
streamId?: string;
|
|
266
|
+
data?: string;
|
|
267
|
+
ts?: number | string;
|
|
268
|
+
}
|
|
269
|
+
export interface ServiceLogClosedFrame {
|
|
270
|
+
name?: string;
|
|
271
|
+
streamId?: string;
|
|
272
|
+
reason?: string;
|
|
273
|
+
}
|
|
274
|
+
export interface StreamServiceLogsOptions extends DedicatedServiceSocketOptions {
|
|
275
|
+
leaseId: string;
|
|
276
|
+
name: string;
|
|
277
|
+
follow: boolean;
|
|
278
|
+
/** Bytes from the end of the log to replay first. */
|
|
279
|
+
tailBytes?: number;
|
|
280
|
+
output: NodeJS.WritableStream;
|
|
281
|
+
errorOutput: NodeJS.WritableStream;
|
|
282
|
+
/** Frame sink for tests; defaults to output.write. */
|
|
283
|
+
write?: (bytes: Buffer) => void;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* `service logs` — tail the stored log, then follow live
|
|
287
|
+
* `dedicated:service:log` frames until `log:closed`, a SIGINT, or the socket
|
|
288
|
+
* dies. Resolves with the exit code the command should use (0 unless the
|
|
289
|
+
* stream failed). The follow is closed with `dedicated:service:logs:stop` so
|
|
290
|
+
* the daemon does not keep piping to a dead reader.
|
|
291
|
+
*/
|
|
292
|
+
export declare function streamServiceLogs(options: StreamServiceLogsOptions): Promise<number>;
|
|
293
|
+
/**
|
|
294
|
+
* A service template — §10.2's spec-with-holes. `${param}` slots inside
|
|
295
|
+
* `spec` are substituted with --param values or the param's default.
|
|
296
|
+
*/
|
|
297
|
+
export interface DedicatedServiceTemplate {
|
|
298
|
+
version?: number;
|
|
299
|
+
name?: string;
|
|
300
|
+
description?: string;
|
|
301
|
+
params?: Array<{
|
|
302
|
+
name: string;
|
|
303
|
+
required?: boolean;
|
|
304
|
+
default?: string;
|
|
305
|
+
description?: string;
|
|
306
|
+
}>;
|
|
307
|
+
spec?: Record<string, unknown>;
|
|
308
|
+
[key: string]: unknown;
|
|
309
|
+
}
|
|
310
|
+
export declare function serviceTemplatesDir(home?: string): string;
|
|
311
|
+
/**
|
|
312
|
+
* `~/.skrr/templates/<name>.json`, or null when absent. A template file that
|
|
313
|
+
* will not parse is an error, not a miss — silent fall-through to the gallery
|
|
314
|
+
* would hide a broken local file.
|
|
315
|
+
*/
|
|
316
|
+
export declare function loadLocalServiceTemplate(name: string, home?: string): DedicatedServiceTemplate | null;
|
|
317
|
+
/**
|
|
318
|
+
* Merge a template with its params into a concrete spec. Required params
|
|
319
|
+
* without a value or a default refuse before any substitution runs — a
|
|
320
|
+
* half-merged spec is a worse failure than a named missing param.
|
|
321
|
+
*/
|
|
322
|
+
export declare function mergeServiceTemplate(template: DedicatedServiceTemplate, given: Record<string, string>, source?: string): DedicatedServiceSpec;
|
|
323
|
+
/**
|
|
324
|
+
* The wire's `detail` is a string or the daemon's structured object
|
|
325
|
+
* ({reason, exitCode, signal, restarts, detail}) — render the fields for a
|
|
326
|
+
* status line, never "[object Object]". Shared by the owner-lane and
|
|
327
|
+
* guest-local status commands so both read the same shape.
|
|
328
|
+
*/
|
|
329
|
+
export declare function serviceDetailText(detail: unknown): string | undefined;
|
|
330
|
+
/** The daemon's workload-facing service socket on a Dedicated Runtime guest. */
|
|
331
|
+
export declare const GUEST_SERVICE_SOCKET_PATH = "/run/skrr-dedicated-runtime/service-propose/service-propose.sock";
|
|
332
|
+
/**
|
|
333
|
+
* True when this process is running on a Dedicated Runtime guest — the
|
|
334
|
+
* workload-uid test, or the guest markers the image/daemon own. An SSH
|
|
335
|
+
* session may not carry the wrapper's env stamp, so the filesystem markers
|
|
336
|
+
* count too; the socket itself remains the authority.
|
|
337
|
+
*/
|
|
338
|
+
export declare function runningOnDedicatedRuntimeGuest(env?: NodeJS.ProcessEnv, getuid?: (() => number) | undefined, paths?: {
|
|
339
|
+
socketPath?: string;
|
|
340
|
+
attestationPath?: string;
|
|
341
|
+
runtimeDir?: string;
|
|
342
|
+
}): boolean;
|