@skrr-ai/cli 0.1.60 → 0.1.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.js +16 -0
- package/dist/commands/agents/create.d.ts +1 -0
- package/dist/commands/agents/create.js +8 -1
- package/dist/commands/agents/delete.d.ts +14 -0
- package/dist/commands/agents/delete.js +52 -4
- package/dist/commands/agents/eval/index.d.ts +38 -0
- package/dist/commands/agents/eval/index.js +157 -0
- package/dist/commands/agents/eval/list.d.ts +13 -0
- package/dist/commands/agents/eval/list.js +53 -0
- package/dist/commands/agents/eval/show.d.ts +13 -0
- package/dist/commands/agents/eval/show.js +36 -0
- package/dist/commands/agents/import.d.ts +37 -0
- package/dist/commands/agents/import.js +233 -0
- package/dist/commands/agents/pull.d.ts +27 -0
- package/dist/commands/agents/pull.js +82 -0
- package/dist/commands/agents/push.d.ts +28 -0
- package/dist/commands/agents/push.js +112 -0
- package/dist/commands/agents/releases/ci-publish.d.ts +32 -0
- package/dist/commands/agents/releases/ci-publish.js +99 -0
- package/dist/commands/agents/releases/create.d.ts +3 -0
- package/dist/commands/agents/releases/create.js +27 -6
- package/dist/commands/agents/releases/known-issues/add.d.ts +19 -0
- package/dist/commands/agents/releases/known-issues/add.js +43 -0
- package/dist/commands/agents/releases/known-issues/list.d.ts +17 -0
- package/dist/commands/agents/releases/known-issues/list.js +55 -0
- package/dist/commands/agents/releases/known-issues/update.d.ts +18 -0
- package/dist/commands/agents/releases/known-issues/update.js +47 -0
- package/dist/commands/agents/releases/list.js +25 -3
- package/dist/commands/agents/releases/rollback.js +12 -4
- package/dist/commands/agents/releases/test-install.d.ts +22 -0
- package/dist/commands/agents/releases/test-install.js +70 -0
- package/dist/commands/agents/releases/trusted-publishers/list.d.ts +17 -0
- package/dist/commands/agents/releases/trusted-publishers/list.js +55 -0
- package/dist/commands/agents/releases/trusted-publishers/remove.d.ts +17 -0
- package/dist/commands/agents/releases/trusted-publishers/remove.js +45 -0
- package/dist/commands/agents/releases/trusted-publishers/set.d.ts +27 -0
- package/dist/commands/agents/releases/trusted-publishers/set.js +82 -0
- package/dist/commands/agents/update.d.ts +1 -0
- package/dist/commands/agents/update.js +8 -1
- package/dist/commands/agents/usage-cap.d.ts +20 -0
- package/dist/commands/agents/usage-cap.js +76 -0
- package/dist/commands/agents/validate.d.ts +22 -0
- package/dist/commands/agents/validate.js +66 -0
- package/dist/commands/agents/visibility.d.ts +13 -0
- package/dist/commands/agents/visibility.js +84 -2
- package/dist/commands/commerce/fees/show.d.ts +19 -0
- package/dist/commands/commerce/fees/show.js +75 -0
- package/dist/commands/earnings/index.d.ts +15 -0
- package/dist/commands/earnings/index.js +46 -0
- package/dist/commands/earnings/payouts.d.ts +12 -0
- package/dist/commands/earnings/payouts.js +39 -0
- package/dist/commands/earnings/statements.d.ts +19 -0
- package/dist/commands/earnings/statements.js +70 -0
- package/dist/commands/goals/key-results/create.d.ts +1 -1
- package/dist/commands/goals/key-results/create.js +5 -1
- package/dist/commands/harnesses/show.js +11 -1
- package/dist/commands/logout.js +31 -0
- package/dist/commands/machines/show.js +10 -1
- package/dist/commands/managed-execution/show.d.ts +10 -0
- package/dist/commands/managed-execution/show.js +60 -0
- package/dist/commands/spaces/show.js +35 -1
- package/dist/commands/step-up.d.ts +23 -0
- package/dist/commands/step-up.js +96 -0
- package/dist/commands/store/acquisitions/approve.d.ts +30 -0
- package/dist/commands/store/acquisitions/approve.js +100 -0
- package/dist/commands/store/acquisitions/decline.d.ts +17 -0
- package/dist/commands/store/acquisitions/decline.js +47 -0
- package/dist/commands/store/acquisitions/show.d.ts +16 -0
- package/dist/commands/store/acquisitions/show.js +49 -0
- package/dist/commands/store/admissions/approve.d.ts +19 -0
- package/dist/commands/store/admissions/approve.js +50 -0
- package/dist/commands/store/admissions/list.d.ts +15 -0
- package/dist/commands/store/admissions/list.js +60 -0
- package/dist/commands/store/admissions/refuse.d.ts +18 -0
- package/dist/commands/store/admissions/refuse.js +49 -0
- package/dist/commands/store/advisories/artifact.d.ts +15 -0
- package/dist/commands/store/advisories/artifact.js +25 -0
- package/dist/commands/store/advisories/cancel.d.ts +13 -0
- package/dist/commands/store/advisories/cancel.js +34 -0
- package/dist/commands/store/advisories/close.d.ts +18 -0
- package/dist/commands/store/advisories/close.js +51 -0
- package/dist/commands/store/advisories/confirm.d.ts +17 -0
- package/dist/commands/store/advisories/confirm.js +40 -0
- package/dist/commands/store/advisories/issue.d.ts +20 -0
- package/dist/commands/store/advisories/issue.js +59 -0
- package/dist/commands/store/advisories/list.d.ts +15 -0
- package/dist/commands/store/advisories/list.js +49 -0
- package/dist/commands/store/advisories/show.d.ts +13 -0
- package/dist/commands/store/advisories/show.js +34 -0
- package/dist/commands/store/artifacts/release.d.ts +16 -0
- package/dist/commands/store/artifacts/release.js +31 -0
- package/dist/commands/store/artifacts/used-by.d.ts +12 -0
- package/dist/commands/store/artifacts/used-by.js +20 -0
- package/dist/commands/store/browse.d.ts +5 -0
- package/dist/commands/store/browse.js +28 -1
- package/dist/commands/store/channel.d.ts +21 -0
- package/dist/commands/store/channel.js +62 -0
- package/dist/commands/store/follow.d.ts +14 -0
- package/dist/commands/store/follow.js +45 -0
- package/dist/commands/store/governance/policy.d.ts +18 -5
- package/dist/commands/store/governance/policy.js +80 -12
- package/dist/commands/store/governance/requests.d.ts +28 -0
- package/dist/commands/store/governance/requests.js +116 -0
- package/dist/commands/store/install.d.ts +3 -0
- package/dist/commands/store/install.js +101 -2
- package/dist/commands/store/issues.d.ts +26 -0
- package/dist/commands/store/issues.js +118 -0
- package/dist/commands/store/maintainers/add.d.ts +13 -0
- package/dist/commands/store/maintainers/add.js +23 -0
- package/dist/commands/store/maintainers/remove.d.ts +13 -0
- package/dist/commands/store/maintainers/remove.js +22 -0
- package/dist/commands/store/publishers/approve.d.ts +11 -0
- package/dist/commands/store/publishers/approve.js +25 -0
- package/dist/commands/store/publishers/claim.d.ts +12 -0
- package/dist/commands/store/publishers/claim.js +20 -0
- package/dist/commands/store/publishers/confirm.d.ts +11 -0
- package/dist/commands/store/publishers/confirm.js +17 -0
- package/dist/commands/store/publishers/domains/begin.d.ts +12 -0
- package/dist/commands/store/publishers/domains/begin.js +20 -0
- package/dist/commands/store/publishers/domains/list.d.ts +9 -0
- package/dist/commands/store/publishers/domains/list.js +19 -0
- package/dist/commands/store/publishers/domains/verify.d.ts +12 -0
- package/dist/commands/store/publishers/domains/verify.js +20 -0
- package/dist/commands/store/publishers/namespaces.d.ts +8 -0
- package/dist/commands/store/publishers/namespaces.js +16 -0
- package/dist/commands/store/publishers/verified.d.ts +11 -0
- package/dist/commands/store/publishers/verified.js +34 -0
- package/dist/commands/store/refund.d.ts +22 -0
- package/dist/commands/store/refund.js +80 -0
- package/dist/commands/store/report.d.ts +20 -0
- package/dist/commands/store/report.js +59 -0
- package/dist/commands/store/reports.d.ts +11 -0
- package/dist/commands/store/reports.js +52 -0
- package/dist/commands/store/signals.d.ts +18 -0
- package/dist/commands/store/signals.js +43 -0
- package/dist/commands/store/star.d.ts +17 -0
- package/dist/commands/store/star.js +41 -0
- package/dist/commands/store/stars.d.ts +10 -0
- package/dist/commands/store/stars.js +33 -0
- package/dist/commands/store/trial.d.ts +11 -0
- package/dist/commands/store/trial.js +17 -0
- package/dist/commands/store/uninstall.d.ts +19 -0
- package/dist/commands/store/uninstall.js +118 -0
- package/dist/commands/store/update.d.ts +2 -0
- package/dist/commands/store/update.js +60 -2
- package/dist/commands/store/updates.d.ts +10 -4
- package/dist/commands/store/updates.js +60 -39
- package/dist/commands/store/watch.d.ts +18 -0
- package/dist/commands/store/watch.js +44 -0
- package/dist/commands/subscriptions/health.d.ts +12 -0
- package/dist/commands/subscriptions/health.js +39 -0
- package/dist/commands/subscriptions/list.js +3 -2
- package/dist/commands/subscriptions/status.js +7 -1
- package/dist/commands/subscriptions/subscribe.d.ts +9 -2
- package/dist/commands/subscriptions/subscribe.js +141 -12
- package/dist/commands/tasks/comments/list.js +9 -1
- package/dist/commands/tasks/labels/attach.js +15 -2
- package/dist/commands/tasks/show.js +17 -3
- package/dist/commands/tasks/update.js +15 -4
- package/dist/commands/tasks/updates/add.js +5 -1
- package/dist/lib/agent-config.js +1 -0
- package/dist/lib/agent-evals.d.ts +71 -0
- package/dist/lib/agent-evals.js +359 -0
- package/dist/lib/agent-spec.d.ts +28 -0
- package/dist/lib/agent-spec.js +58 -0
- package/dist/lib/auth-storage.d.ts +12 -0
- package/dist/lib/auth-storage.js +0 -33
- package/dist/lib/commerce.d.ts +8 -0
- package/dist/lib/commerce.js +10 -0
- package/dist/lib/earnings.d.ts +36 -0
- package/dist/lib/earnings.js +164 -0
- package/dist/lib/github-oidc.d.ts +13 -0
- package/dist/lib/github-oidc.js +41 -0
- package/dist/lib/governed-store.d.ts +43 -2
- package/dist/lib/governed-store.js +25 -1
- package/dist/lib/label-ref.js +16 -0
- package/dist/lib/managed-execution.d.ts +10 -0
- package/dist/lib/managed-execution.js +43 -0
- package/dist/lib/principal-display.d.ts +20 -0
- package/dist/lib/principal-display.js +64 -0
- package/dist/lib/space-template-source.d.ts +14 -0
- package/dist/lib/space-template-source.js +41 -0
- package/dist/lib/step-up.d.ts +21 -0
- package/dist/lib/step-up.js +44 -0
- package/dist/lib/store-acquisition.d.ts +11 -0
- package/dist/lib/store-acquisition.js +40 -0
- package/dist/lib/store-advisories.d.ts +50 -0
- package/dist/lib/store-advisories.js +62 -0
- package/dist/lib/task-closure.js +1 -1
- package/dist/lib/web-url.d.ts +11 -0
- package/dist/lib/web-url.js +14 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +25471 -24177
- package/oclif.manifest.json +38931 -34119
- package/package.json +21 -3
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `skrr agents eval` — the pure half (OSK-12303): reading a case file, choosing
|
|
4
|
+
* the release, and rendering what the platform reports back.
|
|
5
|
+
*
|
|
6
|
+
* The CLI never grades anything. It uploads the cases once, then asks the API
|
|
7
|
+
* to run each planned trial; the API executes, grades and prices every trial
|
|
8
|
+
* itself, so nothing printed here is a number the CLI computed from its own
|
|
9
|
+
* observations.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.EVAL_TRIAL_OBSERVE_LIMIT_MS = exports.EvalTrialFailedError = exports.EVAL_BASELINE_FLAG_VALUES = void 0;
|
|
46
|
+
exports.readEvalCases = readEvalCases;
|
|
47
|
+
exports.pickRelease = pickRelease;
|
|
48
|
+
exports.pendingTrials = pendingTrials;
|
|
49
|
+
exports.describeTrialLine = describeTrialLine;
|
|
50
|
+
exports.describeEvalHeader = describeEvalHeader;
|
|
51
|
+
exports.describeEvalReport = describeEvalReport;
|
|
52
|
+
exports.isTrialStillRunningError = isTrialStillRunningError;
|
|
53
|
+
exports.runEvalTrial = runEvalTrial;
|
|
54
|
+
const fs = __importStar(require("node:fs"));
|
|
55
|
+
const path = __importStar(require("node:path"));
|
|
56
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
57
|
+
const http_error_1 = require("./http-error");
|
|
58
|
+
/** CLI spelling → API spelling. */
|
|
59
|
+
exports.EVAL_BASELINE_FLAG_VALUES = {
|
|
60
|
+
'no-agent': 'no_agent',
|
|
61
|
+
'previous-release': 'previous_release',
|
|
62
|
+
};
|
|
63
|
+
function caseFromRaw(raw, where) {
|
|
64
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
65
|
+
throw new Error(`${where}: a case must be an object`);
|
|
66
|
+
}
|
|
67
|
+
const expected = raw.expected;
|
|
68
|
+
let assertions;
|
|
69
|
+
if (Array.isArray(raw.assertions))
|
|
70
|
+
assertions = raw.assertions;
|
|
71
|
+
else if (expected && Array.isArray(expected.assertions))
|
|
72
|
+
assertions = expected.assertions;
|
|
73
|
+
// Only what the server grades travels. A golden fixture's recorded output,
|
|
74
|
+
// judge scores and frozen agent config stay on this machine.
|
|
75
|
+
return {
|
|
76
|
+
id: raw.id,
|
|
77
|
+
prompt: raw.prompt,
|
|
78
|
+
assertions: (assertions ?? []),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function casesFromJson(value, where, fallbackId) {
|
|
82
|
+
if (Array.isArray(value))
|
|
83
|
+
return value.map((entry, i) => caseFromRaw(entry, `${where}[${i}]`));
|
|
84
|
+
if (value && typeof value === 'object') {
|
|
85
|
+
const record = value;
|
|
86
|
+
if (Array.isArray(record.cases)) {
|
|
87
|
+
return record.cases.map((entry, i) => caseFromRaw(entry, `${where} cases[${i}]`));
|
|
88
|
+
}
|
|
89
|
+
// One WS-1.6 golden fixture per file: its id defaults to the file name.
|
|
90
|
+
const single = caseFromRaw(record, where);
|
|
91
|
+
if (!single.id && fallbackId)
|
|
92
|
+
single.id = fallbackId;
|
|
93
|
+
return [single];
|
|
94
|
+
}
|
|
95
|
+
throw new Error(`${where}: expected a list of cases, {"cases": [...]}, or one case`);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read `--cases`: a JSON file (a list, `{cases: [...]}`, or one case) or a
|
|
99
|
+
* directory of such files, read in name order — so the repo's golden set
|
|
100
|
+
* directory is a valid argument as-is.
|
|
101
|
+
*/
|
|
102
|
+
function readEvalCases(casesPath) {
|
|
103
|
+
const resolved = path.resolve(casesPath);
|
|
104
|
+
const stat = fs.statSync(resolved);
|
|
105
|
+
const files = stat.isDirectory()
|
|
106
|
+
? fs
|
|
107
|
+
.readdirSync(resolved)
|
|
108
|
+
.filter((name) => name.endsWith('.json'))
|
|
109
|
+
.sort()
|
|
110
|
+
.map((name) => path.join(resolved, name))
|
|
111
|
+
: [resolved];
|
|
112
|
+
if (files.length === 0)
|
|
113
|
+
throw new Error(`${casesPath}: no .json case files found`);
|
|
114
|
+
const cases = files.flatMap((file) => {
|
|
115
|
+
let parsed;
|
|
116
|
+
try {
|
|
117
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
throw new Error(`${file}: not valid JSON (${error.message})`);
|
|
121
|
+
}
|
|
122
|
+
return casesFromJson(parsed, path.basename(file), path.basename(file, '.json'));
|
|
123
|
+
});
|
|
124
|
+
if (cases.length > data_provider_1.RELEASE_EVAL_LIMITS.maxCases) {
|
|
125
|
+
throw new Error(`${cases.length} cases found; an evaluation takes at most ${data_provider_1.RELEASE_EVAL_LIMITS.maxCases}`);
|
|
126
|
+
}
|
|
127
|
+
return cases;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* `--release`: an id, a version label (`1.2` or `v1.2`), or omitted for the
|
|
131
|
+
* newest release. Releases arrive newest first.
|
|
132
|
+
*/
|
|
133
|
+
function pickRelease(releases, wanted) {
|
|
134
|
+
if (!wanted) {
|
|
135
|
+
return [...releases].sort((a, b) => (b.releaseNumber ?? 0) - (a.releaseNumber ?? 0))[0];
|
|
136
|
+
}
|
|
137
|
+
const label = wanted.replace(/^v/i, '');
|
|
138
|
+
return releases.find((release) => release.id === wanted || release.versionLabel === label);
|
|
139
|
+
}
|
|
140
|
+
/** The planned trials that have no graded result yet, in run order. */
|
|
141
|
+
function pendingTrials(evaluation) {
|
|
142
|
+
const done = new Set((evaluation.trials ?? []).filter((t) => t.state === 'completed').map((t) => t.key));
|
|
143
|
+
return (0, data_provider_1.releaseEvalTrialPlan)({
|
|
144
|
+
cases: evaluation.cases,
|
|
145
|
+
trialsPerCase: evaluation.trialsPerCase,
|
|
146
|
+
}).filter((entry) => !done.has(entry.key));
|
|
147
|
+
}
|
|
148
|
+
function armLabel(evaluation, arm) {
|
|
149
|
+
return arm === 'candidate'
|
|
150
|
+
? `v${evaluation.versionLabel ?? '?'}`
|
|
151
|
+
: (0, data_provider_1.describeReleaseEvalBaseline)(evaluation.baseline);
|
|
152
|
+
}
|
|
153
|
+
function describeTrialLine(evaluation, trial, position, total, replayed = false) {
|
|
154
|
+
let verdict = 'RUNNING';
|
|
155
|
+
if (trial.state === 'completed')
|
|
156
|
+
verdict = trial.passed ? 'PASS' : 'FAIL';
|
|
157
|
+
const failed = (trial.assertions ?? []).filter((a) => !a.passed).map((a) => a.id);
|
|
158
|
+
return [
|
|
159
|
+
` [${position}/${total}]`,
|
|
160
|
+
armLabel(evaluation, trial.arm).padEnd(14),
|
|
161
|
+
`${trial.caseId} #${trial.trialIndex}`.padEnd(28),
|
|
162
|
+
verdict.padEnd(4),
|
|
163
|
+
(0, data_provider_1.formatReleaseEvalCostMicros)(trial.costMicros).padStart(9),
|
|
164
|
+
replayed ? '(already graded)' : '',
|
|
165
|
+
failed.length ? `failed: ${failed.join(', ')}` : '',
|
|
166
|
+
]
|
|
167
|
+
.filter(Boolean)
|
|
168
|
+
.join(' ');
|
|
169
|
+
}
|
|
170
|
+
function armRow(label, arm) {
|
|
171
|
+
const unpriced = arm.unpricedTrials ?? 0;
|
|
172
|
+
return [
|
|
173
|
+
` ${label.padEnd(18)}`,
|
|
174
|
+
`${(0, data_provider_1.formatReleaseEvalPassRate)(arm.passRate)} (${arm.passed}/${arm.trials})`.padEnd(16),
|
|
175
|
+
(0, data_provider_1.formatReleaseEvalCostMicros)(arm.meanCostMicros).padStart(10),
|
|
176
|
+
(0, data_provider_1.formatReleaseEvalCostMicros)(arm.totalCostMicros).padStart(12),
|
|
177
|
+
// An unpriced trial is left out of both cost figures, not priced at $0.
|
|
178
|
+
unpriced > 0 ? `(${unpriced} unpriced, not in cost)` : '',
|
|
179
|
+
]
|
|
180
|
+
.filter(Boolean)
|
|
181
|
+
.join(' ');
|
|
182
|
+
}
|
|
183
|
+
function describeEvalHeader(evaluation) {
|
|
184
|
+
const baseline = evaluation.baseline.kind === 'no_agent'
|
|
185
|
+
? `no agent — the default assistant on ${evaluation.baseline.model || 'the release model'}`
|
|
186
|
+
: (0, data_provider_1.describeReleaseEvalBaseline)(evaluation.baseline);
|
|
187
|
+
return [
|
|
188
|
+
`Evaluation ${evaluation.id}`,
|
|
189
|
+
` Release: v${evaluation.versionLabel ?? '?'} (${evaluation.releaseId})`,
|
|
190
|
+
` Baseline: ${baseline}`,
|
|
191
|
+
` Cases: ${evaluation.cases.length} × ${evaluation.trialsPerCase} trial(s) on each side`,
|
|
192
|
+
` Listed: ${evaluation.listed
|
|
193
|
+
? 'yes — shown on the store listing now, with a result once every trial is graded'
|
|
194
|
+
: 'no — visible only to you'}`,
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
/** The comparison, the per-case table, and the provenance lines. */
|
|
198
|
+
function describeEvalReport(evaluation) {
|
|
199
|
+
const { summary } = evaluation;
|
|
200
|
+
const provenance = (0, data_provider_1.describeReleaseEvalProvenance)(evaluation);
|
|
201
|
+
const lines = [
|
|
202
|
+
...describeEvalHeader(evaluation),
|
|
203
|
+
` Status: ${evaluation.status}${evaluation.status === 'running'
|
|
204
|
+
? ` — ${summary.recordedTrials} of ${summary.expectedTrials} trials graded`
|
|
205
|
+
: ''}`,
|
|
206
|
+
'',
|
|
207
|
+
` ${''.padEnd(18)} ${'pass rate'.padEnd(16)} ${'cost/run'.padStart(10)} ${'total cost'.padStart(12)}`,
|
|
208
|
+
armRow(armLabel(evaluation, 'candidate'), summary.candidate),
|
|
209
|
+
armRow(armLabel(evaluation, 'baseline'), summary.baseline),
|
|
210
|
+
` ${'delta'.padEnd(18)} ${summary.passRateDelta == null
|
|
211
|
+
? 'n/a'
|
|
212
|
+
: `${summary.passRateDelta >= 0 ? '+' : ''}${Math.round(summary.passRateDelta * 100)} pts`}`,
|
|
213
|
+
'',
|
|
214
|
+
' Per case (passed/trials):',
|
|
215
|
+
...summary.perCase.map((row) => ` ${row.caseId.padEnd(28)} ${armLabel(evaluation, 'candidate')} ${row.candidate.passed}/${row.candidate.trials} ${armLabel(evaluation, 'baseline')} ${row.baseline.passed}/${row.baseline.trials}`),
|
|
216
|
+
'',
|
|
217
|
+
` ${provenance.runner} · ${provenance.casesAuthor}`,
|
|
218
|
+
' Cost is model usage at the price billed to your account.',
|
|
219
|
+
];
|
|
220
|
+
if (evaluation.erroredAttempts > 0) {
|
|
221
|
+
lines.push(` ${evaluation.erroredAttempts} trial attempt(s) errored before a result (recorded on the evaluation).`);
|
|
222
|
+
}
|
|
223
|
+
return lines;
|
|
224
|
+
}
|
|
225
|
+
/** A trial that ended without a result; `message` is the server's reason. */
|
|
226
|
+
class EvalTrialFailedError extends Error {
|
|
227
|
+
key;
|
|
228
|
+
constructor(key, message) {
|
|
229
|
+
super(message);
|
|
230
|
+
this.key = key;
|
|
231
|
+
this.name = 'EvalTrialFailedError';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.EvalTrialFailedError = EvalTrialFailedError;
|
|
235
|
+
/** How long one trial is observed before the CLI gives up and says how to resume. */
|
|
236
|
+
exports.EVAL_TRIAL_OBSERVE_LIMIT_MS = 15 * 60 * 1000;
|
|
237
|
+
const OBSERVE_WAIT_MS = Math.min(20_000, data_provider_1.RELEASE_EVAL_OBSERVE_MAX_WAIT_MS);
|
|
238
|
+
const MAX_CONSECUTIVE_OBSERVE_ERRORS = 3;
|
|
239
|
+
/**
|
|
240
|
+
* Whether a failed START may still have started the trial, or found it
|
|
241
|
+
* running: an edge timeout or dropped connection (the request may have landed),
|
|
242
|
+
* or the server saying another run holds it. Either way the answer is to
|
|
243
|
+
* observe the trial, not to give up — or to start a second run.
|
|
244
|
+
*/
|
|
245
|
+
function isTrialStillRunningError(error) {
|
|
246
|
+
const status = (0, http_error_1.httpStatusOf)(error);
|
|
247
|
+
if (status === undefined)
|
|
248
|
+
return true;
|
|
249
|
+
if (status === 502 || status === 503 || status === 504)
|
|
250
|
+
return true;
|
|
251
|
+
return status === 409 && (0, http_error_1.httpBodyOf)(error)?.code === 'RELEASE_EVAL_TRIAL_IN_PROGRESS';
|
|
252
|
+
}
|
|
253
|
+
function attemptErrorCount(evaluation, key) {
|
|
254
|
+
return (evaluation?.attemptErrors ?? []).filter((entry) => entry.key === key).length;
|
|
255
|
+
}
|
|
256
|
+
function latestAttemptError(evaluation, key) {
|
|
257
|
+
const mine = (evaluation.attemptErrors ?? []).filter((entry) => entry.key === key);
|
|
258
|
+
return mine.length ? mine[mine.length - 1].message : undefined;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Run ONE planned trial to a graded result: start it, then observe it with
|
|
262
|
+
* bounded reads until it is graded. No request waits on the run itself.
|
|
263
|
+
*
|
|
264
|
+
* - A trial already graded comes back at once (`replayed`).
|
|
265
|
+
* - A start that fails in a way that may have started it (an edge 504, a
|
|
266
|
+
* dropped connection) or that finds it running elsewhere is observed.
|
|
267
|
+
* - A run that errors is recorded by the server; that reason is thrown as an
|
|
268
|
+
* `EvalTrialFailedError`, and a re-run is the caller's choice (`--resume`).
|
|
269
|
+
* - A claim whose run is gone (`stale`) is started again, which retakes it.
|
|
270
|
+
*/
|
|
271
|
+
async function runEvalTrial(client, entry) {
|
|
272
|
+
const sleep = client.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
273
|
+
const now = client.now ?? (() => Date.now());
|
|
274
|
+
const deadline = now() + exports.EVAL_TRIAL_OBSERVE_LIMIT_MS;
|
|
275
|
+
let started;
|
|
276
|
+
try {
|
|
277
|
+
started = await client.start(entry);
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
if (!isTrialStillRunningError(error))
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
if (started?.trial.state === 'completed') {
|
|
284
|
+
return { trial: started.trial, evaluation: started.evaluation, replayed: started.replayed };
|
|
285
|
+
}
|
|
286
|
+
// A failure recorded AFTER this point is this run's; one recorded before
|
|
287
|
+
// belongs to an earlier attempt.
|
|
288
|
+
let knownErrors = attemptErrorCount(started?.evaluation, entry.key);
|
|
289
|
+
let baselineKnown = started !== undefined;
|
|
290
|
+
let consecutiveErrors = 0;
|
|
291
|
+
let restartedLostStart = false;
|
|
292
|
+
while (now() < deadline) {
|
|
293
|
+
let evaluation;
|
|
294
|
+
try {
|
|
295
|
+
evaluation = await client.observe({ trial: entry.key, waitMs: OBSERVE_WAIT_MS });
|
|
296
|
+
consecutiveErrors = 0;
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
consecutiveErrors += 1;
|
|
300
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_OBSERVE_ERRORS)
|
|
301
|
+
throw error;
|
|
302
|
+
await sleep(2_000);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const trial = (evaluation.trials ?? []).find((t) => t.key === entry.key);
|
|
306
|
+
if (trial?.state === 'completed') {
|
|
307
|
+
return { trial, evaluation, replayed: false };
|
|
308
|
+
}
|
|
309
|
+
const errors = attemptErrorCount(evaluation, entry.key);
|
|
310
|
+
if (!baselineKnown) {
|
|
311
|
+
// The start's answer never arrived. If nothing holds the trial, the
|
|
312
|
+
// start never landed: start it once more rather than wait on nothing.
|
|
313
|
+
if (!trial && !restartedLostStart) {
|
|
314
|
+
restartedLostStart = true;
|
|
315
|
+
try {
|
|
316
|
+
const restarted = await client.start(entry);
|
|
317
|
+
if (restarted.trial.state === 'completed') {
|
|
318
|
+
return {
|
|
319
|
+
trial: restarted.trial,
|
|
320
|
+
evaluation: restarted.evaluation,
|
|
321
|
+
replayed: restarted.replayed,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
knownErrors = attemptErrorCount(restarted.evaluation, entry.key);
|
|
325
|
+
baselineKnown = true;
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
if (!isTrialStillRunningError(error))
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
knownErrors = errors;
|
|
334
|
+
baselineKnown = true;
|
|
335
|
+
}
|
|
336
|
+
if (errors > knownErrors || !trial) {
|
|
337
|
+
throw new EvalTrialFailedError(entry.key, latestAttemptError(evaluation, entry.key) ?? `Trial ${entry.key} did not produce a result`);
|
|
338
|
+
}
|
|
339
|
+
if (trial.stale) {
|
|
340
|
+
// The run behind the claim is gone; starting again retakes it.
|
|
341
|
+
try {
|
|
342
|
+
const retaken = await client.start(entry);
|
|
343
|
+
if (retaken.trial.state === 'completed') {
|
|
344
|
+
return {
|
|
345
|
+
trial: retaken.trial,
|
|
346
|
+
evaluation: retaken.evaluation,
|
|
347
|
+
replayed: retaken.replayed,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
knownErrors = attemptErrorCount(retaken.evaluation, entry.key);
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
if (!isTrialStillRunningError(error))
|
|
354
|
+
throw error;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
throw new EvalTrialFailedError(entry.key, `Trial ${entry.key} was still running after ${Math.round(exports.EVAL_TRIAL_OBSERVE_LIMIT_MS / 60_000)} minutes`);
|
|
359
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type AgentSpecDocument, type AgentSpecIssue, type AgentSpecValidation } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* Shared plumbing for `skrr agents pull | push | validate | import`.
|
|
4
|
+
*
|
|
5
|
+
* The rules themselves are not here — they live in `@skrr-ai/data-provider`
|
|
6
|
+
* (`agents/agentSpec`) and the server reads the same module, so an offline
|
|
7
|
+
* `validate` and a server-side push refusal cannot disagree about a field.
|
|
8
|
+
*/
|
|
9
|
+
/** Serialize a document the way `pull` writes it: stable, reviewable in a diff. */
|
|
10
|
+
export declare function serializeAgentSpecDocument(document: AgentSpecDocument): string;
|
|
11
|
+
/** Read a file, or stdin for `-`. */
|
|
12
|
+
export declare function readSpecSource(source: string): Promise<string>;
|
|
13
|
+
export type ParsedSpecSource = {
|
|
14
|
+
ok: true;
|
|
15
|
+
validation: AgentSpecValidation;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
message: string;
|
|
19
|
+
};
|
|
20
|
+
/** Parse JSON text and validate it as an agent spec document, with no network. */
|
|
21
|
+
export declare function parseAndValidateAgentSpec(raw: string, source: string): ParsedSpecSource;
|
|
22
|
+
/** The issue list a server refusal carried, when it carried one. */
|
|
23
|
+
export declare function refusalIssues(err: unknown): {
|
|
24
|
+
code?: string;
|
|
25
|
+
issues: AgentSpecIssue[];
|
|
26
|
+
} | null;
|
|
27
|
+
/** Issue lines indented under a heading, for a terminal. */
|
|
28
|
+
export declare function issueBlock(heading: string, issues: readonly AgentSpecIssue[]): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serializeAgentSpecDocument = serializeAgentSpecDocument;
|
|
4
|
+
exports.readSpecSource = readSpecSource;
|
|
5
|
+
exports.parseAndValidateAgentSpec = parseAndValidateAgentSpec;
|
|
6
|
+
exports.refusalIssues = refusalIssues;
|
|
7
|
+
exports.issueBlock = issueBlock;
|
|
8
|
+
const promises_1 = require("node:fs/promises");
|
|
9
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
10
|
+
const prompt_1 = require("./prompt");
|
|
11
|
+
/**
|
|
12
|
+
* Shared plumbing for `skrr agents pull | push | validate | import`.
|
|
13
|
+
*
|
|
14
|
+
* The rules themselves are not here — they live in `@skrr-ai/data-provider`
|
|
15
|
+
* (`agents/agentSpec`) and the server reads the same module, so an offline
|
|
16
|
+
* `validate` and a server-side push refusal cannot disagree about a field.
|
|
17
|
+
*/
|
|
18
|
+
/** Serialize a document the way `pull` writes it: stable, reviewable in a diff. */
|
|
19
|
+
function serializeAgentSpecDocument(document) {
|
|
20
|
+
return `${JSON.stringify(document, null, 2)}\n`;
|
|
21
|
+
}
|
|
22
|
+
/** Read a file, or stdin for `-`. */
|
|
23
|
+
async function readSpecSource(source) {
|
|
24
|
+
return source === '-' ? (0, prompt_1.readStdin)() : (0, promises_1.readFile)(source, 'utf8');
|
|
25
|
+
}
|
|
26
|
+
/** Parse JSON text and validate it as an agent spec document, with no network. */
|
|
27
|
+
function parseAndValidateAgentSpec(raw, source) {
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = JSON.parse(raw);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
return { ok: false, message: `${source} is not valid JSON: ${err.message}` };
|
|
34
|
+
}
|
|
35
|
+
return { ok: true, validation: (0, data_provider_1.validateAgentSpecDocument)(parsed) };
|
|
36
|
+
}
|
|
37
|
+
/** The issue list a server refusal carried, when it carried one. */
|
|
38
|
+
function refusalIssues(err) {
|
|
39
|
+
const body = err?.body;
|
|
40
|
+
if (typeof body !== 'string')
|
|
41
|
+
return null;
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(body);
|
|
44
|
+
if (!Array.isArray(parsed.issues))
|
|
45
|
+
return null;
|
|
46
|
+
return {
|
|
47
|
+
code: typeof parsed.code === 'string' ? parsed.code : undefined,
|
|
48
|
+
issues: parsed.issues,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Issue lines indented under a heading, for a terminal. */
|
|
56
|
+
function issueBlock(heading, issues) {
|
|
57
|
+
return [heading, ...(0, data_provider_1.formatAgentSpecIssues)(issues).map((line) => ` - ${line}`)].join('\n');
|
|
58
|
+
}
|
|
@@ -113,6 +113,18 @@ export declare function readFromBackend(expectedServerOrigin?: string): ReadResu
|
|
|
113
113
|
* that explain an absent sign-in (BaseCommand, `skrr doctor`).
|
|
114
114
|
*/
|
|
115
115
|
export declare function describeForeignCredential(result: ReadResult): string | null;
|
|
116
|
+
/**
|
|
117
|
+
* Persist a token bundle to the preferred backend.
|
|
118
|
+
*
|
|
119
|
+
* Writes to keychain when available, file otherwise. If keychain writes
|
|
120
|
+
* fail mid-flight (e.g., user canceled the unlock prompt), we fall back
|
|
121
|
+
* to the file backend so the CLI remains functional.
|
|
122
|
+
*
|
|
123
|
+
* Returns the backend that actually accepted the write. Callers wanting
|
|
124
|
+
* a specific backend (bare mode, store-mode overrides) should call the
|
|
125
|
+
* lower-level write helpers directly — not exported here to keep the
|
|
126
|
+
* default path honest.
|
|
127
|
+
*/
|
|
116
128
|
export declare function writeToBackend(bundle: AuthBundle, options?: WriteOptions): AuthBackend;
|
|
117
129
|
/**
|
|
118
130
|
* Clear both backends. Called on `skrr logout` (and internally during
|
package/dist/lib/auth-storage.js
CHANGED
|
@@ -760,37 +760,6 @@ function describeForeignCredential(result) {
|
|
|
760
760
|
* lower-level write helpers directly — not exported here to keep the
|
|
761
761
|
* default path honest.
|
|
762
762
|
*/
|
|
763
|
-
/**
|
|
764
|
-
* Clear the DAEMON's needs-reauth latch as well as the CLI's own.
|
|
765
|
-
*
|
|
766
|
-
* `clearReauthState()` resolves `getAuthConfigDir()`, and the two binaries wire
|
|
767
|
-
* that differently: the CLI points auth-core at the machine root (`~/.skrr`),
|
|
768
|
-
* the daemon at its PROFILE dir (`~/.skrr/profiles/<profile>`). So the daemon
|
|
769
|
-
* latched at one path while `skrr login` cleared another — a file that on most
|
|
770
|
-
* machines does not exist at all, which made the clear a silent no-op.
|
|
771
|
-
*
|
|
772
|
-
* The visible cost was a loop with no exit: `skrr daemon status` reported
|
|
773
|
-
* "Cause: TOKEN_INVALID · Remedy: run `skrr login`", the login succeeded, and
|
|
774
|
-
* the flag never moved, so the daemon's realtime channel stayed down and it
|
|
775
|
-
* could not execute tasks. `auth-core-init.ts` states the intent — "share the
|
|
776
|
-
* daemon's config root so auth.lock and the needs-reauth flag are coordinated
|
|
777
|
-
* across binaries" — which stopped being true when the daemon became
|
|
778
|
-
* profile-scoped.
|
|
779
|
-
*
|
|
780
|
-
* The ACTIVE profile only, deliberately: a per-profile latch is correct because
|
|
781
|
-
* different profiles can hold different credentials, and a login re-authorises
|
|
782
|
-
* exactly the one it just wrote.
|
|
783
|
-
*/
|
|
784
|
-
function clearDaemonProfileReauthState() {
|
|
785
|
-
try {
|
|
786
|
-
const target = path.join(os.homedir(), '.skrr', 'profiles', keychain.getActiveProfile(), 'needs-reauth.json');
|
|
787
|
-
fs.rmSync(target, { force: true });
|
|
788
|
-
}
|
|
789
|
-
catch {
|
|
790
|
-
// Best effort: the CLI's own latch is already cleared, and failing to
|
|
791
|
-
// remove the daemon's must not fail a login that otherwise succeeded.
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
763
|
function writeToBackend(bundle, options = {}) {
|
|
795
764
|
const requestedOrigin = options.serverOrigin ?? bundle.serverOrigin;
|
|
796
765
|
let persistedBundle = bundle;
|
|
@@ -822,7 +791,6 @@ function writeToBackend(bundle, options = {}) {
|
|
|
822
791
|
backend = 'keychain';
|
|
823
792
|
if (options.clearReauth) {
|
|
824
793
|
(0, auth_core_1.clearReauthState)();
|
|
825
|
-
clearDaemonProfileReauthState();
|
|
826
794
|
}
|
|
827
795
|
return backend;
|
|
828
796
|
}
|
|
@@ -837,7 +805,6 @@ function writeToBackend(bundle, options = {}) {
|
|
|
837
805
|
backend = 'file';
|
|
838
806
|
if (options.clearReauth) {
|
|
839
807
|
(0, auth_core_1.clearReauthState)();
|
|
840
|
-
clearDaemonProfileReauthState();
|
|
841
808
|
}
|
|
842
809
|
return backend;
|
|
843
810
|
}
|
package/dist/lib/commerce.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TMarketplaceFeeSchedule } from '@skrr-ai/data-provider';
|
|
1
2
|
/**
|
|
2
3
|
* `/api/commerce` — marketplace terms, the offer governance pipeline, trials,
|
|
3
4
|
* promotions, and the incident queue behind fulfillment and integrity.
|
|
@@ -38,6 +39,13 @@ export declare function getMarketplaceTerms(scope: MarketplaceTermsScope): Promi
|
|
|
38
39
|
* may default, because the whole value of the receipt is that somebody said so.
|
|
39
40
|
*/
|
|
40
41
|
export declare function acceptMarketplaceTerms(scope: MarketplaceTermsScope): Promise<unknown>;
|
|
42
|
+
/**
|
|
43
|
+
* `GET /marketplace/fee-schedule` — the seller share, hold and payout minimum
|
|
44
|
+
* every surface quotes, under the publisher terms in force (OSK-12271). The
|
|
45
|
+
* shape is `@skrr-ai/data-provider`'s, the one the web client reads too.
|
|
46
|
+
* `version` names a past schedule version for audit reads (OSK-12539).
|
|
47
|
+
*/
|
|
48
|
+
export declare function getMarketplaceFeeSchedule(version?: string): Promise<TMarketplaceFeeSchedule>;
|
|
41
49
|
/** `GET /admin/marketplace/incidents/:kind` — the queue. */
|
|
42
50
|
export declare function listMarketplaceIncidents(kind: string, params?: {
|
|
43
51
|
status?: string;
|
package/dist/lib/commerce.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getMarketplaceTerms = getMarketplaceTerms;
|
|
4
4
|
exports.acceptMarketplaceTerms = acceptMarketplaceTerms;
|
|
5
|
+
exports.getMarketplaceFeeSchedule = getMarketplaceFeeSchedule;
|
|
5
6
|
exports.listMarketplaceIncidents = listMarketplaceIncidents;
|
|
6
7
|
exports.getMarketplaceIncident = getMarketplaceIncident;
|
|
7
8
|
exports.listMarketplaceIncidentAudit = listMarketplaceIncidentAudit;
|
|
@@ -44,6 +45,15 @@ async function acceptMarketplaceTerms(scope) {
|
|
|
44
45
|
body: { scope, accepted: true },
|
|
45
46
|
});
|
|
46
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* `GET /marketplace/fee-schedule` — the seller share, hold and payout minimum
|
|
50
|
+
* every surface quotes, under the publisher terms in force (OSK-12271). The
|
|
51
|
+
* shape is `@skrr-ai/data-provider`'s, the one the web client reads too.
|
|
52
|
+
* `version` names a past schedule version for audit reads (OSK-12539).
|
|
53
|
+
*/
|
|
54
|
+
async function getMarketplaceFeeSchedule(version) {
|
|
55
|
+
return (0, api_fetch_1.apiFetch)((0, triggers_1.withQuery)('/api/commerce/marketplace/fee-schedule', { version }));
|
|
56
|
+
}
|
|
47
57
|
/** `GET /admin/marketplace/incidents/:kind` — the queue. */
|
|
48
58
|
async function listMarketplaceIncidents(kind, params = {}) {
|
|
49
59
|
return (0, api_fetch_1.apiFetch)((0, triggers_1.withQuery)(`/api/commerce/admin/marketplace/incidents/${encodeURIComponent(kind)}`, params));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type TConnectAutoPayout, type TConnectEarnings, type TConnectPayoutHistoryResponse, type TConnectStatement, type TConnectStatementsResponse } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* earnings.ts — the read-only publisher payout surface (OSK-12272).
|
|
4
|
+
*
|
|
5
|
+
* `skrr earnings` reads a publisher's balance, automatic-payout state, monthly
|
|
6
|
+
* statements and payout history from `/api/connect/*`. It is read-only on
|
|
7
|
+
* purpose: requesting a payout and switching automatic payouts on move money,
|
|
8
|
+
* and those routes refuse a daemon credential (`refuseDaemonScope`), so they
|
|
9
|
+
* stay in the web Earnings page where a signed-in person does them.
|
|
10
|
+
*
|
|
11
|
+
* Every read goes through `dataService`, so the path a command reaches is the
|
|
12
|
+
* same one the web page reads, and copy for server vocabularies comes from
|
|
13
|
+
* `@skrr-ai/data-provider` (`connectPayouts.ts`), shared with that page.
|
|
14
|
+
*/
|
|
15
|
+
export declare const readEarnings: () => Promise<TConnectEarnings>;
|
|
16
|
+
export declare const readAutoPayout: () => Promise<TConnectAutoPayout>;
|
|
17
|
+
export declare const readStatements: (params: {
|
|
18
|
+
limit?: number;
|
|
19
|
+
cursor?: string;
|
|
20
|
+
}) => Promise<TConnectStatementsResponse>;
|
|
21
|
+
export declare const readStatement: (period: string) => Promise<TConnectStatement>;
|
|
22
|
+
export declare const readPayouts: (params: {
|
|
23
|
+
limit?: number;
|
|
24
|
+
cursor?: string;
|
|
25
|
+
}) => Promise<TConnectPayoutHistoryResponse>;
|
|
26
|
+
export declare const PERIOD_PATTERN: RegExp;
|
|
27
|
+
type Log = (line: string) => void;
|
|
28
|
+
/** `skrr earnings`: the balance, then how and when it is paid out. */
|
|
29
|
+
export declare function renderEarningsSummary(earnings: TConnectEarnings, autoPayout: TConnectAutoPayout | null, log: Log): void;
|
|
30
|
+
/** `skrr earnings statements`: one row per month, newest first. */
|
|
31
|
+
export declare function renderStatementList(result: TConnectStatementsResponse, log: Log): void;
|
|
32
|
+
/** `skrr earnings statements <YYYY-MM>`: the whole statement, opening to closing. */
|
|
33
|
+
export declare function renderStatement(statement: TConnectStatement, log: Log): void;
|
|
34
|
+
/** `skrr earnings payouts`: the payout ledger, newest first. */
|
|
35
|
+
export declare function renderPayoutHistory(result: TConnectPayoutHistoryResponse, log: Log): void;
|
|
36
|
+
export {};
|