@skrr-ai/cli 0.1.92 → 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/set.js +1 -1
- 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/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 +5 -0
- package/dist/lib/dedicated-power.js +30 -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 +6612 -6113
- package/oclif.manifest.json +46778 -38019
- package/package.json +2 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Storage-field stripping for `--json` output (audit P9).
|
|
4
|
+
*
|
|
5
|
+
* The API returns Mongo documents, so every row carries `_id` and `__v` beside
|
|
6
|
+
* the real `id`: 47 keys per task row, two of which are storage detail an agent
|
|
7
|
+
* pays tokens for and can mistake for the identifier (OSK-12205 was exactly
|
|
8
|
+
* that: a 24-hex `_id` passed where a task id was wanted).
|
|
9
|
+
*
|
|
10
|
+
* This runs at the CLI SERIALIZER only (`BaseCommand.log`), never in the API or
|
|
11
|
+
* the data layer, so no other consumer's payload changes. `--raw` (or
|
|
12
|
+
* `OVERSKY_CLI_RAW=1`) turns it off for the caller that does want them.
|
|
13
|
+
*
|
|
14
|
+
* Two rules, both conservative:
|
|
15
|
+
* - `__v` is the Mongoose version key and is always dropped.
|
|
16
|
+
* - `_id` is dropped only when the same object has a usable `id`. A row that
|
|
17
|
+
* has ONLY `_id` (some legacy collections) keeps it: removing the sole
|
|
18
|
+
* identifier would turn a cosmetic cleanup into data loss.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.stripStorageFields = stripStorageFields;
|
|
22
|
+
exports.stripStorageFieldsFromText = stripStorageFieldsFromText;
|
|
23
|
+
function usableId(value) {
|
|
24
|
+
return (typeof value === 'string' && value.length > 0) || typeof value === 'number';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns the SAME reference when nothing needed stripping, so a caller can tell
|
|
28
|
+
* "unchanged" apart from "rebuilt" and leave the original text alone.
|
|
29
|
+
*/
|
|
30
|
+
function stripStorageFields(value) {
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
let changed = false;
|
|
33
|
+
const next = value.map((item) => {
|
|
34
|
+
const stripped = stripStorageFields(item);
|
|
35
|
+
if (stripped !== item)
|
|
36
|
+
changed = true;
|
|
37
|
+
return stripped;
|
|
38
|
+
});
|
|
39
|
+
return changed ? next : value;
|
|
40
|
+
}
|
|
41
|
+
if (value === null || typeof value !== 'object')
|
|
42
|
+
return value;
|
|
43
|
+
const source = value;
|
|
44
|
+
const dropId = '_id' in source && usableId(source.id);
|
|
45
|
+
const dropVersion = '__v' in source;
|
|
46
|
+
let changed = dropId || dropVersion;
|
|
47
|
+
const next = {};
|
|
48
|
+
for (const [key, child] of Object.entries(source)) {
|
|
49
|
+
if ((key === '_id' && dropId) || (key === '__v' && dropVersion))
|
|
50
|
+
continue;
|
|
51
|
+
const stripped = stripStorageFields(child);
|
|
52
|
+
if (stripped !== child)
|
|
53
|
+
changed = true;
|
|
54
|
+
next[key] = stripped;
|
|
55
|
+
}
|
|
56
|
+
return changed ? next : value;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Apply {@link stripStorageFields} to one line of CLI output. Anything that is
|
|
60
|
+
* not a JSON object/array (prose, a bare string, malformed text) is returned
|
|
61
|
+
* untouched, as is JSON with nothing to strip, so existing formatting survives.
|
|
62
|
+
*/
|
|
63
|
+
function stripStorageFieldsFromText(text) {
|
|
64
|
+
const head = text.trimStart()[0];
|
|
65
|
+
if (head !== '{' && head !== '[')
|
|
66
|
+
return text;
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(text);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return text;
|
|
73
|
+
}
|
|
74
|
+
const stripped = stripStorageFields(parsed);
|
|
75
|
+
if (stripped === parsed)
|
|
76
|
+
return text;
|
|
77
|
+
return JSON.stringify(stripped, null, text.includes('\n') ? 2 : undefined);
|
|
78
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export type ListWarning = {
|
|
2
|
+
code: string;
|
|
3
|
+
value?: unknown;
|
|
4
|
+
hint: string;
|
|
5
|
+
};
|
|
6
|
+
export type ListEnvelope = {
|
|
7
|
+
object: 'list';
|
|
8
|
+
data: Array<Record<string, unknown>>;
|
|
9
|
+
has_more: boolean;
|
|
10
|
+
next_cursor: string | null;
|
|
11
|
+
limit_applied?: number;
|
|
12
|
+
warnings?: ListWarning[];
|
|
13
|
+
} & Record<string, unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* The navigation projection per resource: enough to identify a row, decide
|
|
16
|
+
* whether it matters and fetch it with `show`. Allowlists, not drop-lists, so a
|
|
17
|
+
* field the server adds tomorrow does not silently re-inflate every compact row.
|
|
18
|
+
* Documented in docs/cli/SKRR_TASKS.md (List output for agents).
|
|
19
|
+
*/
|
|
20
|
+
export declare const COMPACT_FIELDS: {
|
|
21
|
+
readonly task: readonly ["id", "identifier", "ref", "title", "status", "statusType", "priority", "estimate", "assigneeAgentIds", "assigneeUserIds", "parentId", "spaceId", "projectId", "goalId", "dueDate", "scheduledFor", "labelIds", "tags", "externalKey", "version", "executionMode", "nextAction", "createdAt", "updatedAt", "url"];
|
|
22
|
+
readonly space: readonly ["id", "identifier", "title", "status", "parentSpaceId", "leadAgentId", "labelIds", "archivedAt", "createdAt", "updatedAt", "url"];
|
|
23
|
+
readonly project: readonly ["id", "identifier", "title", "spaceId", "externalKey", "taskCounts", "archivedAt", "createdAt", "updatedAt", "url"];
|
|
24
|
+
};
|
|
25
|
+
export type ListResource = keyof typeof COMPACT_FIELDS;
|
|
26
|
+
/** The three flags every projecting list command declares. */
|
|
27
|
+
export declare const listOutputFlags: {
|
|
28
|
+
fields: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
compact: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
30
|
+
ndjson: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
31
|
+
};
|
|
32
|
+
export type ListOutputFlags = {
|
|
33
|
+
fields?: string;
|
|
34
|
+
compact?: boolean;
|
|
35
|
+
ndjson?: boolean;
|
|
36
|
+
};
|
|
37
|
+
/** `--fields a, b ,c` -> ['a','b','c']; empty/blank -> undefined. */
|
|
38
|
+
export declare function parseFields(raw: string | undefined): string[] | undefined;
|
|
39
|
+
export declare function projectRow(row: Record<string, unknown>, fields: readonly string[]): Record<string, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Normalize any list response to the shared envelope. `data` is where rows live
|
|
42
|
+
* for every list command; `projects` (an older serialization) is folded into it.
|
|
43
|
+
* A response that is not list-shaped is returned untouched (never invent rows).
|
|
44
|
+
*/
|
|
45
|
+
export declare function toListEnvelope(response: unknown): ListEnvelope | undefined;
|
|
46
|
+
export type ShapeListOptions = ListOutputFlags & {
|
|
47
|
+
resource: ListResource;
|
|
48
|
+
/** What the caller asked for with --limit (undefined when the command has none). */
|
|
49
|
+
requestedLimit?: number;
|
|
50
|
+
warnings?: ListWarning[];
|
|
51
|
+
/** A filter the CLI applied that the caller did not ask for (E12). Echoed as `filter_applied`. */
|
|
52
|
+
filterApplied?: Record<string, unknown>;
|
|
53
|
+
};
|
|
54
|
+
/** Pure: envelope + projection + notes. Returns the response untouched if not a list. */
|
|
55
|
+
export declare function shapeListResponse(response: unknown, options: ShapeListOptions): unknown;
|
|
56
|
+
/**
|
|
57
|
+
* E11: the server silently clamps `--limit` (cap) and coerces `0` to its default.
|
|
58
|
+
* Echo what was applied. `applied` is only reported when we can prove it: a full
|
|
59
|
+
* page that still has more rows means the cap is exactly the row count.
|
|
60
|
+
*/
|
|
61
|
+
export declare function limitNote(requested: number | undefined, rowCount: number, hasMore: boolean): {
|
|
62
|
+
applied?: number;
|
|
63
|
+
warning?: ListWarning;
|
|
64
|
+
};
|
|
65
|
+
/** The text-mode twin of a warning: one `Note:` line a person can act on. */
|
|
66
|
+
export declare function warningLines(warnings: readonly ListWarning[] | undefined): string[];
|
|
67
|
+
export type ListOutput = {
|
|
68
|
+
stdout: string[];
|
|
69
|
+
stderr: string[];
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Render a shaped list for `--json` (pretty envelope) or `--ndjson` (rows one per
|
|
73
|
+
* line, `_meta` on stderr). Pure; the caller writes the lines.
|
|
74
|
+
*/
|
|
75
|
+
export declare function renderListOutput(shaped: unknown, ndjson: boolean): ListOutput;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listOutputFlags = exports.COMPACT_FIELDS = void 0;
|
|
4
|
+
exports.parseFields = parseFields;
|
|
5
|
+
exports.projectRow = projectRow;
|
|
6
|
+
exports.toListEnvelope = toListEnvelope;
|
|
7
|
+
exports.shapeListResponse = shapeListResponse;
|
|
8
|
+
exports.limitNote = limitNote;
|
|
9
|
+
exports.warningLines = warningLines;
|
|
10
|
+
exports.renderListOutput = renderListOutput;
|
|
11
|
+
/**
|
|
12
|
+
* Shared output shaping for `skrr` LIST commands (agent-surface audit
|
|
13
|
+
* OSK-14039 / OSK-14040: P3, P4, E1, E11).
|
|
14
|
+
*
|
|
15
|
+
* A list command's `--json` used to print whatever the server sent: 4.4 KB per
|
|
16
|
+
* task, 38% of it `activityLog`, with no way to ask for less, and an envelope
|
|
17
|
+
* that differed per command. This module is the one place that decides:
|
|
18
|
+
*
|
|
19
|
+
* - the ENVELOPE: `{object:'list', data, has_more, next_cursor, ...}`, the same
|
|
20
|
+
* for every list command (`data` is always the row array, so a consumer that
|
|
21
|
+
* read `.data` keeps working);
|
|
22
|
+
* - the PROJECTION: `--fields a,b,c` (explicit, wins) or `--compact` (a
|
|
23
|
+
* documented per-resource navigation set), applied to `data` rows only;
|
|
24
|
+
* - `--ndjson`: one JSON row per line on stdout, metadata on stderr;
|
|
25
|
+
* - NOTES: `limit_applied` / `warnings[]`, so "the server clamped your limit" and
|
|
26
|
+
* "your filter matched nothing because it is not a state id" are visible in
|
|
27
|
+
* JSON the way they already are in text.
|
|
28
|
+
*
|
|
29
|
+
* Pure functions, no oclif: the commands own I/O, this owns the shape.
|
|
30
|
+
*/
|
|
31
|
+
const core_1 = require("@oclif/core");
|
|
32
|
+
/**
|
|
33
|
+
* The navigation projection per resource: enough to identify a row, decide
|
|
34
|
+
* whether it matters and fetch it with `show`. Allowlists, not drop-lists, so a
|
|
35
|
+
* field the server adds tomorrow does not silently re-inflate every compact row.
|
|
36
|
+
* Documented in docs/cli/SKRR_TASKS.md (List output for agents).
|
|
37
|
+
*/
|
|
38
|
+
exports.COMPACT_FIELDS = {
|
|
39
|
+
task: [
|
|
40
|
+
'id',
|
|
41
|
+
'identifier',
|
|
42
|
+
'ref',
|
|
43
|
+
'title',
|
|
44
|
+
'status',
|
|
45
|
+
'statusType',
|
|
46
|
+
'priority',
|
|
47
|
+
'estimate',
|
|
48
|
+
'assigneeAgentIds',
|
|
49
|
+
'assigneeUserIds',
|
|
50
|
+
'parentId',
|
|
51
|
+
'spaceId',
|
|
52
|
+
'projectId',
|
|
53
|
+
'goalId',
|
|
54
|
+
'dueDate',
|
|
55
|
+
'scheduledFor',
|
|
56
|
+
'labelIds',
|
|
57
|
+
'tags',
|
|
58
|
+
'externalKey',
|
|
59
|
+
'version',
|
|
60
|
+
'executionMode',
|
|
61
|
+
'nextAction',
|
|
62
|
+
'createdAt',
|
|
63
|
+
'updatedAt',
|
|
64
|
+
'url',
|
|
65
|
+
],
|
|
66
|
+
space: [
|
|
67
|
+
'id',
|
|
68
|
+
'identifier',
|
|
69
|
+
'title',
|
|
70
|
+
'status',
|
|
71
|
+
'parentSpaceId',
|
|
72
|
+
'leadAgentId',
|
|
73
|
+
'labelIds',
|
|
74
|
+
'archivedAt',
|
|
75
|
+
'createdAt',
|
|
76
|
+
'updatedAt',
|
|
77
|
+
'url',
|
|
78
|
+
],
|
|
79
|
+
project: [
|
|
80
|
+
'id',
|
|
81
|
+
'identifier',
|
|
82
|
+
'title',
|
|
83
|
+
'spaceId',
|
|
84
|
+
'externalKey',
|
|
85
|
+
'taskCounts',
|
|
86
|
+
'archivedAt',
|
|
87
|
+
'createdAt',
|
|
88
|
+
'updatedAt',
|
|
89
|
+
'url',
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
/** The three flags every projecting list command declares. */
|
|
93
|
+
exports.listOutputFlags = {
|
|
94
|
+
fields: core_1.Flags.string({
|
|
95
|
+
description: 'JSON only: comma-separated fields to keep on each row (dotted paths allowed, e.g. id,title,assignee.name). Wins over --compact.',
|
|
96
|
+
}),
|
|
97
|
+
compact: core_1.Flags.boolean({
|
|
98
|
+
description: 'JSON only: keep the navigation fields of each row (id, ref, title, status, owners, dates, url) and drop activity logs, lifecycle and other bulk. See docs/cli/SKRR_TASKS.md (List output for agents).',
|
|
99
|
+
}),
|
|
100
|
+
ndjson: core_1.Flags.boolean({
|
|
101
|
+
description: 'One JSON object per line on stdout (rows only; paging and warnings go to stderr as one {"_meta":...} line). Implies --json.',
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
/** `--fields a, b ,c` -> ['a','b','c']; empty/blank -> undefined. */
|
|
105
|
+
function parseFields(raw) {
|
|
106
|
+
if (!raw)
|
|
107
|
+
return undefined;
|
|
108
|
+
const fields = raw
|
|
109
|
+
.split(',')
|
|
110
|
+
.map((f) => f.trim())
|
|
111
|
+
.filter(Boolean);
|
|
112
|
+
return fields.length > 0 ? Array.from(new Set(fields)) : undefined;
|
|
113
|
+
}
|
|
114
|
+
function pick(row, path) {
|
|
115
|
+
let current = row;
|
|
116
|
+
for (const segment of path.split('.')) {
|
|
117
|
+
if (current === null || typeof current !== 'object' || !(segment in current)) {
|
|
118
|
+
return { found: false, value: undefined };
|
|
119
|
+
}
|
|
120
|
+
current = current[segment];
|
|
121
|
+
}
|
|
122
|
+
return { found: true, value: current };
|
|
123
|
+
}
|
|
124
|
+
function assign(target, path, value) {
|
|
125
|
+
const segments = path.split('.');
|
|
126
|
+
let cursor = target;
|
|
127
|
+
for (const segment of segments.slice(0, -1)) {
|
|
128
|
+
const next = cursor[segment];
|
|
129
|
+
if (next === null || typeof next !== 'object' || Array.isArray(next))
|
|
130
|
+
cursor[segment] = {};
|
|
131
|
+
cursor = cursor[segment];
|
|
132
|
+
}
|
|
133
|
+
cursor[segments[segments.length - 1]] = value;
|
|
134
|
+
}
|
|
135
|
+
function projectRow(row, fields) {
|
|
136
|
+
const out = {};
|
|
137
|
+
for (const field of fields) {
|
|
138
|
+
const { found, value } = pick(row, field);
|
|
139
|
+
if (found)
|
|
140
|
+
assign(out, field, value);
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Normalize any list response to the shared envelope. `data` is where rows live
|
|
146
|
+
* for every list command; `projects` (an older serialization) is folded into it.
|
|
147
|
+
* A response that is not list-shaped is returned untouched (never invent rows).
|
|
148
|
+
*/
|
|
149
|
+
function toListEnvelope(response) {
|
|
150
|
+
if (Array.isArray(response)) {
|
|
151
|
+
return {
|
|
152
|
+
object: 'list',
|
|
153
|
+
data: response,
|
|
154
|
+
has_more: false,
|
|
155
|
+
next_cursor: null,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (!response || typeof response !== 'object')
|
|
159
|
+
return undefined;
|
|
160
|
+
const r = response;
|
|
161
|
+
const rows = Array.isArray(r.data) ? r.data : Array.isArray(r.projects) ? r.projects : undefined;
|
|
162
|
+
if (!rows)
|
|
163
|
+
return undefined;
|
|
164
|
+
const { projects: _legacy, ...rest } = r;
|
|
165
|
+
void _legacy;
|
|
166
|
+
return {
|
|
167
|
+
...rest,
|
|
168
|
+
object: 'list',
|
|
169
|
+
data: rows,
|
|
170
|
+
has_more: typeof r.has_more === 'boolean' ? r.has_more : Boolean(r.next_cursor),
|
|
171
|
+
next_cursor: typeof r.next_cursor === 'string' ? r.next_cursor : null,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** Pure: envelope + projection + notes. Returns the response untouched if not a list. */
|
|
175
|
+
function shapeListResponse(response, options) {
|
|
176
|
+
const envelope = toListEnvelope(response);
|
|
177
|
+
if (!envelope)
|
|
178
|
+
return response;
|
|
179
|
+
const warnings = [...(options.warnings ?? [])];
|
|
180
|
+
const fields = parseFields(options.fields);
|
|
181
|
+
let data = envelope.data;
|
|
182
|
+
if (fields) {
|
|
183
|
+
data = data.map((row) => projectRow(row, fields));
|
|
184
|
+
if (envelope.data.length > 0) {
|
|
185
|
+
for (const field of fields) {
|
|
186
|
+
if (!envelope.data.some((row) => pick(row, field).found)) {
|
|
187
|
+
warnings.push({
|
|
188
|
+
code: 'UNKNOWN_FIELD',
|
|
189
|
+
value: field,
|
|
190
|
+
hint: `No row carried "${field}". Run without --fields to see the available keys.`,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (options.compact) {
|
|
197
|
+
const keep = exports.COMPACT_FIELDS[options.resource];
|
|
198
|
+
data = data.map((row) => {
|
|
199
|
+
const kept = projectRow(row, keep);
|
|
200
|
+
// A row that carries none of the navigation fields is an unknown shape;
|
|
201
|
+
// dropping it to `{}` would hide it rather than compact it.
|
|
202
|
+
return Object.keys(kept).length > 0 ? kept : row;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const limit = limitNote(options.requestedLimit, envelope.data.length, envelope.has_more);
|
|
206
|
+
if (limit.warning)
|
|
207
|
+
warnings.push(limit.warning);
|
|
208
|
+
return {
|
|
209
|
+
...envelope,
|
|
210
|
+
data,
|
|
211
|
+
...(limit.applied !== undefined ? { limit_applied: limit.applied } : {}),
|
|
212
|
+
...(options.filterApplied ? { filter_applied: options.filterApplied } : {}),
|
|
213
|
+
...(warnings.length > 0 ? { warnings } : {}),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* E11: the server silently clamps `--limit` (cap) and coerces `0` to its default.
|
|
218
|
+
* Echo what was applied. `applied` is only reported when we can prove it: a full
|
|
219
|
+
* page that still has more rows means the cap is exactly the row count.
|
|
220
|
+
*/
|
|
221
|
+
function limitNote(requested, rowCount, hasMore) {
|
|
222
|
+
if (requested === undefined)
|
|
223
|
+
return {};
|
|
224
|
+
if (requested <= 0) {
|
|
225
|
+
return {
|
|
226
|
+
applied: hasMore ? rowCount : undefined,
|
|
227
|
+
warning: {
|
|
228
|
+
code: 'LIMIT_COERCED',
|
|
229
|
+
value: requested,
|
|
230
|
+
hint: '--limit must be >= 1; the server applied its default page size instead. Pass an explicit positive --limit.',
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
if (hasMore && rowCount > 0 && rowCount < requested) {
|
|
235
|
+
return {
|
|
236
|
+
applied: rowCount,
|
|
237
|
+
warning: {
|
|
238
|
+
code: 'LIMIT_CLAMPED',
|
|
239
|
+
value: requested,
|
|
240
|
+
hint: `The server returned ${rowCount} rows, its per-page cap, not the ${requested} requested. Follow next_cursor for the rest.`,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return {};
|
|
245
|
+
}
|
|
246
|
+
/** The text-mode twin of a warning: one `Note:` line a person can act on. */
|
|
247
|
+
function warningLines(warnings) {
|
|
248
|
+
return (warnings ?? []).map((w) => `Note: ${w.hint}`);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Render a shaped list for `--json` (pretty envelope) or `--ndjson` (rows one per
|
|
252
|
+
* line, `_meta` on stderr). Pure; the caller writes the lines.
|
|
253
|
+
*/
|
|
254
|
+
function renderListOutput(shaped, ndjson) {
|
|
255
|
+
if (!ndjson)
|
|
256
|
+
return { stdout: [JSON.stringify(shaped, null, 2)], stderr: [] };
|
|
257
|
+
const envelope = shaped;
|
|
258
|
+
if (!envelope || !Array.isArray(envelope.data)) {
|
|
259
|
+
return { stdout: [JSON.stringify(shaped)], stderr: [] };
|
|
260
|
+
}
|
|
261
|
+
const { data, ...meta } = envelope;
|
|
262
|
+
return {
|
|
263
|
+
stdout: data.map((row) => JSON.stringify(row)),
|
|
264
|
+
stderr: [JSON.stringify({ _meta: meta })],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { COMPUTER_DAEMON_LOG_LEVELS, COMPUTER_DAEMON_LOG_LIMITS, type ComputerDaemonLogResult } from '@skrr-ai/data-provider';
|
|
2
|
+
import { type ComputerFileFailure } from './computer-files';
|
|
3
|
+
/**
|
|
4
|
+
* machine-daemon-log.ts — request client for `GET /api/machines/:machineId/daemon-log`
|
|
5
|
+
* (`computer_daemon_log_v1`): the tail of what a machine's daemon logged about
|
|
6
|
+
* itself, so an owner can see why it reconnected, re-registered or failed
|
|
7
|
+
* without reading syslog (which a Dedicated Runtime guest's tenant uid cannot).
|
|
8
|
+
*
|
|
9
|
+
* The daemon serves an in-memory ring of its OWN logger's lines, redacted
|
|
10
|
+
* before they were kept; a `watch` grantee reads it too. Vocabulary, limits
|
|
11
|
+
* and the result shape are owned by `@skrr-ai/data-provider`.
|
|
12
|
+
*
|
|
13
|
+
* ## Inline path literal
|
|
14
|
+
*
|
|
15
|
+
* `domain-api-parity` resolves a command to an endpoint by reading this
|
|
16
|
+
* string; a helper that assembled the URL would read as unreachable.
|
|
17
|
+
*/
|
|
18
|
+
export { COMPUTER_DAEMON_LOG_LEVELS, COMPUTER_DAEMON_LOG_LIMITS };
|
|
19
|
+
export type { ComputerDaemonLogResult };
|
|
20
|
+
export interface MachineDaemonLogQuery {
|
|
21
|
+
lines?: number;
|
|
22
|
+
sinceMs?: number;
|
|
23
|
+
level?: (typeof COMPUTER_DAEMON_LOG_LEVELS)[number];
|
|
24
|
+
}
|
|
25
|
+
export declare function getMachineDaemonLog(machineId: string, query?: MachineDaemonLogQuery): Promise<ComputerDaemonLogResult>;
|
|
26
|
+
/** `--since 90s|30m|2h|1d` as milliseconds, bounded by what the daemon will look back. */
|
|
27
|
+
export declare function parseDaemonLogSince(value: string): number;
|
|
28
|
+
/**
|
|
29
|
+
* A failed read as the sentence the command prints. `capability_missing` is the
|
|
30
|
+
* zero state: this machine's daemon predates the log, and the fix is the image.
|
|
31
|
+
* `consent_missing` is a personal machine that has not run `skrr computer allow`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function describeDaemonLogFailure(err: unknown, ctx: {
|
|
34
|
+
bin: string;
|
|
35
|
+
leaseId: string;
|
|
36
|
+
}): ComputerFileFailure | null;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.COMPUTER_DAEMON_LOG_LIMITS = exports.COMPUTER_DAEMON_LOG_LEVELS = void 0;
|
|
4
|
+
exports.getMachineDaemonLog = getMachineDaemonLog;
|
|
5
|
+
exports.parseDaemonLogSince = parseDaemonLogSince;
|
|
6
|
+
exports.describeDaemonLogFailure = describeDaemonLogFailure;
|
|
7
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
8
|
+
Object.defineProperty(exports, "COMPUTER_DAEMON_LOG_LEVELS", { enumerable: true, get: function () { return data_provider_1.COMPUTER_DAEMON_LOG_LEVELS; } });
|
|
9
|
+
Object.defineProperty(exports, "COMPUTER_DAEMON_LOG_LIMITS", { enumerable: true, get: function () { return data_provider_1.COMPUTER_DAEMON_LOG_LIMITS; } });
|
|
10
|
+
const api_fetch_1 = require("./api-fetch");
|
|
11
|
+
const computer_files_1 = require("./computer-files");
|
|
12
|
+
async function getMachineDaemonLog(machineId, query = {}) {
|
|
13
|
+
const params = new URLSearchParams();
|
|
14
|
+
if (query.lines !== undefined)
|
|
15
|
+
params.set('lines', String(query.lines));
|
|
16
|
+
if (query.sinceMs !== undefined)
|
|
17
|
+
params.set('sinceMs', String(query.sinceMs));
|
|
18
|
+
if (query.level)
|
|
19
|
+
params.set('level', query.level);
|
|
20
|
+
const qs = params.toString();
|
|
21
|
+
const suffix = qs ? `?${qs}` : '';
|
|
22
|
+
return (0, api_fetch_1.apiFetch)(`/api/machines/${encodeURIComponent(machineId)}/daemon-log` + suffix);
|
|
23
|
+
}
|
|
24
|
+
const SINCE_UNIT_MS = {
|
|
25
|
+
s: 1000,
|
|
26
|
+
m: 60_000,
|
|
27
|
+
h: 3_600_000,
|
|
28
|
+
d: 86_400_000,
|
|
29
|
+
};
|
|
30
|
+
/** `--since 90s|30m|2h|1d` as milliseconds, bounded by what the daemon will look back. */
|
|
31
|
+
function parseDaemonLogSince(value) {
|
|
32
|
+
const match = value.trim().match(/^(\d+)([smhd])$/i);
|
|
33
|
+
if (!match) {
|
|
34
|
+
throw new Error(`Invalid --since value: ${value}. Use an age such as 90s, 30m, 2h or 1d.`);
|
|
35
|
+
}
|
|
36
|
+
const ms = Number(match[1]) * SINCE_UNIT_MS[match[2].toLowerCase()];
|
|
37
|
+
if (ms < 1 || ms > data_provider_1.COMPUTER_DAEMON_LOG_LIMITS.maxSinceMs) {
|
|
38
|
+
throw new Error(`--since must be between 1s and ${data_provider_1.COMPUTER_DAEMON_LOG_LIMITS.maxSinceMs / 3_600_000}h; the daemon keeps a short, recent log.`);
|
|
39
|
+
}
|
|
40
|
+
return ms;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A failed read as the sentence the command prints. `capability_missing` is the
|
|
44
|
+
* zero state: this machine's daemon predates the log, and the fix is the image.
|
|
45
|
+
* `consent_missing` is a personal machine that has not run `skrr computer allow`.
|
|
46
|
+
*/
|
|
47
|
+
function describeDaemonLogFailure(err, ctx) {
|
|
48
|
+
const refusal = (0, computer_files_1.computerFileRefusalInfo)(err);
|
|
49
|
+
if (refusal?.code === 'capability_missing') {
|
|
50
|
+
return {
|
|
51
|
+
message: `This machine's daemon predates daemon logs, so it has none to show. ` +
|
|
52
|
+
`\`${ctx.bin} machines dedicated update-image ${ctx.leaseId}\` moves the machine onto the current image, which keeps one.`,
|
|
53
|
+
code: 'capability_missing',
|
|
54
|
+
status: refusal.status,
|
|
55
|
+
retryable: false,
|
|
56
|
+
details: refusal.body,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (refusal?.code === 'consent_missing') {
|
|
60
|
+
return {
|
|
61
|
+
message: `${refusal.message} The person who uses the machine sets this on it: \`${ctx.bin} computer allow\`.`,
|
|
62
|
+
code: 'consent_missing',
|
|
63
|
+
status: refusal.status,
|
|
64
|
+
retryable: false,
|
|
65
|
+
details: refusal.body,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (refusal?.code === 'unauthorized') {
|
|
69
|
+
return {
|
|
70
|
+
message: `${refusal.message} Reading a machine's daemon log needs at least the watch tier — see \`${ctx.bin} machines shares ${ctx.leaseId}\`.`,
|
|
71
|
+
code: 'unauthorized',
|
|
72
|
+
status: refusal.status,
|
|
73
|
+
retryable: false,
|
|
74
|
+
details: refusal.body,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return (0, computer_files_1.describeComputerFileFailure)(err, ctx);
|
|
78
|
+
}
|
package/dist/lib/node-adapter.js
CHANGED
|
@@ -18,6 +18,7 @@ const delegated_cli_1 = require("./delegated-cli");
|
|
|
18
18
|
const workspace_header_1 = require("./workspace-header");
|
|
19
19
|
const non_json_response_1 = require("./non-json-response");
|
|
20
20
|
require("./auth-core-init");
|
|
21
|
+
const rate_limit_retry_1 = require("./rate-limit-retry");
|
|
21
22
|
// ---------------------------------------------------------------------
|
|
22
23
|
// Per-process credential override — set by BaseCommand.init().
|
|
23
24
|
// Pulled out of the closure so test harnesses or long-lived callers
|
|
@@ -146,6 +147,8 @@ function createNodeAdapter(opts = {}) {
|
|
|
146
147
|
}
|
|
147
148
|
return u.toString();
|
|
148
149
|
}
|
|
150
|
+
/** The last 429's `Retry-After`, read off the response of the most recent attempt. */
|
|
151
|
+
let lastRetryAfterMs;
|
|
149
152
|
async function rawRequest(method, url, body, options, isFormData) {
|
|
150
153
|
const headers = buildHeaders(options?.headers);
|
|
151
154
|
let finalBody;
|
|
@@ -163,7 +166,10 @@ function createNodeAdapter(opts = {}) {
|
|
|
163
166
|
// OSK-12020 — a DPoP-bound hand-off token needs a fresh proof per request
|
|
164
167
|
// (and per retry: proofs are single-use). No-op for every other token.
|
|
165
168
|
Object.assign(headers, await (0, dpop_auth_1.dpopHeadersFor)(currentCredential().token, method, finalUrl));
|
|
166
|
-
|
|
169
|
+
// E6: bounded retry on 429 for a GET or an idempotency-keyed write.
|
|
170
|
+
const { response, retryAfterMs } = await (0, rate_limit_retry_1.fetchWithRateLimitRetry)(() => fetch(finalUrl, { method, headers, body: finalBody }), { method, headers });
|
|
171
|
+
lastRetryAfterMs = retryAfterMs;
|
|
172
|
+
return response;
|
|
167
173
|
}
|
|
168
174
|
/**
|
|
169
175
|
* Inner refresh: delegates to `refresh.ts`, the shared CLI refresh
|
|
@@ -359,6 +365,9 @@ function createNodeAdapter(opts = {}) {
|
|
|
359
365
|
// "which of these requests was mine" is otherwise unanswerable, and a
|
|
360
366
|
// 409 that belonged to another session was nearly filed as a CLI bug.
|
|
361
367
|
err.requestId = res.headers.get('x-request-id') || undefined;
|
|
368
|
+
if (res.status === 429 && lastRetryAfterMs !== undefined) {
|
|
369
|
+
err.retryAfterMs = lastRetryAfterMs;
|
|
370
|
+
}
|
|
362
371
|
throw err;
|
|
363
372
|
}
|
|
364
373
|
if (options?.responseType === 'arraybuffer') {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const OPEN_REF_KINDS: readonly string[];
|
|
2
|
+
export type OpenTargetErrorCode = 'OPEN_TARGET_EMPTY' | 'OPEN_TARGET_FOREIGN' | 'OPEN_TARGET_UNKNOWN';
|
|
3
|
+
export declare class OpenTargetError extends Error {
|
|
4
|
+
readonly code: OpenTargetErrorCode;
|
|
5
|
+
constructor(message: string, code: OpenTargetErrorCode);
|
|
6
|
+
}
|
|
7
|
+
export type ResolvedOpenTarget = {
|
|
8
|
+
url: string;
|
|
9
|
+
/** Which spelling was given — echoed by `--json` so a script can tell. */
|
|
10
|
+
form: 'url' | 'path' | 'ref' | 'agent';
|
|
11
|
+
};
|
|
12
|
+
export declare function resolveOpenTarget(input: string, baseURL: string): Promise<ResolvedOpenTarget>;
|