@skrr-ai/cli 0.1.37 → 0.1.38
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/bin/dev-fallback.js +167 -4
- package/dist/base-command.js +46 -2
- package/dist/commands/agents/actions/create.js +18 -7
- package/dist/commands/agents/actions/delete.d.ts +1 -0
- package/dist/commands/agents/actions/delete.js +7 -0
- package/dist/commands/agents/actions/update.js +5 -3
- package/dist/commands/agents/api-actions/add.js +5 -2
- package/dist/commands/agents/api-actions/index.d.ts +11 -0
- package/dist/commands/agents/api-actions/index.js +27 -1
- package/dist/commands/agents/avatar/default/index.d.ts +11 -0
- package/dist/commands/agents/avatar/default/index.js +17 -0
- package/dist/commands/agents/avatar/default/set.d.ts +2 -1
- package/dist/commands/agents/avatar/default/set.js +32 -7
- package/dist/commands/agents/avatar/upload.js +7 -1
- package/dist/commands/agents/categories/delete.js +8 -0
- package/dist/commands/agents/categories/index.d.ts +21 -5
- package/dist/commands/agents/categories/index.js +68 -15
- package/dist/commands/agents/chat.d.ts +21 -0
- package/dist/commands/agents/chat.js +94 -7
- package/dist/commands/agents/create.js +11 -4
- package/dist/commands/agents/list.d.ts +15 -0
- package/dist/commands/agents/list.js +31 -1
- package/dist/commands/agents/scene-background/upload.d.ts +30 -0
- package/dist/commands/agents/scene-background/upload.js +97 -0
- package/dist/commands/agents/show.js +13 -0
- package/dist/commands/agents/tools/calls.d.ts +23 -5
- package/dist/commands/agents/tools/calls.js +81 -18
- package/dist/commands/agents/update.js +15 -5
- package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
- package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
- package/dist/commands/convos/messages.d.ts +13 -0
- package/dist/commands/convos/messages.js +40 -16
- package/dist/commands/daemon/index.js +8 -1
- package/dist/commands/daemon/logs.d.ts +26 -0
- package/dist/commands/daemon/logs.js +56 -0
- package/dist/commands/daemon/uninstall.js +1 -1
- package/dist/commands/followups/act.js +3 -2
- package/dist/commands/followups/cancel.d.ts +6 -3
- package/dist/commands/followups/cancel.js +16 -6
- package/dist/commands/followups/observability.d.ts +23 -0
- package/dist/commands/followups/observability.js +114 -0
- package/dist/commands/followups/reschedule.js +1 -1
- package/dist/commands/followups/resolve.js +3 -3
- package/dist/commands/followups/show.js +2 -1
- package/dist/commands/followups/watch.js +9 -5
- package/dist/commands/harnesses/forget.js +28 -0
- package/dist/commands/harnesses/install.d.ts +41 -0
- package/dist/commands/harnesses/install.js +165 -0
- package/dist/commands/harnesses/installers.d.ts +45 -0
- package/dist/commands/harnesses/installers.js +155 -0
- package/dist/commands/harnesses/list.d.ts +82 -1
- package/dist/commands/harnesses/list.js +104 -12
- package/dist/commands/harnesses/models.js +10 -1
- package/dist/commands/harnesses/show.d.ts +15 -0
- package/dist/commands/harnesses/show.js +44 -3
- package/dist/commands/harnesses/update.js +1 -1
- package/dist/commands/harnesses/usage.d.ts +25 -0
- package/dist/commands/harnesses/usage.js +24 -2
- package/dist/commands/instructions/status.js +13 -1
- package/dist/commands/machines/dedicated/catalog.js +4 -15
- package/dist/commands/machines/dedicated/create.d.ts +8 -0
- package/dist/commands/machines/dedicated/create.js +58 -1
- package/dist/commands/machines/dedicated/destroy.js +18 -4
- package/dist/commands/machines/dedicated/list.js +9 -6
- package/dist/commands/machines/hosted/list.js +12 -0
- package/dist/commands/machines/list.js +11 -0
- package/dist/commands/machines/show.d.ts +1 -0
- package/dist/commands/machines/show.js +40 -11
- package/dist/commands/profiles/list.d.ts +23 -0
- package/dist/commands/profiles/list.js +96 -0
- package/dist/commands/search/skills.d.ts +11 -1
- package/dist/commands/search/skills.js +26 -8
- package/dist/commands/skills/details.d.ts +2 -0
- package/dist/commands/skills/details.js +24 -1
- package/dist/commands/skills/import-as-actions.d.ts +32 -0
- package/dist/commands/skills/import-as-actions.js +175 -0
- package/dist/commands/skills/install.d.ts +2 -0
- package/dist/commands/skills/install.js +24 -1
- package/dist/commands/skills/invocable.js +6 -2
- package/dist/commands/skills/local.d.ts +40 -0
- package/dist/commands/skills/local.js +160 -0
- package/dist/commands/skills/search.d.ts +11 -1
- package/dist/commands/skills/search.js +29 -8
- package/dist/commands/spaces/actions/add.js +23 -5
- package/dist/commands/spaces/actions/available.js +3 -0
- package/dist/commands/spaces/actions/list.d.ts +5 -0
- package/dist/commands/spaces/actions/list.js +49 -3
- package/dist/commands/spaces/actions/run.d.ts +28 -0
- package/dist/commands/spaces/actions/run.js +146 -0
- package/dist/commands/spaces/actions/update.js +27 -5
- package/dist/commands/spaces/label-summaries.d.ts +27 -0
- package/dist/commands/spaces/label-summaries.js +64 -0
- package/dist/commands/spaces/task-rollups.d.ts +5 -0
- package/dist/commands/spaces/task-rollups.js +15 -4
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +63 -3
- package/dist/commands/tasks/actions/attach.js +32 -7
- package/dist/commands/tasks/complete.js +13 -0
- package/dist/commands/tasks/create.js +1 -1
- package/dist/commands/tasks/events/append.js +29 -6
- package/dist/commands/tasks/expectations/assess.d.ts +1 -0
- package/dist/commands/tasks/expectations/assess.js +43 -5
- package/dist/commands/tasks/expectations.js +77 -16
- package/dist/commands/tasks/follow-up.js +2 -2
- package/dist/commands/tasks/lifecycle/definitions.js +21 -2
- package/dist/commands/tasks/lifecycle/detach.d.ts +7 -0
- package/dist/commands/tasks/lifecycle/detach.js +43 -3
- package/dist/commands/tasks/lifecycle/migrate.d.ts +2 -0
- package/dist/commands/tasks/lifecycle/migrate.js +42 -3
- package/dist/commands/tasks/lifecycle/reopen.d.ts +2 -0
- package/dist/commands/tasks/lifecycle/reopen.js +40 -3
- package/dist/commands/tasks/lifecycle/transition.js +33 -2
- package/dist/commands/tasks/list.js +16 -9
- package/dist/commands/tasks/move.js +11 -13
- package/dist/commands/tasks/review-queue.d.ts +15 -0
- package/dist/commands/tasks/review-queue.js +180 -31
- package/dist/commands/tasks/show.d.ts +11 -0
- package/dist/commands/tasks/show.js +105 -12
- package/dist/commands/tasks/trust.js +7 -2
- package/dist/commands/tasks/update.js +46 -10
- package/dist/commands/tasks/updates/add.js +1 -1
- package/dist/commands/token/list.d.ts +22 -0
- package/dist/commands/token/list.js +68 -0
- package/dist/commands/token/revoke.d.ts +23 -0
- package/dist/commands/token/revoke.js +53 -0
- package/dist/lib/agent-actions.d.ts +57 -2
- package/dist/lib/agent-actions.js +113 -21
- package/dist/lib/agent-pin-mute.d.ts +10 -5
- package/dist/lib/agent-pin-mute.js +17 -4
- package/dist/lib/agent-visual-refs.d.ts +27 -0
- package/dist/lib/agent-visual-refs.js +127 -2
- package/dist/lib/agentic-stream.d.ts +6 -0
- package/dist/lib/agentic-stream.js +34 -3
- package/dist/lib/assignee-resolver.d.ts +1 -1
- package/dist/lib/assignee-resolver.js +8 -0
- package/dist/lib/bulk-task-targets.d.ts +12 -0
- package/dist/lib/bulk-task-targets.js +34 -1
- package/dist/lib/cli-installers.d.ts +130 -0
- package/dist/lib/cli-installers.js +145 -0
- package/dist/lib/command-miss.js +55 -7
- package/dist/lib/dedicated-lease-command.d.ts +13 -0
- package/dist/lib/dedicated-lease-command.js +22 -1
- package/dist/lib/dedicated-machines.d.ts +95 -1
- package/dist/lib/dedicated-machines.js +236 -2
- package/dist/lib/failed-lookup.d.ts +3 -0
- package/dist/lib/failed-lookup.js +40 -0
- package/dist/lib/first-party-harness-agent.js +9 -2
- package/dist/lib/first-party-harness-doctor.d.ts +15 -0
- package/dist/lib/first-party-harness-doctor.js +126 -27
- package/dist/lib/followups.d.ts +14 -6
- package/dist/lib/followups.js +31 -6
- package/dist/lib/harnesses.d.ts +8 -0
- package/dist/lib/instruction-input.d.ts +19 -1
- package/dist/lib/instruction-input.js +52 -1
- package/dist/lib/label-scope.d.ts +15 -0
- package/dist/lib/label-scope.js +25 -5
- package/dist/lib/local-skills.d.ts +98 -0
- package/dist/lib/local-skills.js +195 -0
- package/dist/lib/machines.d.ts +10 -10
- package/dist/lib/machines.js +23 -1
- package/dist/lib/search-query.d.ts +19 -0
- package/dist/lib/search-query.js +35 -0
- package/dist/lib/space-custom-actions.d.ts +72 -0
- package/dist/lib/space-custom-actions.js +117 -0
- package/dist/lib/space-resolver.d.ts +1 -21
- package/dist/lib/space-resolver.js +19 -10
- package/dist/lib/task-closure.d.ts +3 -2
- package/dist/lib/task-closure.js +18 -20
- package/dist/lib/task-lifecycle-output.js +117 -9
- package/dist/lib/task-ref-resolver.d.ts +1 -17
- package/dist/lib/task-ref-resolver.js +18 -8
- package/dist/lib/tasks.js +9 -3
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5076 -4947
- package/oclif.manifest.json +26635 -25649
- package/package.json +9 -3
|
@@ -1,14 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.taskPointerLines = taskPointerLines;
|
|
3
4
|
exports.taskFailureLines = taskFailureLines;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const api_fetch_1 = require("../../lib/api-fetch");
|
|
7
8
|
const session_task_endpoints_1 = require("../../lib/session-task-endpoints");
|
|
8
9
|
const base_command_1 = require("../../base-command");
|
|
10
|
+
const task_closure_1 = require("../../lib/task-closure");
|
|
9
11
|
const task_resolver_1 = require("../../lib/task-resolver");
|
|
10
12
|
const web_url_1 = require("../../lib/web-url");
|
|
11
13
|
const html_text_1 = require("../../lib/html-text");
|
|
14
|
+
/**
|
|
15
|
+
* Where to look next — as COMMANDS, not as facts about the task.
|
|
16
|
+
*
|
|
17
|
+
* These used to print as `What the agent produced: skrr tasks output <ref>`,
|
|
18
|
+
* in the same `Label: value` grammar as every line above them, so the line read
|
|
19
|
+
* as a statement of what the agent had produced. It also printed on tasks no
|
|
20
|
+
* agent had ever run, asserting output that did not exist (OSK-9669). They are
|
|
21
|
+
* now a visibly separate list, and only once a run, a conversation or a Result
|
|
22
|
+
* exists for them to show.
|
|
23
|
+
*/
|
|
24
|
+
function taskPointerLines(t, ref, bin = 'skrr') {
|
|
25
|
+
const hasSomethingToShow = Boolean(t.conversationId || t.lastFinalizedRunId || t.checkoutRunId || t.currentResultId);
|
|
26
|
+
if (!hasSomethingToShow)
|
|
27
|
+
return [];
|
|
28
|
+
const pointers = [
|
|
29
|
+
[`${bin} tasks output ${ref}`, 'what the agent produced'],
|
|
30
|
+
];
|
|
31
|
+
if (t.conversationId) {
|
|
32
|
+
pointers.push([`${bin} tasks transcript ${ref}`, 'the full agent transcript']);
|
|
33
|
+
}
|
|
34
|
+
const width = Math.max(...pointers.map(([command]) => command.length));
|
|
35
|
+
return [
|
|
36
|
+
'',
|
|
37
|
+
'See also:',
|
|
38
|
+
...pointers.map(([command, what]) => ` ${command.padEnd(width)} ${what}`),
|
|
39
|
+
];
|
|
40
|
+
}
|
|
12
41
|
/**
|
|
13
42
|
* The failure rows of `tasks show`, when there are any. (S3 dogfood finding)
|
|
14
43
|
*
|
|
@@ -179,13 +208,80 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
179
208
|
* it stood on at close. Show it so a bare "done" never reads as "clean."
|
|
180
209
|
*/
|
|
181
210
|
const resolution = t.resolution;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
211
|
+
/*
|
|
212
|
+
* Same renderer as the `tasks move` receipt, so the two cannot disagree
|
|
213
|
+
* about a Task they are both describing.
|
|
214
|
+
*
|
|
215
|
+
* This copy showed an owner's ordinary close as an override:
|
|
216
|
+
* `TASK_RESULT_REVIEW_REQUIRED` lands in `blockers` whenever the policy is
|
|
217
|
+
* unsatisfied — including when the owner, who is not bound by the Review
|
|
218
|
+
* they declared, closes it themselves — and this rendered it identically to
|
|
219
|
+
* a genuine forced close. So the only read surface for "was this gate
|
|
220
|
+
* overridden?" could not answer the question.
|
|
221
|
+
*/
|
|
222
|
+
if (resolution?.closure) {
|
|
223
|
+
const sentences = (0, task_closure_1.closureSnapshotLines)(resolution.closure);
|
|
224
|
+
if (sentences.length > 0) {
|
|
225
|
+
this.log(`Resolution: ${resolution.kind ?? '-'} — ${sentences.join(' ')}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/*
|
|
229
|
+
* A Result orphaned by a spec edit is not the same as no Result.
|
|
230
|
+
*
|
|
231
|
+
* Editing a `description` or an Expectation advances `specVersion`, which
|
|
232
|
+
* unsets `currentResultId` by design — the old answer replied to a question
|
|
233
|
+
* that has changed. But every CLI surface then reported the Task as though
|
|
234
|
+
* nothing had ever been submitted, and the prior Result is still there. The
|
|
235
|
+
* web already says this correctly ("No Result answers the current Task spec
|
|
236
|
+
* vN", plus the previous one); the CLI said nothing at all.
|
|
237
|
+
*
|
|
238
|
+
* The extra request is paid only in the ambiguous case — when there is no
|
|
239
|
+
* current Result — and `tasks show` is a detail view, so one call to
|
|
240
|
+
* distinguish "nobody answered" from "the answer is out of date" is worth
|
|
241
|
+
* it. A failed lookup degrades to silence rather than to a claim.
|
|
242
|
+
*/
|
|
243
|
+
const taskSpecVersion = Number(t.specVersion) || 1;
|
|
244
|
+
if (t.currentResultId) {
|
|
245
|
+
this.log(`Result: ${String(t.currentResultId)} (answers spec v${taskSpecVersion})`);
|
|
246
|
+
/*
|
|
247
|
+
* The Review on that Result, with its REASON.
|
|
248
|
+
*
|
|
249
|
+
* Closing over a `changes_requested` Review is allowed and recorded, and
|
|
250
|
+
* the closure line says "a reviewer requested changes" — the verdict. What
|
|
251
|
+
* they asked for lived only on the Review row, which no text surface
|
|
252
|
+
* printed, so the objection survived as a fact and lost its content. One
|
|
253
|
+
* read, on a detail view, only when there is a Result to have been
|
|
254
|
+
* reviewed; a failed read says nothing rather than implying no Review.
|
|
255
|
+
*/
|
|
256
|
+
try {
|
|
257
|
+
const history = await data_provider_1.dataService.listTaskResults(taskIdentity.id);
|
|
258
|
+
const review = (history?.reviews || []).find((row) => row.resultId === String(t.currentResultId));
|
|
259
|
+
if (review) {
|
|
260
|
+
const who = (0, task_closure_1.describeAssessor)(review.reviewedBy?.kind);
|
|
261
|
+
const when = review.reviewedAt ? ` on ${String(review.reviewedAt).slice(0, 10)}` : '';
|
|
262
|
+
const why = review.rationale ? `: ${review.rationale}` : '';
|
|
263
|
+
this.log(`Review: ${review.decision} by ${who}${when}${why}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Silence, not "no Review": this read failing is not evidence of absence.
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
let priorLine = 'none submitted';
|
|
272
|
+
try {
|
|
273
|
+
const history = await data_provider_1.dataService.listTaskResults(taskIdentity.id);
|
|
274
|
+
const prior = history?.results?.[0];
|
|
275
|
+
if (prior) {
|
|
276
|
+
priorLine =
|
|
277
|
+
`none answers spec v${taskSpecVersion} — previous v${prior.version} ` +
|
|
278
|
+
`answered spec v${prior.specVersion ?? '?'}`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
priorLine = 'none answers the current spec (earlier Results could not be read)';
|
|
283
|
+
}
|
|
284
|
+
this.log(`Result: ${priorLine}`);
|
|
189
285
|
}
|
|
190
286
|
this.log(`Executor: ${t.executionMode ?? 'legacy / inferred'}`);
|
|
191
287
|
this.log(`Priority: ${t.priority ?? '-'}`);
|
|
@@ -333,11 +429,8 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
333
429
|
// Silent: a Task this caller can VIEW but whose acceptance they cannot
|
|
334
430
|
// read is a permissions shape, not something to shout about mid-page.
|
|
335
431
|
}
|
|
336
|
-
this.
|
|
337
|
-
|
|
338
|
-
if (t.conversationId) {
|
|
339
|
-
this.log(`Full agent transcript: skrr tasks transcript ${ref}`);
|
|
340
|
-
}
|
|
432
|
+
for (const line of taskPointerLines(t, ref, this.config.bin))
|
|
433
|
+
this.log(line);
|
|
341
434
|
}
|
|
342
435
|
}
|
|
343
436
|
exports.default = TasksShow;
|
|
@@ -41,8 +41,13 @@ class TasksTrust extends base_command_1.BaseCommand {
|
|
|
41
41
|
level: core_1.Flags.string({
|
|
42
42
|
options: [...data_provider_1.DELIVERABLE_AUTHORITIES],
|
|
43
43
|
required: true,
|
|
44
|
-
description:
|
|
45
|
-
|
|
44
|
+
description:
|
|
45
|
+
// `observation_backed` is a RETIRED rung name for this domain — the flag
|
|
46
|
+
// rejects it, so the only two values the help explained were one real one
|
|
47
|
+
// and one the command refuses. The four the enum actually accepts:
|
|
48
|
+
'How well evidenced the answer must be: self_reported (the doer says so), ' +
|
|
49
|
+
'human_confirmed (a person confirmed it), system_observed (the platform saw it), ' +
|
|
50
|
+
'external_receipt (a provider receipt proves it).',
|
|
46
51
|
}),
|
|
47
52
|
reason: core_1.Flags.string({
|
|
48
53
|
required: true,
|
|
@@ -251,26 +251,62 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
251
251
|
* rewrote the list and revoked the assessments with no warning at all.
|
|
252
252
|
* Same write, same price: the disclosure belongs on the effective change.
|
|
253
253
|
*/
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
/*
|
|
255
|
+
* The DESCRIPTION is a spec field too.
|
|
256
|
+
*
|
|
257
|
+
* `TaskSpecFence.TASK_SPEC_FIELDS` is `['description', 'expectations']`, and
|
|
258
|
+
* both advance `specVersion` — which revokes every assessment, because they
|
|
259
|
+
* are matched by exact version. The disclosure was wired to the Expectations
|
|
260
|
+
* payload alone, so fixing a typo in the prose voided a reviewer's sign-off
|
|
261
|
+
* with no warning and no receipt. Same write, same price, same disclosure.
|
|
262
|
+
*/
|
|
263
|
+
const changesSpec = expectationsPatch !== undefined ||
|
|
264
|
+
body.expectations !== undefined ||
|
|
265
|
+
flags.description !== undefined ||
|
|
266
|
+
body.description !== undefined;
|
|
267
|
+
if (changesSpec) {
|
|
268
|
+
let settled = [];
|
|
269
|
+
let unreadable = false;
|
|
256
270
|
try {
|
|
257
271
|
const acceptance = await data_provider_1.dataService.getTaskAcceptance(taskIdentity.id);
|
|
258
|
-
|
|
272
|
+
settled = acceptance.expectations.filter((e) => e.assessmentId);
|
|
259
273
|
}
|
|
260
274
|
catch {
|
|
261
275
|
// An unreadable acceptance is not a reason to refuse the edit. Warn
|
|
262
276
|
// without a number rather than inventing one or blocking the write.
|
|
263
|
-
|
|
277
|
+
unreadable = true;
|
|
264
278
|
}
|
|
265
|
-
if (
|
|
266
|
-
const noun =
|
|
267
|
-
const count =
|
|
268
|
-
|
|
279
|
+
if ((unreadable || settled.length > 0) && !flags.yes) {
|
|
280
|
+
const noun = settled.length === 1 ? 'assessment' : 'assessments';
|
|
281
|
+
const count = unreadable ? 'Any existing' : `${settled.length} existing`;
|
|
282
|
+
const field = expectationsPatch !== undefined || body.expectations !== undefined
|
|
283
|
+
? 'Changing Expectations'
|
|
284
|
+
: 'Changing the description';
|
|
285
|
+
this.log(`${field} advances the Task specification, so ${count} ${noun} ` +
|
|
269
286
|
'will stop counting and must be recorded again.');
|
|
287
|
+
/*
|
|
288
|
+
* NAME them. The count alone made the warning unactionable — and it is
|
|
289
|
+
* task-WIDE, so Expectations you are not touching lose their judgements
|
|
290
|
+
* too, which a bare number actively hides.
|
|
291
|
+
*/
|
|
292
|
+
for (const row of settled) {
|
|
293
|
+
this.log(` ${row.id} ${row.sentence || row.text || ''}`);
|
|
294
|
+
}
|
|
295
|
+
if (settled.length > 0) {
|
|
296
|
+
this.log('Revocation covers every Expectation on this Task, including ones this edit ' +
|
|
297
|
+
'does not touch.');
|
|
298
|
+
}
|
|
270
299
|
const ok = await this.confirm('Continue? [y/N] ');
|
|
271
300
|
if (!ok) {
|
|
272
|
-
|
|
273
|
-
|
|
301
|
+
/*
|
|
302
|
+
* Non-zero, because the edit did NOT happen.
|
|
303
|
+
*
|
|
304
|
+
* This printed "No change made." and exited 0, so `skrr tasks update
|
|
305
|
+
* … && echo applied` printed `applied`. The guard exists to protect
|
|
306
|
+
* the non-interactive path, and the non-interactive path is precisely
|
|
307
|
+
* the one that cannot see a message — it can only read the exit code.
|
|
308
|
+
*/
|
|
309
|
+
this.error('No change made — re-run with `--yes` to accept the revocation.', { exit: 2 });
|
|
274
310
|
}
|
|
275
311
|
}
|
|
276
312
|
}
|
|
@@ -42,7 +42,7 @@ class TasksUpdatesAdd extends base_command_1.BaseCommand {
|
|
|
42
42
|
'fields are required even when empty. ' +
|
|
43
43
|
'progress {completedSinceLast:[],nextActions:[],currentFocus?} · ' +
|
|
44
44
|
'finding {finding,evidenceRefs:[],impact?,severity?} · ' +
|
|
45
|
-
'decision {decision,rationale,alternativesConsidered
|
|
45
|
+
'decision {decision,rationale,alternativesConsidered?:[]} · ' +
|
|
46
46
|
'blocker {cause,requiredAction,nextOwner} · ' +
|
|
47
47
|
'verification {claim,result:passed|failed|inconclusive,evidenceRefs:[]}. ' +
|
|
48
48
|
'nextOwner is a principal object like {"kind":"human","userId":"..."}, not a name. ' +
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr token list`
|
|
4
|
+
*
|
|
5
|
+
* The other half of `token mint`. Minting binds a long-lived refresh session to
|
|
6
|
+
* a machine and records the `--label` with it — which reads as a promise that
|
|
7
|
+
* the credential can be found again — and there was no way to see it: `token`
|
|
8
|
+
* had only `mint`, and `list-tokens` shows CI tokens, a different credential
|
|
9
|
+
* type, so `revoke-token` had nothing to aim at. The only remedy was
|
|
10
|
+
* `logout --all-devices`, which signs every machine out.
|
|
11
|
+
*
|
|
12
|
+
* `GET /api/auth/sessions/refresh` has served exactly this list all along; it
|
|
13
|
+
* was simply not reachable from the CLI.
|
|
14
|
+
*/
|
|
15
|
+
export default class TokenList extends BaseCommand {
|
|
16
|
+
static description: string;
|
|
17
|
+
static examples: string[];
|
|
18
|
+
static flags: {
|
|
19
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../base-command");
|
|
5
|
+
const api_fetch_1 = require("../../lib/api-fetch");
|
|
6
|
+
const format_1 = require("../../lib/format");
|
|
7
|
+
/**
|
|
8
|
+
* `skrr token list`
|
|
9
|
+
*
|
|
10
|
+
* The other half of `token mint`. Minting binds a long-lived refresh session to
|
|
11
|
+
* a machine and records the `--label` with it — which reads as a promise that
|
|
12
|
+
* the credential can be found again — and there was no way to see it: `token`
|
|
13
|
+
* had only `mint`, and `list-tokens` shows CI tokens, a different credential
|
|
14
|
+
* type, so `revoke-token` had nothing to aim at. The only remedy was
|
|
15
|
+
* `logout --all-devices`, which signs every machine out.
|
|
16
|
+
*
|
|
17
|
+
* `GET /api/auth/sessions/refresh` has served exactly this list all along; it
|
|
18
|
+
* was simply not reachable from the CLI.
|
|
19
|
+
*/
|
|
20
|
+
class TokenList extends base_command_1.BaseCommand {
|
|
21
|
+
static description = 'List the active sessions a minted token belongs to — the other half of `token mint`';
|
|
22
|
+
static examples = [
|
|
23
|
+
'<%= config.bin %> token list',
|
|
24
|
+
'<%= config.bin %> token list --json',
|
|
25
|
+
];
|
|
26
|
+
static flags = { json: core_1.Flags.boolean({ description: 'Output JSON' }) };
|
|
27
|
+
async run() {
|
|
28
|
+
this.requireAuth();
|
|
29
|
+
const { flags } = await this.parse(TokenList);
|
|
30
|
+
let data = null;
|
|
31
|
+
try {
|
|
32
|
+
data = await (0, api_fetch_1.apiFetch)('/api/auth/sessions/refresh', {
|
|
33
|
+
method: 'GET',
|
|
34
|
+
credential: this.resolvedCredential,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
this.handleApiError(err);
|
|
39
|
+
}
|
|
40
|
+
const sessions = data?.sessions || [];
|
|
41
|
+
if (flags.json)
|
|
42
|
+
return this.log(JSON.stringify({ sessions, count: sessions.length }, null, 2));
|
|
43
|
+
if (!sessions.length)
|
|
44
|
+
return this.log('No active sessions.');
|
|
45
|
+
(0, format_1.renderTable)(sessions.map((session) => ({
|
|
46
|
+
id: session.id,
|
|
47
|
+
kind: session.kind,
|
|
48
|
+
// The operator's own name for the credential wins over a derived
|
|
49
|
+
// device string — it is what they would search by.
|
|
50
|
+
device: session.label || session.device || '-',
|
|
51
|
+
ip: session.ip || '-',
|
|
52
|
+
lastActive: session.lastActiveAt || session.createdAt || '-',
|
|
53
|
+
// The session you are typing in. Revoking it signs THIS machine out,
|
|
54
|
+
// which is the one outcome nobody means when they revoke a credential.
|
|
55
|
+
current: session.current ? 'yes' : '',
|
|
56
|
+
})), [
|
|
57
|
+
{ key: 'id', header: 'ID' },
|
|
58
|
+
{ key: 'kind', header: 'KIND' },
|
|
59
|
+
{ key: 'device', header: 'DEVICE', maxWidth: 34 },
|
|
60
|
+
{ key: 'ip', header: 'IP' },
|
|
61
|
+
{ key: 'lastActive', header: 'LAST ACTIVE' },
|
|
62
|
+
{ key: 'current', header: 'CURRENT' },
|
|
63
|
+
], (line) => this.log(line));
|
|
64
|
+
this.log('');
|
|
65
|
+
this.log('Retire one with: skrr token revoke <id>');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.default = TokenList;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr token revoke <id>`
|
|
4
|
+
*
|
|
5
|
+
* Retire ONE session — the credential `token mint` handed to one machine —
|
|
6
|
+
* without signing every other machine out. `logout --all-devices` was the only
|
|
7
|
+
* way to do this, which is a blunt instrument for "that one CI box is
|
|
8
|
+
* decommissioned".
|
|
9
|
+
*
|
|
10
|
+
* Owner-gated server-side: a row that is not the caller's returns
|
|
11
|
+
* `{ revoked: false }` rather than an error, so ids cannot be enumerated.
|
|
12
|
+
*/
|
|
13
|
+
export default class TokenRevoke extends BaseCommand {
|
|
14
|
+
static description: string;
|
|
15
|
+
static examples: string[];
|
|
16
|
+
static args: {
|
|
17
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
18
|
+
};
|
|
19
|
+
static flags: {
|
|
20
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../base-command");
|
|
5
|
+
const api_fetch_1 = require("../../lib/api-fetch");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr token revoke <id>`
|
|
8
|
+
*
|
|
9
|
+
* Retire ONE session — the credential `token mint` handed to one machine —
|
|
10
|
+
* without signing every other machine out. `logout --all-devices` was the only
|
|
11
|
+
* way to do this, which is a blunt instrument for "that one CI box is
|
|
12
|
+
* decommissioned".
|
|
13
|
+
*
|
|
14
|
+
* Owner-gated server-side: a row that is not the caller's returns
|
|
15
|
+
* `{ revoked: false }` rather than an error, so ids cannot be enumerated.
|
|
16
|
+
*/
|
|
17
|
+
class TokenRevoke extends base_command_1.BaseCommand {
|
|
18
|
+
static description = 'Revoke one session by id — see `skrr token list` for the ids';
|
|
19
|
+
static examples = ['<%= config.bin %> token revoke 665f1c2e9a4b3d0011aa77bc'];
|
|
20
|
+
static args = {
|
|
21
|
+
id: core_1.Args.string({
|
|
22
|
+
required: true,
|
|
23
|
+
ignoreStdin: true,
|
|
24
|
+
description: 'Session id from `skrr token list`',
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
static flags = { json: core_1.Flags.boolean({ description: 'Output JSON' }) };
|
|
28
|
+
async run() {
|
|
29
|
+
this.requireAuth();
|
|
30
|
+
const { args, flags } = await this.parse(TokenRevoke);
|
|
31
|
+
let data = null;
|
|
32
|
+
try {
|
|
33
|
+
data = await (0, api_fetch_1.apiFetch)(`/api/auth/sessions/refresh/${encodeURIComponent(args.id)}/revoke`, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
credential: this.resolvedCredential,
|
|
36
|
+
body: {},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
this.handleApiError(err);
|
|
41
|
+
}
|
|
42
|
+
if (flags.json)
|
|
43
|
+
return this.log(JSON.stringify(data, null, 2));
|
|
44
|
+
if (data?.revoked)
|
|
45
|
+
return this.log(`Revoked session ${args.id}. Other machines stay signed in.`);
|
|
46
|
+
// The server does not distinguish "already gone" from "not yours" on
|
|
47
|
+
// purpose, so neither does this — saying "not found" would leak the
|
|
48
|
+
// difference and let somebody probe for ids.
|
|
49
|
+
this.log(`Nothing to revoke for ${args.id} — it is already revoked, or it is not one of your sessions.`);
|
|
50
|
+
this.log('List what is active with: skrr token list');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.default = TokenRevoke;
|
|
@@ -1,11 +1,50 @@
|
|
|
1
1
|
import type { Agent, AgentAction, AgentActionOutcome, AgentActionScope, BuiltinActionConfig, BuiltinActionType, BuiltinAgentAction, EmbeddedActionRef, PromptAgentAction } from '@skrr-ai/data-provider';
|
|
2
|
-
export
|
|
2
|
+
export { BUILTIN_ACTION_TYPES } from '@skrr-ai/data-provider';
|
|
3
3
|
export declare const ACTION_TARGET_TYPES: readonly ["group-chats", "spaces", "tasks", "goals", "slack-channels", "slack-users"];
|
|
4
4
|
export type ActionTargetType = (typeof ACTION_TARGET_TYPES)[number];
|
|
5
5
|
export declare function parseJsonObjectFlag(value: string | undefined, flagName: string): Record<string, unknown> | undefined;
|
|
6
6
|
export declare function fetchAgentForActionEdit(agentId: string): Promise<Agent>;
|
|
7
7
|
export declare function getAgentActions(agent: Agent): AgentAction[];
|
|
8
8
|
export declare function findAgentAction(agent: Agent, actionId: string): AgentAction | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* The row as the SERVER stored it, not as we sent it.
|
|
11
|
+
*
|
|
12
|
+
* `updateAgentActions` returns the updated Agent, and both editors used to
|
|
13
|
+
* discard it and print the object they had just built — so the output was the
|
|
14
|
+
* input, restated. That is not a cosmetic difference: the server normalizes
|
|
15
|
+
* `agentActions` through an allowlist before persisting, so a field it drops is
|
|
16
|
+
* echoed back by the CLI as though it had been saved. A `label` scope and
|
|
17
|
+
* `outcome: durable` were both silently discarded that way and the CLI reported
|
|
18
|
+
* success with the values the caller had typed (OSK-9628).
|
|
19
|
+
*
|
|
20
|
+
* Falling back to the local object keeps the command working if the write
|
|
21
|
+
* succeeds but the response is unexpectedly shaped; it cannot make the output
|
|
22
|
+
* wrong in a way it was not already.
|
|
23
|
+
*/
|
|
24
|
+
export declare function storedActionOrLocal(agent: Agent | null | undefined, local: AgentAction): AgentAction;
|
|
25
|
+
export type AppendedAgentAction = {
|
|
26
|
+
/** The action as the server stored it. */
|
|
27
|
+
action: AgentAction;
|
|
28
|
+
/** False when this id was already in the library — a replayed request. */
|
|
29
|
+
created: boolean;
|
|
30
|
+
total: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Append ONE action atomically.
|
|
34
|
+
*
|
|
35
|
+
* `agents actions create` used to read the agent, append in memory and write
|
|
36
|
+
* the whole library back through `updateAgentActions`. Two concurrent creates
|
|
37
|
+
* therefore each read the same library and the later write erased the earlier
|
|
38
|
+
* action — six parallel creates all printed success and left one (OSK-9673).
|
|
39
|
+
* This endpoint appends with a single conditional `$push` on the server, so
|
|
40
|
+
* concurrent creates all land, the cap is enforced at the instant of the write,
|
|
41
|
+
* and a retried request whose id already landed returns `created: false`
|
|
42
|
+
* instead of adding a second copy. The client-generated id is what makes that
|
|
43
|
+
* retry safe, so it is sent rather than left for the server to assign.
|
|
44
|
+
*
|
|
45
|
+
* Update and delete still use `updateAgentActions` and still read-modify-write.
|
|
46
|
+
*/
|
|
47
|
+
export declare function appendAgentAction(agentId: string, action: AgentAction): Promise<AppendedAgentAction>;
|
|
9
48
|
export declare function updateAgentActions(agentId: string, actions: AgentAction[]): Promise<Agent>;
|
|
10
49
|
/**
|
|
11
50
|
* Fields every action shape carries regardless of kind.
|
|
@@ -52,7 +91,23 @@ export type AgentActionScopeFlags = {
|
|
|
52
91
|
* `--scope space --space s1` twice is the kind of ceremony people skip and then
|
|
53
92
|
* wonder why the action is everywhere. An explicit `--scope general` clears it.
|
|
54
93
|
*/
|
|
55
|
-
|
|
94
|
+
/**
|
|
95
|
+
* `--label` accepts an id OR a name, like every other `--label` in the CLI.
|
|
96
|
+
*
|
|
97
|
+
* It used to take the value verbatim as a `labelId`. A name was therefore
|
|
98
|
+
* stored as though it were an id, matched no space's `labelIds`, and produced
|
|
99
|
+
* an action offered NOWHERE — silently, with the create reporting success. That
|
|
100
|
+
* is exactly the "an action that disappears reads as deletion" hazard the label
|
|
101
|
+
* tier was designed around, arriving through the CLI instead of through a card
|
|
102
|
+
* that forgot to pass its labels. An unknown name was accepted too, so a typo
|
|
103
|
+
* was indistinguishable from a working scope.
|
|
104
|
+
*
|
|
105
|
+
* `resolveLabelRefs` is the same resolver `spaces create --label` uses: it
|
|
106
|
+
* short-circuits when every value already looks like an id (so a scripted
|
|
107
|
+
* caller pays no request), refuses an unknown name with the near misses named,
|
|
108
|
+
* and refuses an ambiguous one rather than guessing.
|
|
109
|
+
*/
|
|
110
|
+
export declare function resolveAgentActionScopeFlags(flags: AgentActionScopeFlags): Promise<AgentActionScope | undefined>;
|
|
56
111
|
/** Human-readable one-liner for a scope, used by list/show renderers. */
|
|
57
112
|
export declare function describeAgentActionScope(scope?: AgentActionScope | null): string;
|
|
58
113
|
export declare function nextActionOrder(actions: AgentAction[]): number;
|