@skrr-ai/cli 0.1.91 → 0.1.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.d.ts +44 -0
- package/dist/base-command.js +96 -0
- package/dist/commands/agents/badge.d.ts +41 -0
- package/dist/commands/agents/badge.js +158 -0
- package/dist/commands/agents/create.d.ts +24 -0
- package/dist/commands/agents/create.js +212 -0
- package/dist/commands/agents/embed.d.ts +20 -0
- package/dist/commands/agents/embed.js +61 -0
- package/dist/commands/agents/share.d.ts +27 -0
- package/dist/commands/agents/share.js +100 -0
- package/dist/commands/agents/vanity.d.ts +21 -0
- package/dist/commands/agents/vanity.js +77 -0
- package/dist/commands/agents/visibility.d.ts +21 -1
- package/dist/commands/agents/visibility.js +112 -0
- package/dist/commands/commands.d.ts +1 -0
- package/dist/commands/commands.js +22 -9
- package/dist/commands/earnings/attributions.d.ts +17 -0
- package/dist/commands/earnings/attributions.js +82 -0
- package/dist/commands/earnings/index.js +2 -1
- package/dist/commands/generate-recovery-code.js +4 -3
- package/dist/commands/github/allow-tools.d.ts +1 -0
- package/dist/commands/github/app/install.d.ts +1 -0
- package/dist/commands/github/app/status.d.ts +1 -0
- package/dist/commands/github/connect.d.ts +1 -0
- package/dist/commands/github/connections.d.ts +1 -0
- package/dist/commands/github/disconnect.d.ts +1 -0
- package/dist/commands/github/finalize.d.ts +1 -0
- package/dist/commands/github/reconnect.d.ts +1 -0
- package/dist/commands/github/run.d.ts +1 -0
- package/dist/commands/github/tools.d.ts +1 -0
- package/dist/commands/integrations/connections/connect.d.ts +1 -0
- package/dist/commands/integrations/connections/disconnect.d.ts +1 -0
- package/dist/commands/integrations/connections/finalize.d.ts +1 -0
- package/dist/commands/integrations/connections/list.d.ts +1 -0
- package/dist/commands/integrations/connections/reconnect.d.ts +1 -0
- package/dist/commands/integrations/execute.d.ts +1 -0
- package/dist/commands/integrations/search.d.ts +1 -0
- package/dist/commands/integrations/toolkits.d.ts +1 -0
- package/dist/commands/integrations/tools/allow.d.ts +1 -0
- package/dist/commands/integrations/tools/list.d.ts +1 -0
- package/dist/commands/login.js +12 -0
- package/dist/commands/machines/dedicated/logs.d.ts +19 -0
- package/dist/commands/machines/dedicated/logs.js +103 -0
- package/dist/commands/machines/dedicated/power/index.js +3 -2
- package/dist/commands/machines/dedicated/power/set.js +1 -1
- package/dist/commands/machines/dedicated/power/waiting.d.ts +13 -0
- package/dist/commands/machines/dedicated/power/waiting.js +36 -0
- package/dist/commands/open.d.ts +24 -0
- package/dist/commands/open.js +74 -0
- package/dist/commands/projects/archive.d.ts +1 -0
- package/dist/commands/projects/archive.js +23 -0
- package/dist/commands/projects/delete.d.ts +1 -0
- package/dist/commands/projects/delete.js +23 -0
- package/dist/commands/projects/list.d.ts +3 -0
- package/dist/commands/projects/list.js +12 -2
- package/dist/commands/spaces/actions/add.js +4 -3
- package/dist/commands/spaces/actions/available.js +3 -2
- package/dist/commands/spaces/actions/list.js +5 -4
- package/dist/commands/spaces/actions/replace.js +6 -5
- package/dist/commands/spaces/archive.js +3 -2
- package/dist/commands/spaces/auto-executor/preview.js +4 -3
- package/dist/commands/spaces/auto-executor/run.js +4 -3
- package/dist/commands/spaces/auto-executor/runs.js +3 -2
- package/dist/commands/spaces/auto-executor/update.js +4 -3
- package/dist/commands/spaces/bootstrap.js +3 -2
- package/dist/commands/spaces/briefs/delete.js +3 -2
- package/dist/commands/spaces/briefs/get.js +3 -2
- package/dist/commands/spaces/briefs/list.js +3 -2
- package/dist/commands/spaces/briefs/set.js +5 -4
- package/dist/commands/spaces/capacity.js +5 -4
- package/dist/commands/spaces/conversations.js +3 -2
- package/dist/commands/spaces/cycles/create.js +3 -2
- package/dist/commands/spaces/cycles/graph.js +2 -1
- package/dist/commands/spaces/cycles/list.js +3 -2
- package/dist/commands/spaces/cycles/settings.js +4 -3
- package/dist/commands/spaces/cycles/show.js +3 -2
- package/dist/commands/spaces/cycles/update.js +3 -2
- package/dist/commands/spaces/delete.js +4 -3
- package/dist/commands/spaces/expertise-suggestions.js +4 -3
- package/dist/commands/spaces/files/delete.js +3 -2
- package/dist/commands/spaces/files/folders/create.js +3 -2
- package/dist/commands/spaces/files/folders/delete.js +3 -2
- package/dist/commands/spaces/files/folders/list.js +3 -2
- package/dist/commands/spaces/files/folders/update.js +3 -2
- package/dist/commands/spaces/files/list.js +3 -2
- package/dist/commands/spaces/files/move.js +3 -2
- package/dist/commands/spaces/files/rename.js +3 -2
- package/dist/commands/spaces/files/upload.js +6 -5
- package/dist/commands/spaces/github-automations/set.js +3 -2
- package/dist/commands/spaces/github-automations/show.js +3 -2
- package/dist/commands/spaces/goals.js +2 -1
- package/dist/commands/spaces/heartbeats/create.js +4 -3
- package/dist/commands/spaces/heartbeats/delete.js +4 -3
- package/dist/commands/spaces/heartbeats/list.js +4 -3
- package/dist/commands/spaces/heartbeats/status.js +3 -2
- package/dist/commands/spaces/heartbeats/update.js +4 -3
- package/dist/commands/spaces/insights.js +5 -4
- package/dist/commands/spaces/labels/add.js +4 -3
- package/dist/commands/spaces/labels/list.js +2 -1
- package/dist/commands/spaces/labels/remove.js +4 -3
- package/dist/commands/spaces/list.d.ts +3 -0
- package/dist/commands/spaces/list.js +11 -2
- package/dist/commands/spaces/live/cards/create.js +3 -2
- package/dist/commands/spaces/live/cards/list.js +3 -2
- package/dist/commands/spaces/live/cards/reorder.js +7 -2
- package/dist/commands/spaces/live/scene.js +4 -3
- package/dist/commands/spaces/members/add.js +7 -6
- package/dist/commands/spaces/members/list.js +4 -3
- package/dist/commands/spaces/members/remove.js +7 -6
- package/dist/commands/spaces/move.js +3 -2
- package/dist/commands/spaces/pin.js +5 -4
- package/dist/commands/spaces/preferences/show.js +4 -3
- package/dist/commands/spaces/preferences/tabs.js +4 -3
- package/dist/commands/spaces/revisions.js +3 -2
- package/dist/commands/spaces/room/ensure.js +5 -4
- package/dist/commands/spaces/room/messages.js +3 -2
- package/dist/commands/spaces/room/show.js +5 -4
- package/dist/commands/spaces/skills/add.js +4 -3
- package/dist/commands/spaces/skills/list.js +3 -2
- package/dist/commands/spaces/skills/pin.js +4 -3
- package/dist/commands/spaces/skills/remove.js +4 -3
- package/dist/commands/spaces/snapshot.js +3 -2
- package/dist/commands/spaces/states/archive.js +3 -2
- package/dist/commands/spaces/states/create.js +3 -2
- package/dist/commands/spaces/states/list.js +3 -2
- package/dist/commands/spaces/states/reorder.js +2 -1
- package/dist/commands/spaces/states/update.js +3 -2
- package/dist/commands/spaces/summary.js +4 -3
- package/dist/commands/spaces/tasks.d.ts +3 -0
- package/dist/commands/spaces/tasks.js +14 -3
- package/dist/commands/spaces/triggers/delete.js +5 -4
- package/dist/commands/spaces/triggers/set.js +4 -3
- package/dist/commands/spaces/triggers/show.js +4 -3
- package/dist/commands/spaces/unarchive.js +3 -2
- package/dist/commands/spaces/update.js +5 -4
- package/dist/commands/spaces/views/create.js +3 -2
- package/dist/commands/spaces/views/list.js +3 -2
- package/dist/commands/spaces/views/reorder.js +6 -3
- package/dist/commands/spaces/views/subscribe.js +2 -1
- package/dist/commands/spaces/views/subscriptions.js +1 -0
- package/dist/commands/spaces/views/unsubscribe.js +2 -1
- package/dist/commands/spaces/widgets/add.js +4 -3
- package/dist/commands/spaces/widgets/list.js +3 -2
- package/dist/commands/spaces/widgets/remove.js +5 -4
- package/dist/commands/spaces/work-graph.js +2 -1
- package/dist/commands/store/install.d.ts +1 -1
- package/dist/commands/store/install.js +24 -8
- package/dist/commands/store/show.d.ts +25 -0
- package/dist/commands/store/show.js +203 -0
- package/dist/commands/store/stats.d.ts +33 -0
- package/dist/commands/store/stats.js +258 -0
- package/dist/commands/tasks/actions/attach.js +1 -1
- package/dist/commands/tasks/actions/detach.js +4 -3
- package/dist/commands/tasks/activity.js +3 -2
- package/dist/commands/tasks/ancestors.js +2 -1
- package/dist/commands/tasks/approvals/create.js +2 -1
- package/dist/commands/tasks/approvals/delete.js +3 -2
- package/dist/commands/tasks/approvals/list.js +5 -4
- package/dist/commands/tasks/approvals/resolve.js +2 -1
- package/dist/commands/tasks/archive.js +3 -2
- package/dist/commands/tasks/assign.js +4 -3
- package/dist/commands/tasks/attachments/delete.js +3 -2
- package/dist/commands/tasks/attachments/download.d.ts +1 -0
- package/dist/commands/tasks/attachments/download.js +20 -1
- package/dist/commands/tasks/attachments/list.js +2 -1
- package/dist/commands/tasks/attachments/set-role.js +2 -1
- package/dist/commands/tasks/attachments/upload.js +2 -1
- package/dist/commands/tasks/bulk-update.d.ts +1 -0
- package/dist/commands/tasks/bulk-update.js +106 -15
- package/dist/commands/tasks/cancel-cascade.d.ts +1 -0
- package/dist/commands/tasks/cancel-cascade.js +13 -3
- package/dist/commands/tasks/cascade-status.js +2 -1
- package/dist/commands/tasks/chat/send.d.ts +44 -0
- package/dist/commands/tasks/chat/send.js +112 -0
- package/dist/commands/tasks/checkout.js +3 -2
- package/dist/commands/tasks/children.js +2 -1
- package/dist/commands/tasks/comments/add.js +7 -6
- package/dist/commands/tasks/comments/anchor.js +8 -7
- package/dist/commands/tasks/comments/delete.js +3 -2
- package/dist/commands/tasks/comments/list.js +2 -1
- package/dist/commands/tasks/comments/reopen.js +3 -2
- package/dist/commands/tasks/comments/resolve.js +3 -2
- package/dist/commands/tasks/create-tree.d.ts +63 -0
- package/dist/commands/tasks/create-tree.js +197 -4
- package/dist/commands/tasks/delete.js +5 -4
- package/dist/commands/tasks/descendants.js +2 -1
- package/dist/commands/tasks/dri-plan.js +3 -2
- package/dist/commands/tasks/dri-run.js +3 -2
- package/dist/commands/tasks/dri-status.js +2 -1
- package/dist/commands/tasks/duplicate-pipeline.js +2 -1
- package/dist/commands/tasks/execution-summary.js +2 -1
- package/dist/commands/tasks/execution-timeline.js +2 -1
- package/dist/commands/tasks/fork.js +1 -0
- package/dist/commands/tasks/forward.js +4 -3
- package/dist/commands/tasks/handover.js +1 -0
- package/dist/commands/tasks/interrupt.js +3 -2
- package/dist/commands/tasks/labels/attach.js +4 -3
- package/dist/commands/tasks/labels/detach.js +4 -3
- package/dist/commands/tasks/labels/suggest.js +5 -4
- package/dist/commands/tasks/list.d.ts +27 -1
- package/dist/commands/tasks/list.js +101 -3
- package/dist/commands/tasks/move.js +4 -3
- package/dist/commands/tasks/output.js +6 -5
- package/dist/commands/tasks/pause-schedule.js +3 -2
- package/dist/commands/tasks/promote.js +1 -0
- package/dist/commands/tasks/prompt-log.js +2 -1
- package/dist/commands/tasks/release.js +5 -4
- package/dist/commands/tasks/remind.js +2 -1
- package/dist/commands/tasks/replay.js +3 -2
- package/dist/commands/tasks/report.js +1 -0
- package/dist/commands/tasks/resume-schedule.js +3 -2
- package/dist/commands/tasks/retry-schedule.js +3 -2
- package/dist/commands/tasks/retry.js +10 -9
- package/dist/commands/tasks/revisions.js +2 -1
- package/dist/commands/tasks/runs.js +6 -5
- package/dist/commands/tasks/schedule.js +3 -2
- package/dist/commands/tasks/self-schedule.js +6 -5
- package/dist/commands/tasks/skills/pin.js +3 -2
- package/dist/commands/tasks/skills/unpin.js +3 -2
- package/dist/commands/tasks/snooze.js +6 -5
- package/dist/commands/tasks/start-all.js +5 -4
- package/dist/commands/tasks/subscribe.js +1 -0
- package/dist/commands/tasks/tags/add.js +4 -3
- package/dist/commands/tasks/tags/remove.js +4 -3
- package/dist/commands/tasks/timeline.js +3 -2
- package/dist/commands/tasks/today.d.ts +4 -1
- package/dist/commands/tasks/today.js +12 -2
- package/dist/commands/tasks/transcript.js +6 -5
- package/dist/commands/tasks/unschedule.js +3 -2
- package/dist/commands/tasks/unsnooze.js +3 -2
- package/dist/commands/tasks/unsubscribe.js +2 -1
- package/dist/commands/tasks/update.js +5 -4
- package/dist/commands/tasks/wait.js +5 -4
- package/dist/lib/agent-distribution.d.ts +37 -0
- package/dist/lib/agent-distribution.js +63 -0
- package/dist/lib/agent-ref.d.ts +69 -0
- package/dist/lib/agent-ref.js +168 -0
- package/dist/lib/api-fetch.d.ts +2 -0
- package/dist/lib/api-fetch.js +14 -3
- package/dist/lib/command-hygiene.d.ts +13 -0
- package/dist/lib/command-hygiene.js +62 -2
- package/dist/lib/dedicated-power.d.ts +16 -1
- package/dist/lib/dedicated-power.js +153 -2
- package/dist/lib/dry-run-plans.d.ts +50 -0
- package/dist/lib/dry-run-plans.js +85 -0
- package/dist/lib/json-output.d.ts +31 -0
- package/dist/lib/json-output.js +78 -0
- package/dist/lib/list-output.d.ts +75 -0
- package/dist/lib/list-output.js +266 -0
- package/dist/lib/machine-daemon-log.d.ts +36 -0
- package/dist/lib/machine-daemon-log.js +78 -0
- package/dist/lib/node-adapter.js +10 -1
- package/dist/lib/open-target.d.ts +12 -0
- package/dist/lib/open-target.js +108 -0
- package/dist/lib/rate-limit-retry.d.ts +45 -0
- package/dist/lib/rate-limit-retry.js +88 -0
- package/dist/lib/store-listing.d.ts +45 -0
- package/dist/lib/store-listing.js +186 -0
- package/dist/lib/task-batch.d.ts +67 -0
- package/dist/lib/task-batch.js +227 -0
- package/dist/lib/terminal-qr.d.ts +55 -0
- package/dist/lib/terminal-qr.js +119 -0
- package/dist/lib/web-url.d.ts +11 -0
- package/dist/lib/web-url.js +24 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +68 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +47 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +68 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +46 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +6615 -6112
- package/oclif.manifest.json +41499 -32585
- package/package.json +2 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type ReleaseCapabilityManifestView, type StoreAgentInstallFunnelSummary, type StoreAgentReleaseAdoptionSummary, type StoreAgentReleaseOutcomes } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* Terminal wording for a Store listing (`skrr store show`) and its publisher
|
|
4
|
+
* readouts (`skrr store stats`). Pure functions, so the commands only fetch
|
|
5
|
+
* and print and every sentence here is pinned by a unit test.
|
|
6
|
+
*
|
|
7
|
+
* Two rules carried over from the web surfaces, because a terminal is not a
|
|
8
|
+
* licence to say less:
|
|
9
|
+
*
|
|
10
|
+
* - The capability manifest is a DISCLOSURE. Nothing narrows a run to it
|
|
11
|
+
* (see `client/src/components/Store/capabilityDisclosure.ts`), so no line
|
|
12
|
+
* here says an agent is limited, restricted or "can only" do something.
|
|
13
|
+
* `Unrestricted` is the one state word, and it names the BAD case.
|
|
14
|
+
* - A k-anonymous readout below its floor has NO figures. It is printed as
|
|
15
|
+
* "withheld" with the floor it missed, never as 0 — a zero is a claim that
|
|
16
|
+
* nobody did the thing, and the server did not make that claim.
|
|
17
|
+
*/
|
|
18
|
+
/** A listing's price in token credits (1,000,000 = $1), as the Store states it. */
|
|
19
|
+
export declare function formatListingPrice(price: number | null | undefined): string;
|
|
20
|
+
/** `4.6 ★ (12 ratings)`, or `No ratings yet` — never `0.0` for an unrated listing. */
|
|
21
|
+
export declare function formatListingRating(rating: number | null | undefined, count: number | null | undefined): string;
|
|
22
|
+
/**
|
|
23
|
+
* What the listed release is configured to use, as `label: value` pairs.
|
|
24
|
+
*
|
|
25
|
+
* `unavailable` stays its own answer — "we could not tell" — and is never
|
|
26
|
+
* rendered as an empty manifest, which would read as "uses nothing".
|
|
27
|
+
*/
|
|
28
|
+
export declare function capabilityDisclosureRows(view: ReleaseCapabilityManifestView | null | undefined): Array<[string, string]>;
|
|
29
|
+
/** One sentence that keeps the disclosure from being read as a sandbox. */
|
|
30
|
+
export declare const CAPABILITY_DISCLOSURE_FOOTNOTE = "Recorded by the platform when the release was created. A disclosure of its configuration \u2014 not a limit on what a run may do.";
|
|
31
|
+
/** Align `label: value` pairs under a section, indented two spaces. */
|
|
32
|
+
export declare function labelledLines(rows: ReadonlyArray<readonly [string, string]>): string[];
|
|
33
|
+
/** `withheld: fewer than 5 buyers in this window` — the floor, never a zero. */
|
|
34
|
+
export declare function withheldLine(minimumCohort: number, unit: string): string;
|
|
35
|
+
export declare function formatRate(value: number | null | undefined): string;
|
|
36
|
+
export declare function funnelWindowLine(summary: StoreAgentInstallFunnelSummary): string;
|
|
37
|
+
export declare function adoptionWindowLine(summary: StoreAgentReleaseAdoptionSummary): string;
|
|
38
|
+
export declare function outcomesWindowLine(outcomes: StoreAgentReleaseOutcomes): string;
|
|
39
|
+
/**
|
|
40
|
+
* Small cells that were withheld from an otherwise reported readout. Said
|
|
41
|
+
* once, with the floor, so a short table is not mistaken for a complete one.
|
|
42
|
+
*/
|
|
43
|
+
export declare function suppressedCellsLine(cells: Record<string, number>, minimumCohort: number, unit: string): string | null;
|
|
44
|
+
/** An exclusion count; `null` is "some, from too few buyers to say how many". */
|
|
45
|
+
export declare function exclusionValue(value: number | null | undefined): string;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CAPABILITY_DISCLOSURE_FOOTNOTE = void 0;
|
|
4
|
+
exports.formatListingPrice = formatListingPrice;
|
|
5
|
+
exports.formatListingRating = formatListingRating;
|
|
6
|
+
exports.capabilityDisclosureRows = capabilityDisclosureRows;
|
|
7
|
+
exports.labelledLines = labelledLines;
|
|
8
|
+
exports.withheldLine = withheldLine;
|
|
9
|
+
exports.formatRate = formatRate;
|
|
10
|
+
exports.funnelWindowLine = funnelWindowLine;
|
|
11
|
+
exports.adoptionWindowLine = adoptionWindowLine;
|
|
12
|
+
exports.outcomesWindowLine = outcomesWindowLine;
|
|
13
|
+
exports.suppressedCellsLine = suppressedCellsLine;
|
|
14
|
+
exports.exclusionValue = exclusionValue;
|
|
15
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
16
|
+
/**
|
|
17
|
+
* Terminal wording for a Store listing (`skrr store show`) and its publisher
|
|
18
|
+
* readouts (`skrr store stats`). Pure functions, so the commands only fetch
|
|
19
|
+
* and print and every sentence here is pinned by a unit test.
|
|
20
|
+
*
|
|
21
|
+
* Two rules carried over from the web surfaces, because a terminal is not a
|
|
22
|
+
* licence to say less:
|
|
23
|
+
*
|
|
24
|
+
* - The capability manifest is a DISCLOSURE. Nothing narrows a run to it
|
|
25
|
+
* (see `client/src/components/Store/capabilityDisclosure.ts`), so no line
|
|
26
|
+
* here says an agent is limited, restricted or "can only" do something.
|
|
27
|
+
* `Unrestricted` is the one state word, and it names the BAD case.
|
|
28
|
+
* - A k-anonymous readout below its floor has NO figures. It is printed as
|
|
29
|
+
* "withheld" with the floor it missed, never as 0 — a zero is a claim that
|
|
30
|
+
* nobody did the thing, and the server did not make that claim.
|
|
31
|
+
*/
|
|
32
|
+
/** A listing's price in token credits (1,000,000 = $1), as the Store states it. */
|
|
33
|
+
function formatListingPrice(price) {
|
|
34
|
+
return (0, data_provider_1.formatStoreAcquisitionPrice)(price);
|
|
35
|
+
}
|
|
36
|
+
/** `4.6 ★ (12 ratings)`, or `No ratings yet` — never `0.0` for an unrated listing. */
|
|
37
|
+
function formatListingRating(rating, count) {
|
|
38
|
+
const ratings = Number(count) || 0;
|
|
39
|
+
if (ratings <= 0)
|
|
40
|
+
return 'No ratings yet';
|
|
41
|
+
return `${(Number(rating) || 0).toFixed(1)} / 5 (${ratings} rating${ratings === 1 ? '' : 's'})`;
|
|
42
|
+
}
|
|
43
|
+
const UNAVAILABLE_REASON = {
|
|
44
|
+
not_recorded: 'no capability record was stored for this release',
|
|
45
|
+
digest_mismatch: 'the stored record describes a different configuration, so it is not shown',
|
|
46
|
+
no_release: 'the listing has no approved public release',
|
|
47
|
+
};
|
|
48
|
+
const SHARED_DATA = {
|
|
49
|
+
none: 'None — you start from a blank agent',
|
|
50
|
+
bootstrap: "The publisher's bootstrap files are offered with the agent",
|
|
51
|
+
memory: "The publisher's shared memories are offered with the agent",
|
|
52
|
+
full: "The publisher's bootstrap files and shared memories are offered with the agent",
|
|
53
|
+
};
|
|
54
|
+
function listOrNone(items, none = 'None named') {
|
|
55
|
+
return items.length > 0 ? items.join(', ') : none;
|
|
56
|
+
}
|
|
57
|
+
/** A permission dimension: a wildcard entry means it is not narrowed at all. */
|
|
58
|
+
function permissionValue(items) {
|
|
59
|
+
if (items.some(data_provider_1.isUnrestrictedCapabilityEntry)) {
|
|
60
|
+
const named = items.filter((entry) => !(0, data_provider_1.isUnrestrictedCapabilityEntry)(entry));
|
|
61
|
+
return named.length > 0 ? `Unrestricted (also names: ${named.join(', ')})` : 'Unrestricted';
|
|
62
|
+
}
|
|
63
|
+
return listOrNone(items);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* What the listed release is configured to use, as `label: value` pairs.
|
|
67
|
+
*
|
|
68
|
+
* `unavailable` stays its own answer — "we could not tell" — and is never
|
|
69
|
+
* rendered as an empty manifest, which would read as "uses nothing".
|
|
70
|
+
*/
|
|
71
|
+
function capabilityDisclosureRows(view) {
|
|
72
|
+
if (!view) {
|
|
73
|
+
return [['Disclosure', 'Not available — this server did not send one']];
|
|
74
|
+
}
|
|
75
|
+
if (view.status !== 'available') {
|
|
76
|
+
return [['Disclosure', `Not available — ${UNAVAILABLE_REASON[view.reason] ?? view.reason}`]];
|
|
77
|
+
}
|
|
78
|
+
const m = view.manifest;
|
|
79
|
+
const rows = [];
|
|
80
|
+
rows.push([
|
|
81
|
+
'Platform capabilities',
|
|
82
|
+
m.platformCapabilities.mode === 'unrestricted'
|
|
83
|
+
? 'Unrestricted — chosen per request'
|
|
84
|
+
: m.platformCapabilities.mode === 'not_loaded'
|
|
85
|
+
? 'Not loaded by its tool policy'
|
|
86
|
+
: listOrNone(m.platformCapabilities.capabilities),
|
|
87
|
+
]);
|
|
88
|
+
rows.push([
|
|
89
|
+
'Built-in tools',
|
|
90
|
+
m.builtinTools.mode === 'platform_default'
|
|
91
|
+
? 'Platform default set (includes a shell and web access)'
|
|
92
|
+
: m.builtinTools.mode === 'none'
|
|
93
|
+
? 'None'
|
|
94
|
+
: listOrNone(m.builtinTools.tools),
|
|
95
|
+
]);
|
|
96
|
+
rows.push(['Tools', permissionValue(m.permissionManifest.tools)]);
|
|
97
|
+
rows.push(['Connectors', permissionValue(m.permissionManifest.connectors)]);
|
|
98
|
+
rows.push(['Network', permissionValue(m.permissionManifest.networkDomains)]);
|
|
99
|
+
rows.push(['Data', permissionValue(m.permissionManifest.dataScopes)]);
|
|
100
|
+
rows.push(['Secrets', permissionValue(m.permissionManifest.secretNames)]);
|
|
101
|
+
const delegation = m.delegation;
|
|
102
|
+
let delegationValue;
|
|
103
|
+
switch (delegation.mode) {
|
|
104
|
+
case 'none':
|
|
105
|
+
delegationValue = 'None';
|
|
106
|
+
break;
|
|
107
|
+
case 'all':
|
|
108
|
+
delegationValue = 'Unrestricted — any agent in its network';
|
|
109
|
+
break;
|
|
110
|
+
case 'not_loaded':
|
|
111
|
+
delegationValue = 'Not loaded by its tool policy';
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
delegationValue = listOrNone(delegation.agentIds);
|
|
115
|
+
}
|
|
116
|
+
if (delegation.includesPublicAgents && delegation.mode !== 'none') {
|
|
117
|
+
delegationValue += ' (includes public agents)';
|
|
118
|
+
}
|
|
119
|
+
rows.push(['Delegates to', delegationValue]);
|
|
120
|
+
const model = [m.model.provider, m.model.model].filter(Boolean).join(' / ');
|
|
121
|
+
rows.push(['Model', model || 'Not stated']);
|
|
122
|
+
const autonomy = [];
|
|
123
|
+
if (m.proactive.enabled) {
|
|
124
|
+
const watches = [...m.proactive.sources, ...m.proactive.watchers];
|
|
125
|
+
autonomy.push(watches.length > 0
|
|
126
|
+
? `Acts on its own schedule after install (watches: ${watches.join(', ')})`
|
|
127
|
+
: 'Acts on its own schedule after install');
|
|
128
|
+
}
|
|
129
|
+
if (m.firstContact)
|
|
130
|
+
autonomy.push('Starts a conversation shortly after install');
|
|
131
|
+
rows.push(['Acts on its own', autonomy.length > 0 ? autonomy.join('; ') : 'No']);
|
|
132
|
+
rows.push(['Shared data', SHARED_DATA[m.sharedData] ?? m.sharedData]);
|
|
133
|
+
return rows;
|
|
134
|
+
}
|
|
135
|
+
/** One sentence that keeps the disclosure from being read as a sandbox. */
|
|
136
|
+
exports.CAPABILITY_DISCLOSURE_FOOTNOTE = 'Recorded by the platform when the release was created. A disclosure of its configuration — not a limit on what a run may do.';
|
|
137
|
+
/** Align `label: value` pairs under a section, indented two spaces. */
|
|
138
|
+
function labelledLines(rows) {
|
|
139
|
+
const width = Math.max(0, ...rows.map(([label]) => label.length)) + 1;
|
|
140
|
+
return rows.map(([label, value]) => ` ${`${label}:`.padEnd(width + 1)}${value}`);
|
|
141
|
+
}
|
|
142
|
+
// ─── Publisher readouts (`skrr store stats`) ────────────────────────────────
|
|
143
|
+
/** `withheld: fewer than 5 buyers in this window` — the floor, never a zero. */
|
|
144
|
+
function withheldLine(minimumCohort, unit) {
|
|
145
|
+
return `withheld: fewer than ${minimumCohort} ${unit} in this window, so no figures are shown`;
|
|
146
|
+
}
|
|
147
|
+
function formatRate(value) {
|
|
148
|
+
if (value === null || value === undefined || !Number.isFinite(Number(value)))
|
|
149
|
+
return '-';
|
|
150
|
+
return `${Math.round(Number(value) * 100)}%`;
|
|
151
|
+
}
|
|
152
|
+
function day(value) {
|
|
153
|
+
return value ? String(value).slice(0, 10) : '?';
|
|
154
|
+
}
|
|
155
|
+
function funnelWindowLine(summary) {
|
|
156
|
+
return `${summary.days}-day window, ${day(summary.since)} to ${day(summary.until)} (UTC, complete days)`;
|
|
157
|
+
}
|
|
158
|
+
function adoptionWindowLine(summary) {
|
|
159
|
+
return `copies acquired before ${day(summary.until)} (UTC)`;
|
|
160
|
+
}
|
|
161
|
+
function outcomesWindowLine(outcomes) {
|
|
162
|
+
return `${outcomes.windowDays}-day window, ${day(outcomes.since)} to ${day(outcomes.until)} (UTC)`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Small cells that were withheld from an otherwise reported readout. Said
|
|
166
|
+
* once, with the floor, so a short table is not mistaken for a complete one.
|
|
167
|
+
*/
|
|
168
|
+
function suppressedCellsLine(cells, minimumCohort, unit) {
|
|
169
|
+
const parts = Object.entries(cells)
|
|
170
|
+
.filter(([, count]) => Number(count) > 0)
|
|
171
|
+
.map(([name, count]) => `${count} ${humanize(name)}`);
|
|
172
|
+
if (parts.length === 0)
|
|
173
|
+
return null;
|
|
174
|
+
return `Withheld rows (fewer than ${minimumCohort} ${unit} each): ${parts.join(', ')}.`;
|
|
175
|
+
}
|
|
176
|
+
function humanize(key) {
|
|
177
|
+
return key.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase();
|
|
178
|
+
}
|
|
179
|
+
/** An exclusion count; `null` is "some, from too few buyers to say how many". */
|
|
180
|
+
function exclusionValue(value) {
|
|
181
|
+
if (value === null)
|
|
182
|
+
return 'some (too few buyers to count)';
|
|
183
|
+
if (value === undefined)
|
|
184
|
+
return '-';
|
|
185
|
+
return String(value);
|
|
186
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type TaskBatchItemResult, type TaskBatchPatchItem } from '@skrr-ai/data-provider';
|
|
2
|
+
export type ApiFailure = {
|
|
3
|
+
message: string;
|
|
4
|
+
status?: number;
|
|
5
|
+
code?: string;
|
|
6
|
+
retryable: boolean;
|
|
7
|
+
};
|
|
8
|
+
/** Normalize a thrown API error (or a per-item batch error) into one shape. */
|
|
9
|
+
export declare function describeApiFailure(err: unknown): ApiFailure;
|
|
10
|
+
/**
|
|
11
|
+
* A server that predates the batch routes answers 404 (no such POST route) or
|
|
12
|
+
* 405. A processed batch is ALWAYS a 200 (or 400/413/429 with a code), so a
|
|
13
|
+
* bare 404/405 on the batch call itself means "route missing", never "task
|
|
14
|
+
* not found".
|
|
15
|
+
*/
|
|
16
|
+
export declare function isBatchRouteMissing(err: unknown): boolean;
|
|
17
|
+
export declare function chunkItems<T>(items: T[], size?: number): T[][];
|
|
18
|
+
/**
|
|
19
|
+
* Same chunk, same key: a retry of an interrupted command replays the stored
|
|
20
|
+
* result instead of creating twice. The key is a fingerprint of the items, so a
|
|
21
|
+
* DIFFERENT chunk can never collide with it (the server answers 422 on a key
|
|
22
|
+
* reused with a different body).
|
|
23
|
+
*/
|
|
24
|
+
export declare function batchIdempotencyKey(kind: 'create' | 'patch', items: unknown[]): string;
|
|
25
|
+
export type BatchCreateNode = {
|
|
26
|
+
key: string;
|
|
27
|
+
parentKey?: string;
|
|
28
|
+
payload: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
export type BatchCreatedRow = {
|
|
31
|
+
key: string;
|
|
32
|
+
id: string;
|
|
33
|
+
identifier?: string;
|
|
34
|
+
/** `created` now, or `exists` when an earlier attempt already made it. */
|
|
35
|
+
status: 'created' | 'exists';
|
|
36
|
+
externalKey?: string;
|
|
37
|
+
};
|
|
38
|
+
export type BatchCreateFailure = {
|
|
39
|
+
key: string;
|
|
40
|
+
/** Not attempted because its parent was not created (or an earlier chunk failed). */
|
|
41
|
+
skipped: boolean;
|
|
42
|
+
error: ApiFailure;
|
|
43
|
+
};
|
|
44
|
+
export type BatchCreateOutcome = {
|
|
45
|
+
supported: false;
|
|
46
|
+
} | {
|
|
47
|
+
supported: true;
|
|
48
|
+
rows: BatchCreatedRow[];
|
|
49
|
+
failures: BatchCreateFailure[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Create `nodes` (parents before children) in chunks. `mapping` holds key -> id
|
|
53
|
+
* for nodes that already exist and is extended in place. Stops after the first
|
|
54
|
+
* chunk that reports a failure, as the serial path stopped at its first failure.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createNodesViaBatch(nodes: BatchCreateNode[], mapping: Record<string, string>): Promise<BatchCreateOutcome>;
|
|
57
|
+
export type BatchPatchOutcome = {
|
|
58
|
+
supported: false;
|
|
59
|
+
} | {
|
|
60
|
+
supported: true;
|
|
61
|
+
results: TaskBatchItemResult[];
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Apply `updates` in chunks; `results[i]` answers `updates[i]`. A chunk the
|
|
65
|
+
* server never processed is reported `skipped` for every row rather than lost.
|
|
66
|
+
*/
|
|
67
|
+
export declare function patchTasksViaBatch(updates: TaskBatchPatchItem[]): Promise<BatchPatchOutcome>;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeApiFailure = describeApiFailure;
|
|
4
|
+
exports.isBatchRouteMissing = isBatchRouteMissing;
|
|
5
|
+
exports.chunkItems = chunkItems;
|
|
6
|
+
exports.batchIdempotencyKey = batchIdempotencyKey;
|
|
7
|
+
exports.createNodesViaBatch = createNodesViaBatch;
|
|
8
|
+
exports.patchTasksViaBatch = patchTasksViaBatch;
|
|
9
|
+
/**
|
|
10
|
+
* Domain lib for `POST|PATCH /api/tasks/batch` (docs/architecture/task-batch-api-2026-10-08.md).
|
|
11
|
+
*
|
|
12
|
+
* `tasks create-tree` and `tasks bulk-update` reach the batch routes through
|
|
13
|
+
* `dataService.createTasksBatch|updateTasksBatch` and nothing else. This file owns
|
|
14
|
+
* the parts a command should not restate: chunking at the server cap, a
|
|
15
|
+
* deterministic idempotency key per chunk, tempId translation, and the "this
|
|
16
|
+
* server has no batch route" signal that sends a command back to its serial path.
|
|
17
|
+
*/
|
|
18
|
+
const node_crypto_1 = require("node:crypto");
|
|
19
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
20
|
+
/** Normalize a thrown API error (or a per-item batch error) into one shape. */
|
|
21
|
+
function describeApiFailure(err) {
|
|
22
|
+
const e = err;
|
|
23
|
+
let code = e.code;
|
|
24
|
+
let message = e.message ?? String(err);
|
|
25
|
+
if (e.body) {
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(e.body);
|
|
28
|
+
code = parsed.code ?? code;
|
|
29
|
+
message = parsed.message ?? parsed.error ?? message;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
/* non-JSON body */
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const status = e.status;
|
|
36
|
+
return {
|
|
37
|
+
message,
|
|
38
|
+
...(status ? { status } : {}),
|
|
39
|
+
...(code ? { code } : {}),
|
|
40
|
+
retryable: status === 408 || status === 425 || status === 429 || (status ?? 0) >= 500,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A server that predates the batch routes answers 404 (no such POST route) or
|
|
45
|
+
* 405. A processed batch is ALWAYS a 200 (or 400/413/429 with a code), so a
|
|
46
|
+
* bare 404/405 on the batch call itself means "route missing", never "task
|
|
47
|
+
* not found".
|
|
48
|
+
*/
|
|
49
|
+
function isBatchRouteMissing(err) {
|
|
50
|
+
const status = err?.status;
|
|
51
|
+
return status === 404 || status === 405;
|
|
52
|
+
}
|
|
53
|
+
function chunkItems(items, size = data_provider_1.TASK_BATCH_MAX_ITEMS ?? 100) {
|
|
54
|
+
const out = [];
|
|
55
|
+
for (let i = 0; i < items.length; i += size)
|
|
56
|
+
out.push(items.slice(i, i + size));
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Same chunk, same key: a retry of an interrupted command replays the stored
|
|
61
|
+
* result instead of creating twice. The key is a fingerprint of the items, so a
|
|
62
|
+
* DIFFERENT chunk can never collide with it (the server answers 422 on a key
|
|
63
|
+
* reused with a different body).
|
|
64
|
+
*/
|
|
65
|
+
function batchIdempotencyKey(kind, items) {
|
|
66
|
+
const digest = (0, node_crypto_1.createHash)('sha256').update((0, data_provider_1.stableJson)(items)).digest('hex').slice(0, 40);
|
|
67
|
+
return `cli-${kind}-batch:${digest}`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create `nodes` (parents before children) in chunks. `mapping` holds key -> id
|
|
71
|
+
* for nodes that already exist and is extended in place. Stops after the first
|
|
72
|
+
* chunk that reports a failure, as the serial path stopped at its first failure.
|
|
73
|
+
*/
|
|
74
|
+
async function createNodesViaBatch(nodes, mapping) {
|
|
75
|
+
const rows = [];
|
|
76
|
+
const failures = [];
|
|
77
|
+
for (const [chunkIndex, chunk] of chunkItems(nodes).entries()) {
|
|
78
|
+
const inChunk = new Map(chunk.map((node, i) => [node.key, `n${i}`]));
|
|
79
|
+
const items = [];
|
|
80
|
+
const sent = [];
|
|
81
|
+
for (const [i, node] of chunk.entries()) {
|
|
82
|
+
const { parentId: _ignored, ...payload } = node.payload;
|
|
83
|
+
const item = { ...payload, tempId: `n${i}` };
|
|
84
|
+
if (node.parentKey) {
|
|
85
|
+
const sameChunk = inChunk.get(node.parentKey);
|
|
86
|
+
if (sameChunk)
|
|
87
|
+
item.parentTempId = sameChunk;
|
|
88
|
+
else if (mapping[node.parentKey])
|
|
89
|
+
item.parentId = mapping[node.parentKey];
|
|
90
|
+
else {
|
|
91
|
+
failures.push({
|
|
92
|
+
key: node.key,
|
|
93
|
+
skipped: true,
|
|
94
|
+
error: {
|
|
95
|
+
message: `Parent "${node.parentKey}" was not created, so "${node.key}" was not attempted`,
|
|
96
|
+
code: 'BATCH_PARENT_NOT_CREATED',
|
|
97
|
+
retryable: false,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (node.payload.parentId) {
|
|
104
|
+
item.parentId = node.payload.parentId;
|
|
105
|
+
}
|
|
106
|
+
items.push(item);
|
|
107
|
+
sent.push(node);
|
|
108
|
+
}
|
|
109
|
+
if (items.length === 0)
|
|
110
|
+
break;
|
|
111
|
+
let response;
|
|
112
|
+
try {
|
|
113
|
+
response = await data_provider_1.dataService.createTasksBatch(items, {
|
|
114
|
+
idempotencyKey: batchIdempotencyKey('create', items),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
if (chunkIndex === 0 && isBatchRouteMissing(err))
|
|
119
|
+
return { supported: false };
|
|
120
|
+
failures.push({ key: sent[0].key, skipped: false, error: describeApiFailure(err) });
|
|
121
|
+
for (const node of sent.slice(1)) {
|
|
122
|
+
failures.push({
|
|
123
|
+
key: node.key,
|
|
124
|
+
skipped: true,
|
|
125
|
+
error: {
|
|
126
|
+
message: `Not attempted: the batch request containing "${sent[0].key}" failed`,
|
|
127
|
+
code: 'BATCH_NOT_ATTEMPTED',
|
|
128
|
+
retryable: true,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
let failed = false;
|
|
135
|
+
for (const [i, result] of response.results.entries()) {
|
|
136
|
+
const node = sent[i];
|
|
137
|
+
if (!node)
|
|
138
|
+
continue;
|
|
139
|
+
if (result.ok && result.id) {
|
|
140
|
+
mapping[node.key] = result.id;
|
|
141
|
+
rows.push({
|
|
142
|
+
key: node.key,
|
|
143
|
+
id: result.id,
|
|
144
|
+
...(result.identifier ? { identifier: result.identifier } : {}),
|
|
145
|
+
status: result.status === 'exists' ? 'exists' : 'created',
|
|
146
|
+
...(result.externalKey ? { externalKey: result.externalKey } : {}),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
failed = true;
|
|
151
|
+
failures.push({
|
|
152
|
+
key: node.key,
|
|
153
|
+
skipped: result.status === 'skipped',
|
|
154
|
+
error: result.error
|
|
155
|
+
? {
|
|
156
|
+
message: result.error.message,
|
|
157
|
+
status: result.error.status,
|
|
158
|
+
code: result.error.code,
|
|
159
|
+
retryable: result.error.retryable,
|
|
160
|
+
}
|
|
161
|
+
: { message: 'Task was not created', retryable: false },
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (failed)
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
return { supported: true, rows, failures };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Apply `updates` in chunks; `results[i]` answers `updates[i]`. A chunk the
|
|
172
|
+
* server never processed is reported `skipped` for every row rather than lost.
|
|
173
|
+
*/
|
|
174
|
+
async function patchTasksViaBatch(updates) {
|
|
175
|
+
const results = [];
|
|
176
|
+
let aborted = null;
|
|
177
|
+
let offset = 0;
|
|
178
|
+
for (const [chunkIndex, chunk] of chunkItems(updates).entries()) {
|
|
179
|
+
if (aborted) {
|
|
180
|
+
for (const [i, update] of chunk.entries()) {
|
|
181
|
+
results.push({
|
|
182
|
+
index: offset + i,
|
|
183
|
+
id: update.id,
|
|
184
|
+
ok: false,
|
|
185
|
+
status: 'skipped',
|
|
186
|
+
error: {
|
|
187
|
+
status: aborted.status ?? 0,
|
|
188
|
+
code: 'BATCH_NOT_ATTEMPTED',
|
|
189
|
+
message: 'Not attempted: an earlier batch request failed',
|
|
190
|
+
retryable: true,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
offset += chunk.length;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
const response = await data_provider_1.dataService.updateTasksBatch(chunk, {
|
|
199
|
+
idempotencyKey: batchIdempotencyKey('patch', chunk),
|
|
200
|
+
});
|
|
201
|
+
for (const [i, result] of response.results.entries()) {
|
|
202
|
+
results.push({ ...result, index: offset + i });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
if (chunkIndex === 0 && isBatchRouteMissing(err))
|
|
207
|
+
return { supported: false };
|
|
208
|
+
aborted = describeApiFailure(err);
|
|
209
|
+
for (const [i, update] of chunk.entries()) {
|
|
210
|
+
results.push({
|
|
211
|
+
index: offset + i,
|
|
212
|
+
id: update.id,
|
|
213
|
+
ok: false,
|
|
214
|
+
status: 'failed',
|
|
215
|
+
error: {
|
|
216
|
+
status: aborted.status ?? 0,
|
|
217
|
+
code: aborted.code ?? 'BATCH_REQUEST_FAILED',
|
|
218
|
+
message: aborted.message,
|
|
219
|
+
retryable: aborted.retryable,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
offset += chunk.length;
|
|
225
|
+
}
|
|
226
|
+
return { supported: true, results };
|
|
227
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A QR code a phone can scan off a terminal.
|
|
3
|
+
*
|
|
4
|
+
* The ENCODER is `qrcode-terminal`'s vendored QR model (the same zero-dependency
|
|
5
|
+
* package the daemon already ships for its login QR, pinned in the lockfile).
|
|
6
|
+
* Its own renderer is not used, because it is the part that decides whether a
|
|
7
|
+
* phone can read the result, and it gets two things wrong for that:
|
|
8
|
+
*
|
|
9
|
+
* - a ONE-module border. The QR spec asks for a four-module quiet zone, and a
|
|
10
|
+
* scanner looking at a terminal full of other text needs it most;
|
|
11
|
+
* - it paints light modules as `█` in the terminal's FOREGROUND colour, so on
|
|
12
|
+
* a light-themed terminal the code comes out inverted, which many scanners
|
|
13
|
+
* refuse.
|
|
14
|
+
*
|
|
15
|
+
* This renderer draws half-blocks (two modules per character row, so the code
|
|
16
|
+
* is square in a ~1:2 character cell) in EXPLICIT colours — black on bright
|
|
17
|
+
* white — so it scans the same on dark and light themes, with a full quiet zone.
|
|
18
|
+
*
|
|
19
|
+
* The QR is always a convenience printed beside the URL, never instead of it:
|
|
20
|
+
* `qrRenderDecision` says no for a pipe, `NO_COLOR`, `OVERSKY_NO_QR` / `SKRR_NO_QR`
|
|
21
|
+
* or a terminal too narrow to hold it, and the caller prints the URL alone.
|
|
22
|
+
*/
|
|
23
|
+
/** The spec's quiet zone, in modules. */
|
|
24
|
+
export declare const QR_QUIET_ZONE = 4;
|
|
25
|
+
/**
|
|
26
|
+
* The module matrix for `text`, quiet zone included. Level M: a share URL is
|
|
27
|
+
* well under 100 bytes, so the extra damage tolerance costs nothing in size.
|
|
28
|
+
*/
|
|
29
|
+
export declare function qrMatrix(text: string, level?: 'L' | 'M' | 'Q' | 'H'): boolean[][];
|
|
30
|
+
/**
|
|
31
|
+
* Render with half blocks: the upper half of each character is the top
|
|
32
|
+
* module (foreground, black), the lower half the bottom module (background,
|
|
33
|
+
* white). Returns the lines, each `matrix width` characters wide.
|
|
34
|
+
*/
|
|
35
|
+
export declare function renderQr(text: string): string[];
|
|
36
|
+
/** The QR's width in terminal columns (one column per module). */
|
|
37
|
+
export declare function qrWidth(text: string): number;
|
|
38
|
+
export type QrRenderDecision = {
|
|
39
|
+
render: true;
|
|
40
|
+
} | {
|
|
41
|
+
render: false;
|
|
42
|
+
reason: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Whether a QR for `text` can be drawn on `stream`. Default-deny when the
|
|
46
|
+
* stream does not say it is a TTY, so captured output never carries block
|
|
47
|
+
* glyphs or escape codes.
|
|
48
|
+
*/
|
|
49
|
+
export declare function qrRenderDecision(text: string, { env, stream, }?: {
|
|
50
|
+
env?: NodeJS.ProcessEnv;
|
|
51
|
+
stream?: {
|
|
52
|
+
isTTY?: boolean;
|
|
53
|
+
columns?: number;
|
|
54
|
+
};
|
|
55
|
+
}): QrRenderDecision;
|