@skrr-ai/cli 0.1.104 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.js +6 -2
- package/dist/commands/agenda/trigger/list.js +2 -0
- package/dist/commands/agents/chat.js +4 -1
- package/dist/commands/agents/operating-plan.js +5 -2
- package/dist/commands/agents/triggers/create.js +3 -1
- package/dist/commands/agents/triggers/fire.js +2 -0
- package/dist/commands/agents/triggers/replay.js +2 -0
- package/dist/commands/agents/triggers/update.js +12 -4
- package/dist/commands/commitments/action-history.js +7 -2
- package/dist/commands/commitments/cadence-decisions.js +6 -1
- package/dist/commands/commitments/cadence-requests/decide.d.ts +1 -1
- package/dist/commands/commitments/cadence-requests/decide.js +1 -1
- package/dist/commands/commitments/doctor.js +7 -1
- package/dist/commands/commitments/observations.js +7 -1
- package/dist/commands/commitments/operating-review.d.ts +15 -0
- package/dist/commands/commitments/operating-review.js +23 -2
- package/dist/commands/commitments/preflight.d.ts +12 -0
- package/dist/commands/commitments/preflight.js +23 -9
- package/dist/commands/commitments/reflection.js +6 -1
- package/dist/commands/commitments/show.js +3 -1
- package/dist/commands/commitments/trigger-status.js +2 -22
- package/dist/commands/commitments/wake-capabilities.d.ts +13 -0
- package/dist/commands/commitments/wake-capabilities.js +39 -3
- package/dist/commands/daemon/logs.d.ts +41 -3
- package/dist/commands/daemon/logs.js +202 -17
- package/dist/commands/followups/act.js +13 -1
- package/dist/commands/followups/checkin.js +11 -2
- package/dist/commands/followups/reschedule.js +13 -1
- package/dist/commands/proposals/discard.d.ts +1 -1
- package/dist/commands/proposals/keep.d.ts +1 -1
- package/dist/commands/proposals/list.d.ts +7 -0
- package/dist/commands/proposals/list.js +31 -5
- package/dist/commands/proposals/show.d.ts +2 -1
- package/dist/commands/proposals/show.js +31 -4
- package/dist/commands/proposals/snooze.d.ts +1 -1
- package/dist/commands/requests/create.js +8 -3
- package/dist/commands/spaces/workflows/create.js +3 -3
- package/dist/commands/tasks/complete.js +4 -0
- package/dist/commands/tasks/create.d.ts +2 -0
- package/dist/commands/tasks/create.js +17 -3
- package/dist/commands/tasks/deliverable/add.d.ts +2 -0
- package/dist/commands/tasks/deliverable/add.js +22 -7
- package/dist/commands/tasks/deliverable/list.d.ts +13 -0
- package/dist/commands/tasks/deliverable/list.js +34 -1
- package/dist/commands/tasks/economics-compare.js +7 -1
- package/dist/commands/tasks/expectations.d.ts +10 -0
- package/dist/commands/tasks/expectations.js +31 -3
- package/dist/commands/tasks/list.d.ts +9 -0
- package/dist/commands/tasks/list.js +40 -5
- package/dist/commands/tasks/report.js +1 -1
- package/dist/commands/tasks/result/show.d.ts +7 -0
- package/dist/commands/tasks/result/show.js +32 -1
- package/dist/commands/tasks/result/submit.js +1 -1
- package/dist/commands/tasks/show.d.ts +6 -0
- package/dist/commands/tasks/show.js +23 -0
- package/dist/commands/tasks/update.d.ts +3 -0
- package/dist/commands/tasks/update.js +23 -3
- package/dist/commands/triggers/audit.js +6 -2
- package/dist/commands/triggers/create.js +3 -1
- package/dist/commands/triggers/fire.d.ts +1 -0
- package/dist/commands/triggers/fire.js +16 -1
- package/dist/commands/triggers/preflight.js +6 -5
- package/dist/commands/triggers/replay.js +2 -0
- package/dist/commands/triggers/update.js +12 -4
- package/dist/commands/workspaces/stewardship.js +5 -1
- package/dist/lib/agentic-stream.d.ts +9 -0
- package/dist/lib/agentic-stream.js +38 -18
- package/dist/lib/commitment-event-wakes.d.ts +8 -0
- package/dist/lib/commitment-event-wakes.js +39 -0
- package/dist/lib/commitment-ledgers.d.ts +9 -0
- package/dist/lib/commitment-ledgers.js +126 -0
- package/dist/lib/commitments.d.ts +102 -2
- package/dist/lib/commitments.js +208 -8
- package/dist/lib/delegated-cli.js +13 -2
- package/dist/lib/followups.d.ts +6 -0
- package/dist/lib/followups.js +12 -0
- package/dist/lib/message-content.d.ts +6 -0
- package/dist/lib/message-content.js +24 -0
- package/dist/lib/operating-plan-loops.d.ts +8 -0
- package/dist/lib/operating-plan-loops.js +32 -0
- package/dist/lib/preflight-copy.d.ts +27 -0
- package/dist/lib/preflight-copy.js +89 -0
- package/dist/lib/proposal-decision-command.d.ts +1 -1
- package/dist/lib/proposal-decision-command.js +27 -3
- package/dist/lib/proposals.d.ts +17 -0
- package/dist/lib/proposals.js +41 -0
- package/dist/lib/stewardship-output.js +57 -12
- package/dist/lib/task-economics-line.d.ts +30 -0
- package/dist/lib/task-economics-line.js +49 -0
- package/dist/lib/task-economics.d.ts +15 -0
- package/dist/lib/task-economics.js +73 -8
- package/dist/lib/task-recurrence-outcome.d.ts +19 -0
- package/dist/lib/task-recurrence-outcome.js +30 -0
- package/dist/lib/triggers.d.ts +42 -0
- package/dist/lib/triggers.js +136 -2
- package/dist/lib/widgetTerminalText.d.ts +8 -0
- package/dist/lib/widgetTerminalText.js +116 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +27 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.d.ts +28 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +50 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +26 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.d.ts +28 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +50 -5
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7261 -7056
- package/docs/v1/operations.md +1 -1
- package/oclif.manifest.json +116 -72
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.taskPointerLines = taskPointerLines;
|
|
4
4
|
exports.blockerDetailLines = blockerDetailLines;
|
|
5
5
|
exports.completionLines = completionLines;
|
|
6
|
+
exports.reviewPolicyLine = reviewPolicyLine;
|
|
6
7
|
exports.labelsLine = labelsLine;
|
|
7
8
|
exports.taskExecutorLabel = taskExecutorLabel;
|
|
8
9
|
exports.recurrenceArmFailureLines = recurrenceArmFailureLines;
|
|
@@ -18,6 +19,7 @@ const web_url_1 = require("../../lib/web-url");
|
|
|
18
19
|
const html_text_1 = require("../../lib/html-text");
|
|
19
20
|
const label_ref_1 = require("../../lib/label-ref");
|
|
20
21
|
const principal_display_1 = require("../../lib/principal-display");
|
|
22
|
+
const task_economics_line_1 = require("../../lib/task-economics-line");
|
|
21
23
|
const format_1 = require("../../lib/format");
|
|
22
24
|
/**
|
|
23
25
|
* Where to look next — as COMMANDS, not as facts about the task.
|
|
@@ -108,6 +110,16 @@ function completionLines(projection, { read = true } = {}) {
|
|
|
108
110
|
: [];
|
|
109
111
|
return [`Done? ${sentence}`, ...also.map((row) => ` also: ${row.trim()}`)];
|
|
110
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* The review-policy line, or null for the default. Only a non-default policy is printed: `none` is
|
|
115
|
+
* every Task that never asked, and printing it would add a line to all of them. Without this the
|
|
116
|
+
* policy was readable in --json alone (OSK-15434).
|
|
117
|
+
*/
|
|
118
|
+
function reviewPolicyLine(policy) {
|
|
119
|
+
return policy === 'required'
|
|
120
|
+
? 'Review policy: required — closing by anyone but the author needs an accepted independent Review'
|
|
121
|
+
: null;
|
|
122
|
+
}
|
|
111
123
|
function labelsLine(labelIds, nameById) {
|
|
112
124
|
const ids = (labelIds ?? []).filter((id) => typeof id === 'string' && id.length > 0);
|
|
113
125
|
if (ids.length === 0)
|
|
@@ -466,6 +478,9 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
466
478
|
}
|
|
467
479
|
}
|
|
468
480
|
this.log(`Priority: ${t.priority ?? '-'}`);
|
|
481
|
+
const review = reviewPolicyLine(t.reviewPolicy);
|
|
482
|
+
if (review)
|
|
483
|
+
this.log(review);
|
|
469
484
|
this.log(`Parent: ${t.parentId ?? '-'}`);
|
|
470
485
|
this.log(`Space: ${t.spaceId ?? '-'}`);
|
|
471
486
|
// Printed beside Space and Goal because `--project` is accepted on create
|
|
@@ -497,6 +512,7 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
497
512
|
t.dri?.resolved?.id,
|
|
498
513
|
...(Array.isArray(t.assigneeAgentIds) ? t.assigneeAgentIds : []),
|
|
499
514
|
...(Array.isArray(t.assigneeUserIds) ? t.assigneeUserIds : []),
|
|
515
|
+
t.economics?.confirmedBy,
|
|
500
516
|
];
|
|
501
517
|
const principalNames = await (0, principal_display_1.resolvePrincipalNames)(principalIds, {
|
|
502
518
|
spaceId: t.spaceId ?? null,
|
|
@@ -516,6 +532,13 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
516
532
|
this.log(`Assignees: ${agents.length} agent(s), ${users.length} user(s)${agents.length + users.length > 0
|
|
517
533
|
? ` — ${[...agents, ...users].map((id) => (0, principal_display_1.displayPrincipal)(id, principalNames)).join(', ')}`
|
|
518
534
|
: ''}`);
|
|
535
|
+
const economics = t.economics;
|
|
536
|
+
const economicsText = (0, task_economics_line_1.economicsLine)(economics, economics?.confirmedBy ? (0, principal_display_1.displayPrincipal)(economics.confirmedBy, principalNames) : undefined);
|
|
537
|
+
if (economicsText)
|
|
538
|
+
this.log(`Economics: ${economicsText}`);
|
|
539
|
+
const rationale = economicsText ? (0, task_economics_line_1.economicsRationaleLine)(economics) : null;
|
|
540
|
+
if (rationale)
|
|
541
|
+
this.log(`Rationale: ${rationale}`);
|
|
519
542
|
const actionability = t.actionability;
|
|
520
543
|
if (actionability) {
|
|
521
544
|
this.log(actionability.state === 'terminal'
|
|
@@ -21,6 +21,8 @@ export default class TasksUpdate extends BaseCommand {
|
|
|
21
21
|
per: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
22
|
effort: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
23
|
risk: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
confidence: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
rationale: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
26
|
estimate: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
27
|
/**
|
|
26
28
|
* Declared, hidden, and refused — on purpose. (S4 dogfood finding)
|
|
@@ -43,6 +45,7 @@ export default class TasksUpdate extends BaseCommand {
|
|
|
43
45
|
*/
|
|
44
46
|
status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
45
47
|
'duplicate-of': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
48
|
+
'review-policy': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
46
49
|
goal: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
47
50
|
cycle: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
48
51
|
space: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -63,13 +63,27 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
63
63
|
}),
|
|
64
64
|
'start-date': core_1.Flags.string({ description: 'New planned start date (ISO string)' }),
|
|
65
65
|
'due-date': core_1.Flags.string({ description: 'New due date (ISO string)' }),
|
|
66
|
-
savings: core_1.Flags.string({
|
|
66
|
+
savings: core_1.Flags.string({
|
|
67
|
+
description: 'Expected USD savings (requires --per). An estimate you write as a person is recorded as Human confirmed under your name, and an Agent edit is then refused with a 409; an Agent writes an Agent estimate. Re-sending the same values changes nothing.',
|
|
68
|
+
}),
|
|
67
69
|
per: core_1.Flags.string({
|
|
68
70
|
options: ['month', 'year', 'once'],
|
|
69
71
|
description: 'Savings period (requires --savings)',
|
|
70
72
|
}),
|
|
71
|
-
effort: core_1.Flags.string({
|
|
72
|
-
|
|
73
|
+
effort: core_1.Flags.string({
|
|
74
|
+
description: 'Expected effort in hours, nonnegative (part of the estimate; see --savings)',
|
|
75
|
+
}),
|
|
76
|
+
risk: core_1.Flags.string({
|
|
77
|
+
options: ['low', 'medium', 'high'],
|
|
78
|
+
description: 'Expected risk (part of the estimate; see --savings)',
|
|
79
|
+
}),
|
|
80
|
+
confidence: core_1.Flags.string({
|
|
81
|
+
options: ['low', 'medium', 'high'],
|
|
82
|
+
description: 'How sure the estimate is (part of the estimate; see --savings). An earlier confidence stays on the claim until you replace it.',
|
|
83
|
+
}),
|
|
84
|
+
rationale: core_1.Flags.string({
|
|
85
|
+
description: 'Why the estimate is what it is, up to 500 characters (part of the estimate). An earlier rationale stays on the claim, under its new basis, until you replace it.',
|
|
86
|
+
}),
|
|
73
87
|
estimate: core_1.Flags.integer({
|
|
74
88
|
description: 'New estimate value from the Space estimate scale. Requires a scale on the Space (or an ' +
|
|
75
89
|
'ancestor it inherits from); with none set, the server drops the value. Set the scale ' +
|
|
@@ -101,6 +115,11 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
101
115
|
'duplicate-of': core_1.Flags.string({
|
|
102
116
|
description: 'Mark this task as a duplicate of the canonical task (merges collaboration)',
|
|
103
117
|
}),
|
|
118
|
+
'review-policy': core_1.Flags.string({
|
|
119
|
+
options: ['none', 'required'],
|
|
120
|
+
description: "Raise or lower the review bar: 'required' means closing this Task needs someone other than the " +
|
|
121
|
+
"Result author to accept it, 'none' (the default) does not. Not a specification change.",
|
|
122
|
+
}),
|
|
104
123
|
// Goal and space moves live here; status and PROJECT moves live on
|
|
105
124
|
// `tasks move`. Nothing said so, and these two flags read as the complete
|
|
106
125
|
// set of "move this task somewhere" options — which is how a reader
|
|
@@ -405,6 +424,7 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
405
424
|
driAgentId: flags['dri-agent'],
|
|
406
425
|
driUserId: flags['dri-user'],
|
|
407
426
|
executionMode: flags['execution-mode'],
|
|
427
|
+
reviewPolicy: flags['review-policy'],
|
|
408
428
|
addAssigneeAgentIds: flags['add-assignee-agent'],
|
|
409
429
|
removeAssigneeAgentIds: flags['remove-assignee-agent'],
|
|
410
430
|
addAssigneeUserIds: flags['add-assignee-user'],
|
|
@@ -24,8 +24,12 @@ class TriggersAudit extends base_command_1.BaseCommand {
|
|
|
24
24
|
trigger: core_1.Flags.string({ description: 'Trigger ID filter for owner-wide audit history' }),
|
|
25
25
|
agent: core_1.Flags.string({ description: 'Agent ID filter for owner-wide audit history' }),
|
|
26
26
|
scope: core_1.Flags.string({ description: 'Scope kind filter for owner-wide audit history' }),
|
|
27
|
-
outcome: core_1.Flags.string({
|
|
28
|
-
|
|
27
|
+
outcome: core_1.Flags.string({
|
|
28
|
+
description: 'Outcome filter for owner-wide audit history (succeeded, failed, skipped, incomplete, capped, ...); an unknown value is refused with the full list',
|
|
29
|
+
}),
|
|
30
|
+
source: core_1.Flags.string({
|
|
31
|
+
description: 'Source filter for owner-wide audit history (schedule, once, event, manual, webhook, replay, ...); an unknown value is refused with the full list',
|
|
32
|
+
}),
|
|
29
33
|
};
|
|
30
34
|
async run() {
|
|
31
35
|
this.requireAuth();
|
|
@@ -98,7 +98,9 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
98
98
|
'end-at': core_1.Flags.string({
|
|
99
99
|
description: 'ISO-8601 datetime after which a schedule stops firing',
|
|
100
100
|
}),
|
|
101
|
-
'stale-catchup-ms': core_1.Flags.integer({
|
|
101
|
+
'stale-catchup-ms': core_1.Flags.integer({
|
|
102
|
+
description: 'How late a missed occurrence may still run, in ms (a positive number). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
|
|
103
|
+
}),
|
|
102
104
|
at: core_1.Flags.string({
|
|
103
105
|
description: 'ISO-8601 datetime for once triggers. --next-run-at is also accepted with --kind once for backwards compatibility.',
|
|
104
106
|
}),
|
|
@@ -8,6 +8,7 @@ export default class TriggersFire extends BaseCommand {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
strict: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -9,6 +9,7 @@ class TriggersFire extends base_command_1.BaseCommand {
|
|
|
9
9
|
static examples = [
|
|
10
10
|
'<%= config.bin %> triggers fire <trigger-id>',
|
|
11
11
|
'<%= config.bin %> triggers fire <trigger-id> --from-json fire-options.json --json',
|
|
12
|
+
'<%= config.bin %> triggers fire <trigger-id> --strict # exit 1 unless the fire succeeded',
|
|
12
13
|
];
|
|
13
14
|
static args = {
|
|
14
15
|
id: core_1.Args.string({ description: 'Trigger ID', required: true, ignoreStdin: true }),
|
|
@@ -16,7 +17,14 @@ class TriggersFire extends base_command_1.BaseCommand {
|
|
|
16
17
|
static flags = {
|
|
17
18
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
18
19
|
'from-json': core_1.Flags.string({
|
|
19
|
-
description: 'Path to a JSON file (or "-" for stdin)
|
|
20
|
+
description: 'Path to a JSON file (or "-" for stdin) of fire options. Read: occurrenceId (a key of your own; ' +
|
|
21
|
+
'firing it again is the same fire) and, for an event trigger only, event ({payload}; the ' +
|
|
22
|
+
'entity and event type come from the trigger). Any other key is ignored, and the answer names it',
|
|
23
|
+
}),
|
|
24
|
+
strict: core_1.Flags.boolean({
|
|
25
|
+
description: 'Exit 1 unless the fire was accepted (outcome succeeded, in_progress or awaiting_runtime, or a ' +
|
|
26
|
+
'repeat of one that was). A fire that resolved nothing or was refused (incomplete, skipped, ' +
|
|
27
|
+
'failed, …) exits 1 with it; without it every outcome exits 0',
|
|
20
28
|
}),
|
|
21
29
|
};
|
|
22
30
|
async run() {
|
|
@@ -36,14 +44,21 @@ class TriggersFire extends base_command_1.BaseCommand {
|
|
|
36
44
|
catch (err) {
|
|
37
45
|
this.handleApiError(err);
|
|
38
46
|
}
|
|
47
|
+
const accepted = (0, triggers_1.fireWasAccepted)(result);
|
|
39
48
|
if (flags.json) {
|
|
40
49
|
this.log(JSON.stringify(result, null, 2));
|
|
50
|
+
if (flags.strict && !accepted)
|
|
51
|
+
this.exit(1);
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
43
54
|
this.log(`Fire requested: outcome=${String(result.outcome ?? '-')} reason=${String(result.reason ?? '-')}`);
|
|
55
|
+
for (const line of (0, triggers_1.describeFireDetail)(result))
|
|
56
|
+
this.log(line);
|
|
44
57
|
const note = (0, triggers_1.describeScheduledFire)(result);
|
|
45
58
|
if (note)
|
|
46
59
|
this.log(note);
|
|
60
|
+
if (flags.strict && !accepted)
|
|
61
|
+
this.exit(1);
|
|
47
62
|
}
|
|
48
63
|
}
|
|
49
64
|
exports.default = TriggersFire;
|
|
@@ -125,13 +125,14 @@ class TriggersPreflight extends base_command_1.BaseCommand {
|
|
|
125
125
|
else if (report.prompt?.note) {
|
|
126
126
|
this.log(`\nPrompt: ${report.prompt.note}`);
|
|
127
127
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
const fireLines = (0, triggers_1.nextFireLines)(report.schedule);
|
|
129
|
+
if (fireLines.length) {
|
|
130
|
+
this.log('');
|
|
131
|
+
for (const line of fireLines)
|
|
132
|
+
this.log(line);
|
|
132
133
|
}
|
|
133
134
|
if (report.destination) {
|
|
134
|
-
this.log(`\nDestination: ${
|
|
135
|
+
this.log(`\nDestination: ${(0, triggers_1.destinationLine)(report.destination)}`);
|
|
135
136
|
}
|
|
136
137
|
// Non-zero when the trigger would not autonomously run, so this is usable
|
|
137
138
|
// in a script or a pre-deploy check. `2` for indeterminate keeps "blocked"
|
|
@@ -46,6 +46,8 @@ class TriggersReplay extends base_command_1.BaseCommand {
|
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
this.log(`Replay requested: ok=${String(result.ok ?? '-')} outcome=${String(result.outcome ?? '-')} reason=${String(result.reason ?? '-')}`);
|
|
49
|
+
for (const line of (0, triggers_1.describeFireDetail)(result))
|
|
50
|
+
this.log(line);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
exports.default = TriggersReplay;
|
|
@@ -55,9 +55,13 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
55
55
|
'end-at': core_1.Flags.string({
|
|
56
56
|
description: 'ISO-8601 datetime after which a schedule stops firing',
|
|
57
57
|
}),
|
|
58
|
-
'stale-catchup-ms': core_1.Flags.integer({
|
|
58
|
+
'stale-catchup-ms': core_1.Flags.integer({
|
|
59
|
+
description: 'How late a missed occurrence may still run, in ms (a positive number). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
|
|
60
|
+
}),
|
|
59
61
|
at: core_1.Flags.string({ description: 'ISO-8601 datetime for once triggers' }),
|
|
60
|
-
entity: core_1.Flags.string({
|
|
62
|
+
entity: core_1.Flags.string({
|
|
63
|
+
description: 'Event entity type for event triggers (create only; refused on update)',
|
|
64
|
+
}),
|
|
61
65
|
event: core_1.Flags.string({ description: 'Event type for event triggers' }),
|
|
62
66
|
'filter-mode': core_1.Flags.string({
|
|
63
67
|
description: 'Event filter mode',
|
|
@@ -72,8 +76,12 @@ class TriggersUpdate extends base_command_1.BaseCommand {
|
|
|
72
76
|
'max-per-hour': core_1.Flags.integer({ description: 'Event hourly cap' }),
|
|
73
77
|
probability: core_1.Flags.string({ description: 'Stochastic probability from 0 to 1' }),
|
|
74
78
|
'jitter-ms': core_1.Flags.integer({ description: 'Stochastic jitter in ms' }),
|
|
75
|
-
'eval-interval-minutes': core_1.Flags.integer({
|
|
76
|
-
|
|
79
|
+
'eval-interval-minutes': core_1.Flags.integer({
|
|
80
|
+
description: 'Stochastic eval interval in minutes (create only; refused on update)',
|
|
81
|
+
}),
|
|
82
|
+
'next-run-at': core_1.Flags.string({
|
|
83
|
+
description: 'ISO datetime: alias of --at for once triggers; for self_scheduled triggers it is set at create and refused on update',
|
|
84
|
+
}),
|
|
77
85
|
'form-title': core_1.Flags.string({ description: 'Form heading for form triggers' }),
|
|
78
86
|
'form-subtitle': core_1.Flags.string({ description: 'Form subtitle for form triggers' }),
|
|
79
87
|
'form-fields': core_1.Flags.string({ description: 'Form fields JSON array for form triggers' }),
|
|
@@ -11,7 +11,11 @@ class WorkspacesStewardship extends base_command_1.BaseCommand {
|
|
|
11
11
|
];
|
|
12
12
|
static args = {
|
|
13
13
|
workspaceId: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Workspace ID' }),
|
|
14
|
-
userId: core_1.Args.string({
|
|
14
|
+
userId: core_1.Args.string({
|
|
15
|
+
required: true,
|
|
16
|
+
ignoreStdin: true,
|
|
17
|
+
description: 'Member user ID: 24 hexadecimal characters, not an email (`skrr whoami` prints your own)',
|
|
18
|
+
}),
|
|
15
19
|
};
|
|
16
20
|
static flags = {
|
|
17
21
|
json: core_1.Flags.boolean({ description: 'Output metadata and coverage as JSON' }),
|
|
@@ -705,6 +705,15 @@ export declare class AgenticStreamClient {
|
|
|
705
705
|
private flushPendingEnvelopes;
|
|
706
706
|
/** Poll even while a tool is quiet: a pre-join start has no later live event to reveal its gap. */
|
|
707
707
|
private catchUpEnvelopes;
|
|
708
|
+
/**
|
|
709
|
+
* The answer so far, as a terminal shows it: each widget block as its fallback
|
|
710
|
+
* sentence (see `widgetTerminalText.ts`). `accumulated` stays the raw text the
|
|
711
|
+
* stream delivered, because the reconciliation below compares it with what the
|
|
712
|
+
* server sent; this is what every ANSWER lane (`text.delta`, the printed text,
|
|
713
|
+
* `run.result`) reads. While the run is live a trailing line that could still become
|
|
714
|
+
* a block opener is held back, so nothing printed is ever retracted.
|
|
715
|
+
*/
|
|
716
|
+
private answerText;
|
|
708
717
|
private applySessionOutput;
|
|
709
718
|
private installHandlers;
|
|
710
719
|
private handlePermission;
|
|
@@ -28,6 +28,7 @@ const node_readline_1 = require("node:readline");
|
|
|
28
28
|
const socket_io_client_1 = require("socket.io-client");
|
|
29
29
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
30
30
|
const config_1 = require("./config");
|
|
31
|
+
const widgetTerminalText_1 = require("./widgetTerminalText");
|
|
31
32
|
const publicEndpoints_generated_1 = require("./publicEndpoints.generated");
|
|
32
33
|
const dpop_auth_1 = require("./dpop-auth");
|
|
33
34
|
/**
|
|
@@ -1407,6 +1408,17 @@ class AgenticStreamClient {
|
|
|
1407
1408
|
});
|
|
1408
1409
|
return this.replayFlight;
|
|
1409
1410
|
}
|
|
1411
|
+
/**
|
|
1412
|
+
* The answer so far, as a terminal shows it: each widget block as its fallback
|
|
1413
|
+
* sentence (see `widgetTerminalText.ts`). `accumulated` stays the raw text the
|
|
1414
|
+
* stream delivered, because the reconciliation below compares it with what the
|
|
1415
|
+
* server sent; this is what every ANSWER lane (`text.delta`, the printed text,
|
|
1416
|
+
* `run.result`) reads. While the run is live a trailing line that could still become
|
|
1417
|
+
* a block opener is held back, so nothing printed is ever retracted.
|
|
1418
|
+
*/
|
|
1419
|
+
answerText() {
|
|
1420
|
+
return (0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: false });
|
|
1421
|
+
}
|
|
1410
1422
|
applySessionOutput(event) {
|
|
1411
1423
|
// The agent's words arrive HERE for agentic runs, inside `envelopes`, and
|
|
1412
1424
|
// `event.text` is null. Normalising the frame without reading them meant
|
|
@@ -1439,7 +1451,7 @@ class AgenticStreamClient {
|
|
|
1439
1451
|
const envelopeText = envelopesText(scoped);
|
|
1440
1452
|
if (envelopeText) {
|
|
1441
1453
|
this.accumulated += envelopeText;
|
|
1442
|
-
this.emit({ ...scoped, type: 'text.delta', text: this.
|
|
1454
|
+
this.emit({ ...scoped, type: 'text.delta', text: this.answerText() });
|
|
1443
1455
|
}
|
|
1444
1456
|
// A daemon-routed turn carries its tool calls HERE and nowhere else.
|
|
1445
1457
|
// Projecting them gives both execution paths one vocabulary (OSK-7730).
|
|
@@ -1518,7 +1530,7 @@ class AgenticStreamClient {
|
|
|
1518
1530
|
this.accumulated += delta;
|
|
1519
1531
|
if (typeof event.messageId === 'string')
|
|
1520
1532
|
this.responseMessageId = event.messageId;
|
|
1521
|
-
this.emit({ ...event, type: 'text.delta', text: this.
|
|
1533
|
+
this.emit({ ...event, type: 'text.delta', text: this.answerText() });
|
|
1522
1534
|
});
|
|
1523
1535
|
socket.on('session:stream', (event) => {
|
|
1524
1536
|
if (!match(event))
|
|
@@ -1933,35 +1945,35 @@ class AgenticStreamClient {
|
|
|
1933
1945
|
// The banner moved the cursor to a fresh line, so nothing of the answer
|
|
1934
1946
|
// is on screen after it: the next snapshot must be printed from where the
|
|
1935
1947
|
// text left off, not from column 0 of a line that no longer holds it.
|
|
1936
|
-
this.renderedText = this.
|
|
1948
|
+
this.renderedText = this.answerText();
|
|
1937
1949
|
}
|
|
1938
1950
|
else if (event.type === 'tool.completed') {
|
|
1939
1951
|
output.write(`${describeToolEnd(event.toolName, event.status)}\n`);
|
|
1940
|
-
this.renderedText = this.
|
|
1952
|
+
this.renderedText = this.answerText();
|
|
1941
1953
|
}
|
|
1942
1954
|
else if (event.type === 'stream.gap') {
|
|
1943
1955
|
// Said WHILE READING, which is the only moment it helps: a truncated
|
|
1944
1956
|
// live answer looks like a complete short answer, and by the terminal
|
|
1945
1957
|
// event the reader has already believed it (OSK-7631).
|
|
1946
1958
|
output.write(`\n${String(event.message ?? '')}\n`);
|
|
1947
|
-
this.renderedText = this.
|
|
1959
|
+
this.renderedText = this.answerText();
|
|
1948
1960
|
}
|
|
1949
1961
|
else if (event.type === 'permission.resolved') {
|
|
1950
1962
|
const verb = event.decision === 'allow' ? 'allowed' : 'denied';
|
|
1951
1963
|
output.write(`\n[permission] ${String(event.toolName ?? 'tool')} ${verb} by ${String(event.decidedBy ?? '')}\n`);
|
|
1952
|
-
this.renderedText = this.
|
|
1964
|
+
this.renderedText = this.answerText();
|
|
1953
1965
|
}
|
|
1954
1966
|
else if (event.type === 'session.notice') {
|
|
1955
1967
|
output.write(`\n[session] ${String(event.message ?? '')}\n`);
|
|
1956
|
-
this.renderedText = this.
|
|
1968
|
+
this.renderedText = this.answerText();
|
|
1957
1969
|
}
|
|
1958
1970
|
else if (event.type === 'transport.disconnected') {
|
|
1959
1971
|
output.write(`\n[reconnecting] ${String(event.reason ?? '')}\n`);
|
|
1960
|
-
this.renderedText = this.
|
|
1972
|
+
this.renderedText = this.answerText();
|
|
1961
1973
|
}
|
|
1962
1974
|
else if (event.type === 'permission.requested') {
|
|
1963
1975
|
output.write(`\n[${event.type}] ${describePermission(event)}\n`);
|
|
1964
|
-
this.renderedText = this.
|
|
1976
|
+
this.renderedText = this.answerText();
|
|
1965
1977
|
}
|
|
1966
1978
|
else if (event.type === 'permission.cancelled') {
|
|
1967
1979
|
// A request the run stopped waiting for (OSK-12197). Without this line
|
|
@@ -1970,11 +1982,11 @@ class AgenticStreamClient {
|
|
|
1970
1982
|
? event.message
|
|
1971
1983
|
: `closed (${String(event.reason ?? 'cancelled')})`;
|
|
1972
1984
|
output.write(`\n[permission] ${String(event.toolName ?? 'tool')}: ${why}\n`);
|
|
1973
|
-
this.renderedText = this.
|
|
1985
|
+
this.renderedText = this.answerText();
|
|
1974
1986
|
}
|
|
1975
1987
|
else if (event.type === 'question.requested') {
|
|
1976
1988
|
output.write(`\n[${event.type}]\n`);
|
|
1977
|
-
this.renderedText = this.
|
|
1989
|
+
this.renderedText = this.answerText();
|
|
1978
1990
|
}
|
|
1979
1991
|
else if (event.type === 'question.cancelled') {
|
|
1980
1992
|
// A question the run stopped waiting for (OSK-12208).
|
|
@@ -1982,17 +1994,17 @@ class AgenticStreamClient {
|
|
|
1982
1994
|
? event.message
|
|
1983
1995
|
: `closed (${String(event.reason ?? 'cancelled')})`;
|
|
1984
1996
|
output.write(`\n[question] ${why}\n`);
|
|
1985
|
-
this.renderedText = this.
|
|
1997
|
+
this.renderedText = this.answerText();
|
|
1986
1998
|
}
|
|
1987
1999
|
else if (event.type === 'permission.approved' && event.auto === true) {
|
|
1988
2000
|
// Said out loud, because nobody was asked: the flag approved it, and a
|
|
1989
2001
|
// reader of this log should see which tools that covered (OSK-10323).
|
|
1990
2002
|
output.write(`\n[permission] ${describePermission(event)} allowed by --approve-tools\n`);
|
|
1991
|
-
this.renderedText = this.
|
|
2003
|
+
this.renderedText = this.answerText();
|
|
1992
2004
|
}
|
|
1993
2005
|
else if (event.type === 'question.answered' && event.nonInteractive) {
|
|
1994
2006
|
output.write('\n[question] no terminal to answer on, so the question was dismissed unanswered\n');
|
|
1995
|
-
this.renderedText = this.
|
|
2007
|
+
this.renderedText = this.answerText();
|
|
1996
2008
|
}
|
|
1997
2009
|
}
|
|
1998
2010
|
/**
|
|
@@ -2014,7 +2026,7 @@ class AgenticStreamClient {
|
|
|
2014
2026
|
'machine is still working on it. Waiting up to ' +
|
|
2015
2027
|
`${formatWaitDuration(Number(event.waitMs) || 0)} for its reply ` +
|
|
2016
2028
|
'(Ctrl-C stops waiting; it does not stop your machine).\n');
|
|
2017
|
-
this.renderedText = this.
|
|
2029
|
+
this.renderedText = this.answerText();
|
|
2018
2030
|
return true;
|
|
2019
2031
|
}
|
|
2020
2032
|
if (event.type === 'run.completed') {
|
|
@@ -2063,7 +2075,10 @@ class AgenticStreamClient {
|
|
|
2063
2075
|
// no `result` — so `run.result` is filled from the record, or the notice's
|
|
2064
2076
|
// promise is false exactly when it was made (OSK-12132).
|
|
2065
2077
|
if (this.lostRanges.length && this.options.reconcileTerminal) {
|
|
2066
|
-
|
|
2078
|
+
// The record's text is the server's projection (a widget block is its fallback
|
|
2079
|
+
// sentence), so the comparison is made with what the reader was shown, not with
|
|
2080
|
+
// the raw block that the stream carried.
|
|
2081
|
+
const streamedText = (0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true });
|
|
2067
2082
|
void this.readRecordedText().then((recorded) => {
|
|
2068
2083
|
this.settleGapVerdict(streamedText, recorded);
|
|
2069
2084
|
this.settle(status, event, recorded?.text || undefined);
|
|
@@ -2134,14 +2149,19 @@ class AgenticStreamClient {
|
|
|
2134
2149
|
// The record wins over a stream known to have lost chunks, unless what
|
|
2135
2150
|
// arrived is already longer (the record lags a completed stream, never the
|
|
2136
2151
|
// other way round).
|
|
2137
|
-
|
|
2152
|
+
// (Compared as the reader sees it: the record holds a widget as its fallback sentence,
|
|
2153
|
+
// which is shorter than the block the stream carried, and the raw length would never lose.)
|
|
2154
|
+
if (recordedText &&
|
|
2155
|
+
recordedText.length > (0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true }).length) {
|
|
2138
2156
|
this.accumulated = recordedText;
|
|
2139
2157
|
}
|
|
2140
2158
|
// The finished answer, as every other surface shows it: the web applies
|
|
2141
2159
|
// this same sanitizer, so a scheduling JSON block or leaked function-call
|
|
2142
2160
|
// XML the model wrote into its reply is removed here too instead of being
|
|
2143
2161
|
// printed as part of the agent's answer.
|
|
2144
|
-
|
|
2162
|
+
// A widget is its fallback sentence in a terminal, first: the sanitizer must read
|
|
2163
|
+
// prose and never a widget's script (the server projects before it sanitizes, too).
|
|
2164
|
+
this.accumulated = (0, data_provider_1.sanitizeFinalText)((0, widgetTerminalText_1.widgetsAsText)(this.accumulated, { final: true }));
|
|
2145
2165
|
if (!this.options.quiet && !this.options.jsonl && this.accumulated) {
|
|
2146
2166
|
const output = this.options.output ?? process.stdout;
|
|
2147
2167
|
const { append, shown } = renderableDelta(this.renderedText, this.accumulated);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EventWakeCapabilities } from './commitments';
|
|
2
|
+
/**
|
|
3
|
+
* The "Event wakes:" block, one renderer for `trigger-status` and `wake-capabilities`. The second
|
|
4
|
+
* used to word its own conclusion ("configured sources may wake the Agent", a column marked
|
|
5
|
+
* ACTIVE) and contradicted the first for the same Commitment (OSK-15428, OSK-15419); printing the
|
|
6
|
+
* same facts in the same words is the only way the two cannot disagree.
|
|
7
|
+
*/
|
|
8
|
+
export declare function eventWakeLines(caps: EventWakeCapabilities): string[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventWakeLines = eventWakeLines;
|
|
4
|
+
/**
|
|
5
|
+
* The "Event wakes:" block, one renderer for `trigger-status` and `wake-capabilities`. The second
|
|
6
|
+
* used to word its own conclusion ("configured sources may wake the Agent", a column marked
|
|
7
|
+
* ACTIVE) and contradicted the first for the same Commitment (OSK-15428, OSK-15419); printing the
|
|
8
|
+
* same facts in the same words is the only way the two cannot disagree.
|
|
9
|
+
*/
|
|
10
|
+
function eventWakeLines(caps) {
|
|
11
|
+
const lines = [];
|
|
12
|
+
lines.push('Event wakes:');
|
|
13
|
+
lines.push(` requested: ${caps.requested ? 'yes' : 'no'}`);
|
|
14
|
+
lines.push(` configured sources: ${(caps.configuredSources ?? []).join(', ') || 'none'}`);
|
|
15
|
+
lines.push(` eligible sources: ${(caps.eligibleSources ?? []).join(', ') || 'none'}`);
|
|
16
|
+
lines.push(` materialized sources: ${(caps.materializedSources ?? []).join(', ') || 'none'}`);
|
|
17
|
+
if ((caps.dormantSources ?? []).length) {
|
|
18
|
+
lines.push(` dormant sources: ${caps.dormantSources.join(', ')} (configured, but no event wake is planned for them)`);
|
|
19
|
+
}
|
|
20
|
+
if ((caps.unroutableSources ?? []).length) {
|
|
21
|
+
lines.push(` unroutable sources: ${caps
|
|
22
|
+
.unroutableSources.map((item) => `${item.source} (${item.reason})`)
|
|
23
|
+
.join(', ')} — materialized but no upstream producer can deliver events`);
|
|
24
|
+
}
|
|
25
|
+
if ((caps.unverifiedSources ?? []).length) {
|
|
26
|
+
lines.push(` unverified sources: ${caps
|
|
27
|
+
.unverifiedSources.map((item) => `${item.source} (${item.reason})`)
|
|
28
|
+
.join(', ')} — the upstream producer could not be read, so delivery is unknown`);
|
|
29
|
+
}
|
|
30
|
+
if ((caps.permissionGaps ?? []).length) {
|
|
31
|
+
lines.push(` permission gaps: ${caps
|
|
32
|
+
.permissionGaps.map((gap) => `${gap.source} ${gap.capability ?? gap.permission}` +
|
|
33
|
+
` (${gap.impact === 'evidence_read' ? 'needed by' : 'blocks'} ${(gap.events ?? []).join(', ')})`)
|
|
34
|
+
.join('; ')} — the routing GitHub installation does not hold the permission`);
|
|
35
|
+
}
|
|
36
|
+
if (caps.degradedReason)
|
|
37
|
+
lines.push(` degraded: ${caps.degradedReason}`);
|
|
38
|
+
return lines;
|
|
39
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function renderActionHistory(page: {
|
|
2
|
+
data?: unknown[];
|
|
3
|
+
has_more?: boolean;
|
|
4
|
+
next_cursor?: string | null;
|
|
5
|
+
} | undefined, log: (line: string) => void): void;
|
|
6
|
+
export declare function renderReflection(review: Record<string, unknown> | undefined, log: (line: string) => void): void;
|
|
7
|
+
export declare function renderCadenceDecisions(list: {
|
|
8
|
+
data?: unknown[];
|
|
9
|
+
} | undefined, log: (line: string) => void): void;
|