@skrr-ai/cli 0.1.95 → 0.1.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/commands/agent/message/send.d.ts +2 -0
- package/dist/commands/agent/message/send.js +75 -5
- package/dist/commands/agents/chat.js +1 -1
- package/dist/commands/agents/create.d.ts +0 -3
- package/dist/commands/agents/create.js +0 -26
- package/dist/commands/agents/egress.d.ts +17 -0
- package/dist/commands/agents/egress.js +84 -0
- package/dist/commands/agents/mailbox/messages.d.ts +14 -0
- package/dist/commands/agents/mailbox/messages.js +52 -0
- package/dist/commands/agents/mailbox/show.d.ts +13 -0
- package/dist/commands/agents/mailbox/show.js +52 -0
- package/dist/commands/agents/operating-plan.js +8 -0
- package/dist/commands/agents/roles/capture.d.ts +16 -0
- package/dist/commands/agents/roles/capture.js +53 -0
- package/dist/commands/agents/roles/install.d.ts +1 -0
- package/dist/commands/agents/roles/install.js +8 -1
- package/dist/commands/agents/roles/preview.d.ts +2 -0
- package/dist/commands/agents/roles/preview.js +27 -3
- package/dist/commands/agents/update.d.ts +0 -3
- package/dist/commands/agents/update.js +1 -31
- package/dist/commands/agents/usage-cap.d.ts +4 -1
- package/dist/commands/agents/usage-cap.js +49 -10
- package/dist/commands/code/jobs/show.js +12 -0
- package/dist/commands/commitments/action-proposals/decide.d.ts +2 -0
- package/dist/commands/commitments/action-proposals/decide.js +12 -0
- package/dist/commands/commitments/action-proposals.js +7 -0
- package/dist/commands/commitments/create.d.ts +1 -0
- package/dist/commands/commitments/create.js +17 -1
- package/dist/commands/commitments/delivery.d.ts +1 -0
- package/dist/commands/commitments/delivery.js +11 -1
- package/dist/commands/commitments/doctor.js +4 -0
- package/dist/commands/commitments/effective-policy.js +26 -0
- package/dist/commands/commitments/endpoints/create.js +5 -2
- package/dist/commands/commitments/observations.d.ts +10 -0
- package/dist/commands/commitments/observations.js +88 -0
- package/dist/commands/commitments/pause.d.ts +1 -1
- package/dist/commands/commitments/pause.js +4 -3
- package/dist/commands/commitments/preflight.js +2 -1
- package/dist/commands/commitments/reports.d.ts +2 -0
- package/dist/commands/commitments/reports.js +22 -4
- package/dist/commands/commitments/update.d.ts +1 -0
- package/dist/commands/commitments/update.js +35 -5
- package/dist/commands/grants/create.d.ts +1 -0
- package/dist/commands/grants/create.js +8 -0
- package/dist/commands/grants/rotate.d.ts +5 -0
- package/dist/commands/grants/rotate.js +13 -1
- package/dist/commands/grants/update.d.ts +12 -0
- package/dist/commands/grants/update.js +27 -0
- package/dist/commands/machines/hosted/start.js +7 -1
- package/dist/commands/machines/list.js +4 -4
- package/dist/commands/measures/confirm.d.ts +1 -7
- package/dist/commands/measures/confirm.js +15 -14
- package/dist/commands/measures/list.d.ts +1 -7
- package/dist/commands/measures/list.js +1 -7
- package/dist/commands/measures/record.js +4 -4
- package/dist/commands/measures/show.d.ts +11 -0
- package/dist/commands/measures/show.js +26 -0
- package/dist/commands/northstars/governance/configure.d.ts +1 -0
- package/dist/commands/northstars/governance/configure.js +8 -1
- package/dist/commands/proposals/discard.d.ts +5 -0
- package/dist/commands/proposals/discard.js +8 -0
- package/dist/commands/proposals/keep.d.ts +5 -0
- package/dist/commands/proposals/keep.js +8 -0
- package/dist/commands/proposals/list.d.ts +15 -0
- package/dist/commands/proposals/list.js +74 -0
- package/dist/commands/proposals/show.d.ts +12 -0
- package/dist/commands/proposals/show.js +27 -0
- package/dist/commands/proposals/snooze.d.ts +5 -0
- package/dist/commands/proposals/snooze.js +8 -0
- package/dist/commands/signals/monitors/create.d.ts +9 -0
- package/dist/commands/signals/monitors/create.js +29 -0
- package/dist/commands/signals/monitors/list.d.ts +8 -0
- package/dist/commands/signals/monitors/list.js +16 -0
- package/dist/commands/signals/monitors/pause.d.ts +11 -0
- package/dist/commands/signals/monitors/pause.js +17 -0
- package/dist/commands/signals/monitors/resume.d.ts +11 -0
- package/dist/commands/signals/monitors/resume.js +17 -0
- package/dist/commands/signals/monitors/revise.d.ts +12 -0
- package/dist/commands/signals/monitors/revise.js +25 -0
- package/dist/commands/signals/monitors/show.d.ts +11 -0
- package/dist/commands/signals/monitors/show.js +17 -0
- package/dist/commands/signals/monitors/test.d.ts +12 -0
- package/dist/commands/signals/monitors/test.js +25 -0
- package/dist/commands/signals/monitors/transitions.d.ts +11 -0
- package/dist/commands/signals/monitors/transitions.js +17 -0
- package/dist/commands/signals/monitors/validate.d.ts +9 -0
- package/dist/commands/signals/monitors/validate.js +24 -0
- package/dist/commands/signals/schemas/list.d.ts +8 -0
- package/dist/commands/signals/schemas/list.js +16 -0
- package/dist/commands/signals/schemas/show.d.ts +11 -0
- package/dist/commands/signals/schemas/show.js +17 -0
- package/dist/commands/signals/sources/list.d.ts +8 -0
- package/dist/commands/signals/sources/list.js +16 -0
- package/dist/commands/signals/sources/receipts.d.ts +11 -0
- package/dist/commands/signals/sources/receipts.js +17 -0
- package/dist/commands/signals/sources/show.d.ts +11 -0
- package/dist/commands/signals/sources/show.js +17 -0
- package/dist/commands/spaces/usage.d.ts +12 -0
- package/dist/commands/spaces/usage.js +28 -0
- package/dist/commands/spaces/workflows/run.js +3 -0
- package/dist/commands/spaces/workflows/runs.js +2 -1
- package/dist/commands/spaces/workflows/update.d.ts +6 -1
- package/dist/commands/spaces/workflows/update.js +34 -2
- package/dist/commands/tasks/cascade-status.d.ts +2 -0
- package/dist/commands/tasks/cascade-status.js +27 -1
- package/dist/commands/tasks/create.d.ts +4 -0
- package/dist/commands/tasks/create.js +16 -0
- package/dist/commands/tasks/deliverable/add.js +12 -3
- package/dist/commands/tasks/economics-compare.d.ts +15 -0
- package/dist/commands/tasks/economics-compare.js +60 -0
- package/dist/commands/tasks/expectations/evaluate.d.ts +13 -0
- package/dist/commands/tasks/expectations/evaluate.js +43 -0
- package/dist/commands/tasks/list.d.ts +1 -0
- package/dist/commands/tasks/list.js +44 -1
- package/dist/commands/tasks/show.d.ts +5 -0
- package/dist/commands/tasks/show.js +17 -0
- package/dist/commands/tasks/update.d.ts +4 -0
- package/dist/commands/tasks/update.js +9 -0
- package/dist/commands/tasks/workflow-findings.js +2 -2
- package/dist/commands/triggers/create.d.ts +2 -0
- package/dist/commands/triggers/create.js +15 -0
- package/dist/commands/workspaces/grants.d.ts +12 -0
- package/dist/commands/workspaces/grants.js +31 -0
- package/dist/commands/workspaces/stewardship.d.ts +13 -0
- package/dist/commands/workspaces/stewardship.js +34 -0
- package/dist/lib/agent-config.d.ts +0 -12
- package/dist/lib/agent-config.js +1 -27
- package/dist/lib/agent-mailbox.d.ts +35 -0
- package/dist/lib/agent-mailbox.js +55 -0
- package/dist/lib/commitment-endpoints.d.ts +2 -1
- package/dist/lib/commitment-endpoints.js +2 -5
- package/dist/lib/commitment-product.d.ts +3 -1
- package/dist/lib/commitment-product.js +10 -0
- package/dist/lib/commitment-terms.js +1 -1
- package/dist/lib/commitments.d.ts +17 -7
- package/dist/lib/commitments.js +173 -85
- package/dist/lib/compasses.d.ts +14 -0
- package/dist/lib/compasses.js +25 -11
- package/dist/lib/grants.d.ts +5 -1
- package/dist/lib/grants.js +9 -1
- package/dist/lib/hosted-machines.d.ts +7 -0
- package/dist/lib/mailbox-human-command.d.ts +11 -0
- package/dist/lib/mailbox-human-command.js +41 -0
- package/dist/lib/measures.d.ts +28 -2
- package/dist/lib/measures.js +38 -14
- package/dist/lib/message-intent.d.ts +6 -2
- package/dist/lib/message-intent.js +1 -0
- package/dist/lib/northstars.js +2 -1
- package/dist/lib/proposal-decision-command.d.ts +19 -0
- package/dist/lib/proposal-decision-command.js +64 -0
- package/dist/lib/proposals.d.ts +8 -0
- package/dist/lib/proposals.js +22 -0
- package/dist/lib/roles.d.ts +141 -6
- package/dist/lib/roles.js +8 -2
- package/dist/lib/signals.d.ts +20 -0
- package/dist/lib/signals.js +24 -0
- package/dist/lib/space-usage.d.ts +3 -0
- package/dist/lib/space-usage.js +17 -0
- package/dist/lib/stewardship-output.d.ts +4 -0
- package/dist/lib/stewardship-output.js +82 -0
- package/dist/lib/task-asset-upload.d.ts +3 -1
- package/dist/lib/task-asset-upload.js +1 -0
- package/dist/lib/task-economics.d.ts +16 -0
- package/dist/lib/task-economics.js +22 -0
- package/dist/lib/triggers.d.ts +11 -3
- package/dist/lib/triggers.js +58 -1
- package/dist/lib/usage-discovery.d.ts +10 -0
- package/dist/lib/usage-discovery.js +24 -3
- package/dist/lib/workflow-run-budget.d.ts +12 -0
- package/dist/lib/workflow-run-budget.js +37 -0
- package/dist/lib/workspaces.d.ts +48 -0
- package/dist/lib/workspaces.js +8 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +14 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/githubPushRefusal.d.ts +9 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/githubPushRefusal.js +49 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +12 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/githubPushRefusal.d.ts +9 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/githubPushRefusal.js +44 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +10 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +8017 -7086
- package/oclif.manifest.json +3872 -1167
- package/package.json +22 -1
package/README.md
CHANGED
|
@@ -15,6 +15,28 @@ skrr whoami
|
|
|
15
15
|
skrr spaces list --json
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
The CLI is the user-facing command; `skrr daemon install` downloads and verifies
|
|
19
|
+
the background runtime when needed. Installing `skrrd` alone does not install
|
|
20
|
+
the CLI. For a user-owned installation without administrator access on macOS
|
|
21
|
+
or Linux, use `npm install -g --prefix "$HOME/.local" @skrr-ai/cli` and add
|
|
22
|
+
`$HOME/.local/bin` to your shell PATH. Verify with `command -v skrr` and
|
|
23
|
+
`skrr --version` in a new terminal.
|
|
24
|
+
|
|
25
|
+
The desktop app includes the CLI and installs its `skrr` wrapper on launch,
|
|
26
|
+
using its bundled interpreter so no separate Node.js installation is needed.
|
|
27
|
+
If your terminal cannot find it, choose **Help > Set Up skrr Command…**.
|
|
28
|
+
This verifies your shell, offers Unix PATH setup, and can copy the full command.
|
|
29
|
+
Existing commands owned by npm or another installer are preserved. Desktop
|
|
30
|
+
updates maintain the bundled wrapper; npm maintains npm installations.
|
|
31
|
+
|
|
32
|
+
The script installer sets up both `skrr` and the signed `skrrd` runtime by
|
|
33
|
+
default and requires Node.js 20+ with npm. To repair a machine that already has
|
|
34
|
+
the runtime, run `bash scripts/install-daemon.sh --cli-only` from this checkout.
|
|
35
|
+
Use `--daemon-only` for runtime images without npm. On Windows the equivalent
|
|
36
|
+
runtime-only switch is `$env:SKRR_INSTALL_DAEMON_ONLY='1'` before running
|
|
37
|
+
`install-daemon.ps1`. These installers use a user-owned npm prefix and leave
|
|
38
|
+
the system/global npm configuration unchanged.
|
|
39
|
+
|
|
18
40
|
`login` first tries a signed-in local daemon, then browser PKCE, then a device code when the callback cannot run. With SSH or no local browser, use `skrr login --device-code`; approve it in a browser on another device. Password, MFA, passkey and configured federation challenges remain on the web sign-in page. The CLI has no password flag.
|
|
19
41
|
|
|
20
42
|
To create your first Task in an existing Space, copy its ID from `spaces list` and run:
|
|
@@ -85,6 +85,8 @@ export default class AgentMessageSend extends BaseCommand {
|
|
|
85
85
|
part: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
86
86
|
'message-lint': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
87
87
|
destination: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
88
|
+
to: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
89
|
+
subject: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
88
90
|
channel: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
89
91
|
'thread-ts': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
90
92
|
'thread-root': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -114,6 +114,11 @@ class AgentMessageSend extends base_command_1.BaseCommand {
|
|
|
114
114
|
description: 'Destination kind for the canonical intent',
|
|
115
115
|
options: [...message_intent_1.CANONICAL_DESTINATION_KINDS],
|
|
116
116
|
}),
|
|
117
|
+
to: core_1.Flags.string({
|
|
118
|
+
description: 'Recipient email address; repeat for up to 5 recipients',
|
|
119
|
+
multiple: true,
|
|
120
|
+
}),
|
|
121
|
+
subject: core_1.Flags.string({ description: 'Plain email subject (agent_email only)' }),
|
|
117
122
|
channel: core_1.Flags.string({
|
|
118
123
|
description: 'Slack channel ID (only meaningful with --destination slack_channel)',
|
|
119
124
|
}),
|
|
@@ -178,6 +183,8 @@ class AgentMessageSend extends base_command_1.BaseCommand {
|
|
|
178
183
|
agentId: flags.agent,
|
|
179
184
|
text: flags.text,
|
|
180
185
|
destinationKind: flags.destination,
|
|
186
|
+
recipients: flags.to,
|
|
187
|
+
subject: flags.subject,
|
|
181
188
|
channelId: flags.channel,
|
|
182
189
|
threadTs: flags['thread-ts'],
|
|
183
190
|
threadRootMessageId: flags['thread-root'],
|
|
@@ -497,6 +504,9 @@ class AgentMessageSend extends base_command_1.BaseCommand {
|
|
|
497
504
|
},
|
|
498
505
|
});
|
|
499
506
|
}
|
|
507
|
+
if (request.destination.kind === 'agent_email') {
|
|
508
|
+
this.error('Agent email is available only through an authorized Agent session.');
|
|
509
|
+
}
|
|
500
510
|
// slack_owner_dm is a Gateway-only destination: it applies workspace-scoped
|
|
501
511
|
// owner routing that no legacy human transport can enact.
|
|
502
512
|
this.failWithCliError({
|
|
@@ -538,6 +548,14 @@ function messageSegmentationAdvisory({ destination, text, followingParts, }) {
|
|
|
538
548
|
* from one explicit semantic idempotency key.
|
|
539
549
|
*/
|
|
540
550
|
function buildSequencedRequests(request, followingParts, hasExplicitIdempotencyKey) {
|
|
551
|
+
if (request.destination.kind === 'agent_email') {
|
|
552
|
+
if (followingParts.length)
|
|
553
|
+
throw invalidIntent('Email accepts one plain-text body; --part is not supported.');
|
|
554
|
+
requireText(request.content.text, 'content.text', 20 * 1024);
|
|
555
|
+
if (Buffer.byteLength(request.content.text, 'utf8') > 20 * 1024)
|
|
556
|
+
throw invalidIntent('Email body exceeds 20 KiB.');
|
|
557
|
+
return [request];
|
|
558
|
+
}
|
|
541
559
|
const parts = [request.content.text, ...followingParts].map((part) => requireText(part, 'part'));
|
|
542
560
|
if (parts.length === 1)
|
|
543
561
|
return [request];
|
|
@@ -586,6 +604,8 @@ const DELIVERY_FAILURE_STATUSES = new Set([
|
|
|
586
604
|
'dropped',
|
|
587
605
|
'expired',
|
|
588
606
|
'cancelled',
|
|
607
|
+
'unknown',
|
|
608
|
+
'refused',
|
|
589
609
|
]);
|
|
590
610
|
/**
|
|
591
611
|
* Exit codes for a submitted-but-undelivered message.
|
|
@@ -723,8 +743,18 @@ function normalizeIntentPayload({ agentId, jsonBody, merged, }) {
|
|
|
723
743
|
bodyDestination,
|
|
724
744
|
overlayChannel,
|
|
725
745
|
overlayThreadTs,
|
|
746
|
+
overlayRecipients: merged.recipients,
|
|
747
|
+
overlaySubject: merged.subject,
|
|
726
748
|
});
|
|
727
|
-
const text = requireText(readTextField(jsonBody, merged), 'content.text');
|
|
749
|
+
const text = requireText(readTextField(jsonBody, merged), 'content.text', destination.kind === 'agent_email' ? 20 * 1024 : MAX_TEXT_CHARS);
|
|
750
|
+
if (destination.kind === 'agent_email') {
|
|
751
|
+
if (Buffer.byteLength(text, 'utf8') > 20 * 1024)
|
|
752
|
+
throw invalidIntent('Email body exceeds 20 KiB.');
|
|
753
|
+
const forbidden = ['from', 'cc', 'bcc', 'html', 'attachments', 'headers', 'replyTo'];
|
|
754
|
+
const content = jsonBody.content;
|
|
755
|
+
if (forbidden.some((key) => jsonBody[key] !== undefined || content?.[key] !== undefined))
|
|
756
|
+
throw invalidIntent('Agent email accepts plain text only; sender and headers are server-owned.');
|
|
757
|
+
}
|
|
728
758
|
const idempotencyKey = optionalIdempotencyKey(merged.idempotencyKey ??
|
|
729
759
|
jsonBody.idempotencyKey ??
|
|
730
760
|
jsonBody['idempotency_key'] ??
|
|
@@ -778,10 +808,38 @@ function pickDestinationKind({ bodyDestination, overlayKind, }) {
|
|
|
778
808
|
}
|
|
779
809
|
throw invalidIntent(`destination.kind must be one of ${message_intent_1.CANONICAL_DESTINATION_KINDS.join(', ')} (got "${normalized}").`);
|
|
780
810
|
}
|
|
781
|
-
function buildDestination({ kind, bodyDestination, overlayChannel, overlayThreadTs, }) {
|
|
811
|
+
function buildDestination({ kind, bodyDestination, overlayChannel, overlayThreadTs, overlayRecipients, overlaySubject, }) {
|
|
782
812
|
if (kind === 'app_owner_dm' || kind === 'slack_owner_dm') {
|
|
783
813
|
return { kind };
|
|
784
814
|
}
|
|
815
|
+
if (kind === 'agent_email') {
|
|
816
|
+
const source = bodyDestination;
|
|
817
|
+
if (source &&
|
|
818
|
+
Object.keys(source).some((key) => !['kind', 'recipients', 'subject'].includes(key))) {
|
|
819
|
+
throw invalidIntent('agent_email accepts only recipients and subject.');
|
|
820
|
+
}
|
|
821
|
+
const rawRecipients = overlayRecipients ?? source?.recipients;
|
|
822
|
+
if (!Array.isArray(rawRecipients) || rawRecipients.length < 1 || rawRecipients.length > 5) {
|
|
823
|
+
throw invalidIntent('agent_email requires 1 to 5 recipients.');
|
|
824
|
+
}
|
|
825
|
+
const recipients = rawRecipients.map((value) => {
|
|
826
|
+
if (typeof value !== 'string' ||
|
|
827
|
+
value.length > 254 ||
|
|
828
|
+
!/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(value))
|
|
829
|
+
throw invalidIntent('Invalid email recipient.');
|
|
830
|
+
return value.toLowerCase();
|
|
831
|
+
});
|
|
832
|
+
if (new Set(recipients).size !== recipients.length)
|
|
833
|
+
throw invalidIntent('Email recipients must be distinct.');
|
|
834
|
+
const subject = overlaySubject ?? source?.subject;
|
|
835
|
+
if (typeof subject !== 'string' ||
|
|
836
|
+
!subject.trim() ||
|
|
837
|
+
subject.length > 200 ||
|
|
838
|
+
// eslint-disable-next-line no-control-regex -- Reject control characters in mail headers.
|
|
839
|
+
/[\r\n\x00-\x1f\x7f]/.test(subject))
|
|
840
|
+
throw invalidIntent('Email subject must be a single line of at most 200 characters.');
|
|
841
|
+
return { kind, recipients: recipients.sort(), subject: subject.trim() };
|
|
842
|
+
}
|
|
785
843
|
const channelId = optionalString(overlayChannel ?? bodyDestination?.channelId);
|
|
786
844
|
if (!channelId) {
|
|
787
845
|
throw invalidIntent('slack_channel destinations require destination.channelId.');
|
|
@@ -905,6 +963,16 @@ function booleanFlagInput(argv, name, parsedValue) {
|
|
|
905
963
|
}
|
|
906
964
|
function canonicalIntentFromDestination({ agentId, idempotencyKey, destination, text, presentation, notificationPolicy, context, threadRootMessageId, embeds, }) {
|
|
907
965
|
switch (destination.kind) {
|
|
966
|
+
case 'agent_email':
|
|
967
|
+
return {
|
|
968
|
+
protocolVersion: 1,
|
|
969
|
+
agentId,
|
|
970
|
+
intentType: 'status_update',
|
|
971
|
+
destination,
|
|
972
|
+
content: { text },
|
|
973
|
+
idempotencyKey,
|
|
974
|
+
...(context ? { context } : {}),
|
|
975
|
+
};
|
|
908
976
|
case 'app_owner_dm':
|
|
909
977
|
return (0, message_intent_1.canonicalAppOwnerDmRequest)({
|
|
910
978
|
agentId,
|
|
@@ -947,13 +1015,13 @@ function resolveAgentInput(argValue, flagValue, merged, jsonBody) {
|
|
|
947
1015
|
{ label: 'agentId in JSON input', value: fromBody ?? fromMerged },
|
|
948
1016
|
]);
|
|
949
1017
|
}
|
|
950
|
-
function requireText(value, field) {
|
|
1018
|
+
function requireText(value, field, maxChars = MAX_TEXT_CHARS) {
|
|
951
1019
|
if (typeof value !== 'string' || !value.trim()) {
|
|
952
1020
|
throw invalidIntent(`${field} is required.`);
|
|
953
1021
|
}
|
|
954
1022
|
const normalized = value.trim();
|
|
955
|
-
if (normalized.length >
|
|
956
|
-
throw invalidIntent(`${field} must be ${
|
|
1023
|
+
if (normalized.length > maxChars) {
|
|
1024
|
+
throw invalidIntent(`${field} must be ${maxChars} characters or less.`);
|
|
957
1025
|
}
|
|
958
1026
|
return normalized;
|
|
959
1027
|
}
|
|
@@ -1043,6 +1111,8 @@ function formatEnvelope(envelope) {
|
|
|
1043
1111
|
return `Agent message intent for ${envelope.agent.id} → ${destination}: ${status}${suffix}.${presentation}`;
|
|
1044
1112
|
}
|
|
1045
1113
|
function describeDestination(destination) {
|
|
1114
|
+
if (destination.kind === 'agent_email')
|
|
1115
|
+
return `agent_email:${destination.recipients.join(', ')}`;
|
|
1046
1116
|
if (destination.kind === 'slack_channel') {
|
|
1047
1117
|
return `slack_channel:${destination.channelId}${destination.threadTs ? `:${destination.threadTs}` : ''}`;
|
|
1048
1118
|
}
|
|
@@ -594,7 +594,7 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
594
594
|
'status is not managed for you. The runtime session is bound to this task for ' +
|
|
595
595
|
'task context and artifact uploads; use the canonical id above.',
|
|
596
596
|
].join('\n');
|
|
597
|
-
if (!flags.jsonl) {
|
|
597
|
+
if (!flags.jsonl && !flags.json) {
|
|
598
598
|
this.log(`Bound to task ${task.identifier ?? taskId} (chat turn — task not checked out)`);
|
|
599
599
|
}
|
|
600
600
|
}
|
|
@@ -124,9 +124,6 @@ export default class AgentsCreate extends BaseCommand {
|
|
|
124
124
|
avatar: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
125
125
|
'conversation-starter': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
126
126
|
'todo-working-hours': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
127
|
-
'reasoning-tool-escape': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
128
|
-
'commitment-responsibility': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
129
|
-
'commitment-responsibility-ceiling': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
130
127
|
'max-turns': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
131
128
|
'tool-resources': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
132
129
|
'install-channel': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -280,32 +280,6 @@ class AgentsCreate extends base_command_1.BaseCommand {
|
|
|
280
280
|
description: 'When this agent schedules its own work: HH:MM-HH:MM[@<IANA timezone>], e.g. ' +
|
|
281
281
|
'09:00-18:00@America/Los_Angeles',
|
|
282
282
|
}),
|
|
283
|
-
// Retired (OSK-11975): a Commitment turn works under the Agent's own
|
|
284
|
-
// permissions. Hidden, warned on use, and never sent (OSK-12068) — see
|
|
285
|
-
// `mergeAgentConfigFlags`. Kept parseable so an old script still runs.
|
|
286
|
-
'reasoning-tool-escape': core_1.Flags.string({
|
|
287
|
-
description: "Retired — has no effect and is not sent. Commitment runs use the agent's own permissions.",
|
|
288
|
-
options: [...agent_config_1.REASONING_TOOL_ESCAPES],
|
|
289
|
-
multiple: true,
|
|
290
|
-
deprecated: { message: (0, agent_config_1.retiredCommitmentPermissionFlagMessage)('reasoning-tool-escape') },
|
|
291
|
-
hidden: true,
|
|
292
|
-
}),
|
|
293
|
-
'commitment-responsibility': core_1.Flags.string({
|
|
294
|
-
description: "Retired — has no effect and is not sent. Commitment runs use the agent's own permissions.",
|
|
295
|
-
options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
|
|
296
|
-
deprecated: {
|
|
297
|
-
message: (0, agent_config_1.retiredCommitmentPermissionFlagMessage)('commitment-responsibility'),
|
|
298
|
-
},
|
|
299
|
-
hidden: true,
|
|
300
|
-
}),
|
|
301
|
-
'commitment-responsibility-ceiling': core_1.Flags.string({
|
|
302
|
-
description: "Retired — has no effect and is not sent. Commitment runs use the agent's own permissions.",
|
|
303
|
-
options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
|
|
304
|
-
deprecated: {
|
|
305
|
-
message: (0, agent_config_1.retiredCommitmentPermissionFlagMessage)('commitment-responsibility-ceiling'),
|
|
306
|
-
},
|
|
307
|
-
hidden: true,
|
|
308
|
-
}),
|
|
309
283
|
'max-turns': core_1.Flags.integer({ description: 'Maximum turns in one agent run (1-500)' }),
|
|
310
284
|
'tool-resources': core_1.Flags.string({
|
|
311
285
|
description: 'Tool resources JSON object (file_search / context / image_edit bindings)',
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export default class AgentsEgress extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static flags: {
|
|
8
|
+
allow: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
remove: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
repo: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
'remove-repo': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
clear: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../base-command");
|
|
6
|
+
class AgentsEgress extends base_command_1.BaseCommand {
|
|
7
|
+
static description = 'Show or declare the exact hosts and repositories a hosted agent may use on its next start';
|
|
8
|
+
static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
|
|
9
|
+
static flags = {
|
|
10
|
+
allow: core_1.Flags.string({ multiple: true, exclusive: ['clear'] }),
|
|
11
|
+
remove: core_1.Flags.string({ multiple: true, exclusive: ['clear'] }),
|
|
12
|
+
repo: core_1.Flags.string({
|
|
13
|
+
multiple: true,
|
|
14
|
+
exclusive: ['clear'],
|
|
15
|
+
description: 'Allow a repository (owner/name) for Hosted Jobs',
|
|
16
|
+
}),
|
|
17
|
+
'remove-repo': core_1.Flags.string({ multiple: true, exclusive: ['clear'] }),
|
|
18
|
+
reason: core_1.Flags.string({ exclusive: ['clear'] }),
|
|
19
|
+
clear: core_1.Flags.boolean({
|
|
20
|
+
exclusive: ['allow', 'remove', 'repo', 'remove-repo', 'reason'],
|
|
21
|
+
description: 'Delete the whole declaration: hosts and repositories',
|
|
22
|
+
}),
|
|
23
|
+
json: core_1.Flags.boolean(),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
this.requireAuth();
|
|
27
|
+
const { args, flags } = await this.parse(AgentsEgress);
|
|
28
|
+
try {
|
|
29
|
+
let result = await data_provider_1.dataService.getAgentEgress(args.id);
|
|
30
|
+
if (flags.clear)
|
|
31
|
+
result = await data_provider_1.dataService.clearAgentEgress(args.id);
|
|
32
|
+
else if (flags.allow ||
|
|
33
|
+
flags.remove ||
|
|
34
|
+
flags.repo ||
|
|
35
|
+
flags['remove-repo'] ||
|
|
36
|
+
flags.reason !== undefined) {
|
|
37
|
+
const remove = new Set((0, data_provider_1.normalizeAgentEgressHosts)(flags.remove || []));
|
|
38
|
+
const hosts = (0, data_provider_1.normalizeAgentEgressHosts)([
|
|
39
|
+
...(result.declaration?.hosts || []),
|
|
40
|
+
...(flags.allow || []),
|
|
41
|
+
]).filter((host) => !remove.has(host));
|
|
42
|
+
// Repositories are sent only when this call changes them, so a hosts-only
|
|
43
|
+
// edit can never rewrite a list another surface set.
|
|
44
|
+
const touchesRepositories = Boolean(flags.repo || flags['remove-repo']);
|
|
45
|
+
const removeRepos = new Set((0, data_provider_1.normalizeAgentRepositories)(flags['remove-repo'] || []));
|
|
46
|
+
const repositories = touchesRepositories
|
|
47
|
+
? (0, data_provider_1.normalizeAgentRepositories)([
|
|
48
|
+
...(result.declaration?.repositories || []),
|
|
49
|
+
...(flags.repo || []),
|
|
50
|
+
]).filter((repository) => !removeRepos.has(repository))
|
|
51
|
+
: undefined;
|
|
52
|
+
result = await data_provider_1.dataService.setAgentEgress(args.id, {
|
|
53
|
+
hosts,
|
|
54
|
+
...(repositories ? { repositories } : {}),
|
|
55
|
+
...(flags.reason !== undefined ? { reason: flags.reason } : {}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (flags.json) {
|
|
59
|
+
this.log(JSON.stringify(result, null, 2));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const repositories = result.declaration?.repositories;
|
|
63
|
+
this.log(repositories?.length
|
|
64
|
+
? `Repositories: ${repositories.join(', ')} (Hosted Jobs and Commitment deliveries may use only these; git_commit push is not enabled in production turns and, when enabled, is bounded by them too; raw git in a shell is not limited by it)`
|
|
65
|
+
: 'Repositories: none declared (no restriction)');
|
|
66
|
+
if (!('policy' in result.effective)) {
|
|
67
|
+
this.log('Effective network unavailable: the workspace policy could not be read.');
|
|
68
|
+
this.log(data_provider_1.AGENT_EGRESS_EXPLANATION);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.log(`Network: ${result.effective.policy} (${result.effective.source}; ${result.effective.hosts.length} hosts)`);
|
|
72
|
+
this.log(result.effective.hosts.join(', '));
|
|
73
|
+
if (result.effective.droppedHosts.length)
|
|
74
|
+
this.log(`Workspace policy dropped: ${result.effective.droppedHosts.join(', ')}`);
|
|
75
|
+
if (result.effective.unreadable)
|
|
76
|
+
this.log('Declaration or ceiling unreadable: baseline only.');
|
|
77
|
+
this.log(data_provider_1.AGENT_EGRESS_EXPLANATION);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
this.handleApiError(error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = AgentsEgress;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MailboxHumanCommand } from '../../../lib/mailbox-human-command';
|
|
2
|
+
export default class AgentsMailboxMessages extends MailboxHumanCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const mailbox_human_command_1 = require("../../../lib/mailbox-human-command");
|
|
5
|
+
const agent_mailbox_1 = require("../../../lib/agent-mailbox");
|
|
6
|
+
class AgentsMailboxMessages extends mailbox_human_command_1.MailboxHumanCommand {
|
|
7
|
+
static description = 'List received mailbox message metadata (human operator only; view content in agent settings)';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> agents mailbox messages <agent-id> --json',
|
|
10
|
+
'<%= config.bin %> agents mailbox messages <agent-id> --limit 25 --cursor <cursor>',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: core_1.Args.string({ description: 'Agent ID', required: true, ignoreStdin: true }),
|
|
14
|
+
};
|
|
15
|
+
static flags = {
|
|
16
|
+
json: core_1.Flags.boolean({ description: 'Output message metadata and nextCursor as JSON' }),
|
|
17
|
+
limit: core_1.Flags.integer({
|
|
18
|
+
description: 'Messages per page (1–100)',
|
|
19
|
+
default: 25,
|
|
20
|
+
min: 1,
|
|
21
|
+
max: 100,
|
|
22
|
+
}),
|
|
23
|
+
cursor: core_1.Flags.string({ description: 'Opaque nextCursor from a previous page' }),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
this.requireHumanMailboxAuth();
|
|
27
|
+
const { args, flags } = await this.parse(AgentsMailboxMessages);
|
|
28
|
+
let result;
|
|
29
|
+
try {
|
|
30
|
+
result = await (0, agent_mailbox_1.getAgentMailboxMessageMetadata)(args.id, {
|
|
31
|
+
limit: flags.limit,
|
|
32
|
+
cursor: flags.cursor,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
this.handleApiError(error);
|
|
37
|
+
}
|
|
38
|
+
if (flags.json) {
|
|
39
|
+
this.log(JSON.stringify(result, null, 2));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (result.data.length === 0)
|
|
43
|
+
this.log('No received messages on this page.');
|
|
44
|
+
for (const message of result.data) {
|
|
45
|
+
this.log(`${message.id} ${message.receivedAt} ${message.classification} ${message.status}`);
|
|
46
|
+
}
|
|
47
|
+
if (result.nextCursor)
|
|
48
|
+
this.log(`Next cursor: ${result.nextCursor}`);
|
|
49
|
+
this.log('Read mail content in the mailbox tab in agent settings.');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.default = AgentsMailboxMessages;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { MailboxHumanCommand } from '../../../lib/mailbox-human-command';
|
|
2
|
+
export default class AgentsMailboxShow extends MailboxHumanCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static aliases: string[];
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static args: {
|
|
7
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const mailbox_human_command_1 = require("../../../lib/mailbox-human-command");
|
|
5
|
+
const agent_mailbox_1 = require("../../../lib/agent-mailbox");
|
|
6
|
+
class AgentsMailboxShow extends mailbox_human_command_1.MailboxHumanCommand {
|
|
7
|
+
static description = "Show an agent's mailbox status and address (human operator only)";
|
|
8
|
+
static aliases = ['agents:mailbox:status'];
|
|
9
|
+
static examples = [
|
|
10
|
+
'<%= config.bin %> agents mailbox show <agent-id>',
|
|
11
|
+
'<%= config.bin %> agents mailbox status <agent-id> --json',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Agent ID', required: true, ignoreStdin: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = { json: core_1.Flags.boolean({ description: 'Output metadata as JSON' }) };
|
|
17
|
+
async run() {
|
|
18
|
+
this.requireHumanMailboxAuth();
|
|
19
|
+
const { args, flags } = await this.parse(AgentsMailboxShow);
|
|
20
|
+
let result;
|
|
21
|
+
try {
|
|
22
|
+
result = await (0, agent_mailbox_1.getAgentMailboxMetadata)(args.id);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
this.handleApiError(error);
|
|
26
|
+
}
|
|
27
|
+
if (flags.json) {
|
|
28
|
+
this.log(JSON.stringify(result, null, 2));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const receiving = result.receivingRuntime?.status;
|
|
32
|
+
this.log(receiving === 'running'
|
|
33
|
+
? 'Incoming processing: running (DNS and SMTP delivery are not verified by this command).'
|
|
34
|
+
: receiving === 'starting'
|
|
35
|
+
? 'Incoming processing: starting. Refresh before using a recovery address.'
|
|
36
|
+
: receiving === 'unavailable'
|
|
37
|
+
? 'Incoming processing: unavailable. Do not use this address for account recovery until receiving is restored.'
|
|
38
|
+
: 'Incoming processing: unverified. Refresh before using a recovery address.');
|
|
39
|
+
if (!result.mailbox) {
|
|
40
|
+
this.log('No mailbox provisioned. Configure the mailbox in the agent settings.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.log(`Address: ${result.mailbox.address}`);
|
|
44
|
+
this.log(`Address lifecycle: ${result.mailbox.status}`);
|
|
45
|
+
this.log(`Sending: ${result.mailbox.sending}`);
|
|
46
|
+
if (result.mailbox.sendingPausedReason) {
|
|
47
|
+
this.log(`Sending paused: ${result.mailbox.sendingPausedReason}`);
|
|
48
|
+
}
|
|
49
|
+
this.log(`Version: ${result.mailbox.version}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.default = AgentsMailboxShow;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const roles_1 = require("../../lib/roles");
|
|
@@ -26,6 +27,13 @@ class AgentOperatingPlan extends base_command_1.BaseCommand {
|
|
|
26
27
|
this.log(` Responsibility: ${r.purpose}`);
|
|
27
28
|
this.log(` Evidence: ${r.evidence.status}${r.evidence.issues?.length ? ` (${r.evidence.issues.join(', ')})` : ''}`);
|
|
28
29
|
this.log(" Execution authority: tools, sandbox and approvals use the Agent's runtime permissions.");
|
|
30
|
+
for (const observation of r.evidenceAuthority?.observations || []) {
|
|
31
|
+
const comparison = (0, data_provider_1.describeObservationChange)({
|
|
32
|
+
...observation.serverComparison,
|
|
33
|
+
changeReason: observation.serverComparison.reason,
|
|
34
|
+
});
|
|
35
|
+
this.log(` Observation: ${observation.key} — ${comparison.reason}${comparison.progress ? ` ${comparison.progress}` : ''}${comparison.reference ? `; ${comparison.reference}` : ''} (AGENT-REPORTED)`);
|
|
36
|
+
}
|
|
29
37
|
for (const q of r.inquiries)
|
|
30
38
|
this.log(` Inquiry: ${q.question} [${q.status}] — ${q.decisionImpact}`);
|
|
31
39
|
for (const w of r.work)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
export default class RolesCapture extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static flags: {
|
|
8
|
+
key: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
title: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
commitment: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
compass: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
const roles_1 = require("../../../lib/roles");
|
|
7
|
+
class RolesCapture extends base_command_1.BaseCommand {
|
|
8
|
+
static description = 'Capture selected owner responsibilities as a portable role draft with explicit omissions';
|
|
9
|
+
static args = {
|
|
10
|
+
id: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Agent ID' }),
|
|
11
|
+
};
|
|
12
|
+
static flags = {
|
|
13
|
+
key: core_1.Flags.string({ required: true, description: 'Portable role key' }),
|
|
14
|
+
title: core_1.Flags.string({ required: true, description: 'Role title' }),
|
|
15
|
+
commitment: core_1.Flags.string({
|
|
16
|
+
required: true,
|
|
17
|
+
multiple: true,
|
|
18
|
+
description: 'Responsibility ID (repeat for each)',
|
|
19
|
+
}),
|
|
20
|
+
compass: core_1.Flags.string({ description: 'Compass to capture' }),
|
|
21
|
+
output: core_1.Flags.string({ description: 'Save portable spec JSON for review' }),
|
|
22
|
+
json: core_1.Flags.boolean({ description: 'Output draft and omissions as JSON' }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
this.requireAuth();
|
|
26
|
+
const { args, flags } = await this.parse(RolesCapture);
|
|
27
|
+
try {
|
|
28
|
+
const result = await roles_1.roleApi.capture(args.id, {
|
|
29
|
+
key: flags.key,
|
|
30
|
+
title: flags.title,
|
|
31
|
+
commitmentIds: flags.commitment,
|
|
32
|
+
...(flags.compass ? { compassId: flags.compass } : {}),
|
|
33
|
+
});
|
|
34
|
+
if (flags.output)
|
|
35
|
+
(0, node_fs_1.writeFileSync)(flags.output, `${JSON.stringify(result.spec, null, 2)}\n`, { mode: 0o600 });
|
|
36
|
+
if (flags.json) {
|
|
37
|
+
this.log(JSON.stringify(result, null, 2));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.log(`Captured ${result.spec.title}; review before installation.`);
|
|
41
|
+
for (const omission of result.omitted)
|
|
42
|
+
this.log(`Omitted ${omission.responsibilityKey || 'role'}.${omission.field}: ${omission.reason}`);
|
|
43
|
+
for (const prerequisite of result.prerequisites)
|
|
44
|
+
this.log(prerequisite);
|
|
45
|
+
if (flags.output)
|
|
46
|
+
this.log(`Portable draft saved to ${flags.output}.`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.handleApiError(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.default = RolesCapture;
|
|
@@ -6,6 +6,7 @@ export default class RolesInstall extends BaseCommand {
|
|
|
6
6
|
};
|
|
7
7
|
static flags: {
|
|
8
8
|
preview: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
'confirm-rule-conflict': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
10
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
11
|
};
|
|
11
12
|
run(): Promise<void>;
|
|
@@ -13,6 +13,10 @@ class RolesInstall extends base_command_1.BaseCommand {
|
|
|
13
13
|
required: true,
|
|
14
14
|
description: 'Server-generated preview JSON saved by agents roles preview',
|
|
15
15
|
}),
|
|
16
|
+
'confirm-rule-conflict': core_1.Flags.string({
|
|
17
|
+
multiple: true,
|
|
18
|
+
description: 'Rule id the role revision changed or removes and you also edited: overwrite or delete your edit (shown as conflicts_with_owner_edit or removed_owner_edited in the preview)',
|
|
19
|
+
}),
|
|
16
20
|
json: core_1.Flags.boolean({ description: 'Output the installation receipt as JSON' }),
|
|
17
21
|
};
|
|
18
22
|
async run() {
|
|
@@ -21,7 +25,10 @@ class RolesInstall extends base_command_1.BaseCommand {
|
|
|
21
25
|
try {
|
|
22
26
|
const preview = (0, roles_1.readRoleJson)(flags.preview);
|
|
23
27
|
(0, roles_1.assertRolePreview)(preview);
|
|
24
|
-
const
|
|
28
|
+
const confirmed = flags['confirm-rule-conflict'] ?? [];
|
|
29
|
+
const receipt = confirmed.length
|
|
30
|
+
? await roles_1.roleApi.install(args.id, preview, confirmed)
|
|
31
|
+
: await roles_1.roleApi.install(args.id, preview);
|
|
25
32
|
if (flags.json)
|
|
26
33
|
this.log(JSON.stringify(receipt, null, 2));
|
|
27
34
|
else {
|
|
@@ -6,6 +6,8 @@ export default class RolesPreview extends BaseCommand {
|
|
|
6
6
|
};
|
|
7
7
|
static flags: {
|
|
8
8
|
file: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
params: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
endpoints: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
11
|
bindings: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
12
|
output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
13
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|