@skrr-ai/cli 0.1.101 → 0.1.103
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 +24 -0
- package/dist/commands/agent/message/send.js +6 -2
- package/dist/commands/agents/triggers/create.js +7 -17
- package/dist/commands/agents/triggers/update.js +41 -28
- package/dist/commands/commitments/control/apply.d.ts +15 -0
- package/dist/commands/commitments/control/apply.js +36 -0
- package/dist/commands/commitments/control/preview.d.ts +17 -0
- package/dist/commands/commitments/control/preview.js +43 -0
- package/dist/commands/commitments/control/show.d.ts +12 -0
- package/dist/commands/commitments/control/show.js +29 -0
- package/dist/commands/commitments/create.js +5 -2
- package/dist/commands/commitments/observation/probe.d.ts +15 -0
- package/dist/commands/commitments/observation/probe.js +46 -0
- package/dist/commands/commitments/observation/summary.d.ts +9 -0
- package/dist/commands/commitments/observation/summary.js +31 -0
- package/dist/commands/commitments/preflight.js +18 -1
- package/dist/commands/commitments/readiness/show.d.ts +12 -0
- package/dist/commands/commitments/readiness/show.js +29 -0
- package/dist/commands/commitments/readiness/verify.d.ts +13 -0
- package/dist/commands/commitments/readiness/verify.js +33 -0
- package/dist/commands/commitments/roster.d.ts +15 -0
- package/dist/commands/commitments/roster.js +39 -0
- package/dist/commands/commitments/show.js +1 -1
- package/dist/commands/commitments/status.d.ts +17 -0
- package/dist/commands/commitments/status.js +41 -0
- package/dist/commands/commitments/update.js +23 -9
- package/dist/commands/commitments/work-plan.d.ts +11 -0
- package/dist/commands/commitments/work-plan.js +36 -0
- package/dist/commands/compass/effective-policy.d.ts +12 -0
- package/dist/commands/compass/effective-policy.js +34 -0
- package/dist/commands/compass/update.d.ts +12 -0
- package/dist/commands/compass/update.js +27 -0
- package/dist/commands/daemon/logs.d.ts +39 -1
- package/dist/commands/daemon/logs.js +140 -13
- package/dist/commands/followups/checkin.js +46 -3
- package/dist/commands/machines/dedicated/exec.js +3 -1
- package/dist/commands/proposals/discard.d.ts +4 -0
- package/dist/commands/proposals/discard.js +3 -0
- package/dist/commands/proposals/keep.d.ts +4 -0
- package/dist/commands/proposals/keep.js +3 -0
- package/dist/commands/proposals/snooze.d.ts +4 -0
- package/dist/commands/proposals/snooze.js +3 -0
- package/dist/commands/spaces/workflows/cancel-node.d.ts +16 -0
- package/dist/commands/spaces/workflows/cancel-node.js +44 -0
- package/dist/commands/spaces/workflows/cancel.d.ts +40 -0
- package/dist/commands/spaces/workflows/cancel.js +109 -3
- package/dist/commands/spaces/workflows/run.d.ts +9 -0
- package/dist/commands/spaces/workflows/run.js +38 -0
- package/dist/commands/tasks/approvals/resolve.d.ts +12 -0
- package/dist/commands/tasks/approvals/resolve.js +21 -5
- package/dist/commands/tasks/schedule.js +1 -1
- package/dist/commands/triggers/capabilities.js +7 -0
- package/dist/commands/triggers/create.js +12 -18
- package/dist/commands/triggers/fire.js +3 -0
- package/dist/commands/triggers/update.js +41 -27
- package/dist/commands/widgets/check.d.ts +39 -0
- package/dist/commands/widgets/check.js +179 -0
- package/dist/lib/agent-mailbox.d.ts +0 -1
- package/dist/lib/agent-mailbox.js +0 -1
- package/dist/lib/commitment-loop-status.d.ts +16 -0
- package/dist/lib/commitment-loop-status.js +164 -0
- package/dist/lib/commitments.d.ts +47 -1
- package/dist/lib/commitments.js +218 -6
- package/dist/lib/compasses.d.ts +3 -0
- package/dist/lib/compasses.js +1 -0
- package/dist/lib/delegated-cli.d.ts +23 -1
- package/dist/lib/delegated-cli.js +61 -4
- package/dist/lib/first-party-harness.d.ts +1 -1
- package/dist/lib/first-party-harness.js +1 -1
- package/dist/lib/responsibility-controls.d.ts +11 -0
- package/dist/lib/responsibility-controls.js +119 -0
- package/dist/lib/session-task-write.d.ts +13 -0
- package/dist/lib/session-task-write.js +63 -3
- package/dist/lib/stewardship-output.js +13 -2
- package/dist/lib/triggers.d.ts +26 -0
- package/dist/lib/triggers.js +134 -1
- package/dist/lib/widgetCheck.d.ts +123 -0
- package/dist/lib/widgetCheck.js +998 -0
- package/dist/lib/widgetStaticScan.d.ts +111 -0
- package/dist/lib/widgetStaticScan.js +833 -0
- package/dist/lib/workflow-node-control.d.ts +10 -0
- package/dist/lib/workflow-node-control.js +76 -0
- package/dist/lib/workspaces.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +9 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +12 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +9 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +12 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +11924 -8704
- package/oclif.manifest.json +1487 -396
- package/package.json +11 -2
|
@@ -99,18 +99,32 @@ class FollowupsCheckin extends base_command_1.BaseCommand {
|
|
|
99
99
|
this.handleApiError(err);
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
+
const producer = agent.boundToSession ? 'agent_in_turn' : 'user_explicit';
|
|
103
|
+
// An explicit request from a person that arms nothing is a refusal, and a script reading the
|
|
104
|
+
// exit code must see it as one (OSK-15413). A check-in the AGENT chose to make is different:
|
|
105
|
+
// there, staying quiet when the budget is spent is the designed outcome.
|
|
106
|
+
if (response.dropped && producer === 'user_explicit') {
|
|
107
|
+
this.failWithCliError({
|
|
108
|
+
message: budgetRefusalMessage(agent.id, response.budget),
|
|
109
|
+
code: 'FOLLOWUP_BUDGET_EXHAUSTED',
|
|
110
|
+
exit: 1,
|
|
111
|
+
retryable: false,
|
|
112
|
+
details: { budget: response.budget ?? null, response },
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
102
116
|
if (flags.json) {
|
|
103
117
|
this.log(JSON.stringify(response, null, 2));
|
|
104
118
|
return;
|
|
105
119
|
}
|
|
106
120
|
const row = response.followup;
|
|
107
121
|
if (response.reused) {
|
|
108
|
-
this.log(
|
|
122
|
+
this.log(reusedMessage(row, subject, flags.why));
|
|
109
123
|
return;
|
|
110
124
|
}
|
|
111
125
|
if (response.dropped) {
|
|
112
|
-
// silent_drop is the check-in budget's contract: the answer to
|
|
113
|
-
// greeting too many" is quiet, not an error the caller can retry.
|
|
126
|
+
// silent_drop is the check-in budget's contract for an agent's own check-in: the answer to
|
|
127
|
+
// "one greeting too many" is quiet, not an error the caller can retry.
|
|
114
128
|
this.log('Dropped by the daily check-in budget — staying quiet is the correct outcome.');
|
|
115
129
|
return;
|
|
116
130
|
}
|
|
@@ -118,3 +132,32 @@ class FollowupsCheckin extends base_command_1.BaseCommand {
|
|
|
118
132
|
}
|
|
119
133
|
}
|
|
120
134
|
exports.default = FollowupsCheckin;
|
|
135
|
+
/**
|
|
136
|
+
* What a reused answer means for the person who asked: a second check-in on a subject that already
|
|
137
|
+
* has one arms nothing and changes nothing, so the note and time they typed were NOT applied. Say
|
|
138
|
+
* so, show what is armed, and name the two ways forward (OSK-15411). Exit stays 0: the follow-up
|
|
139
|
+
* they wanted to exist does exist.
|
|
140
|
+
*/
|
|
141
|
+
function reusedMessage(row, subject, requestedWhy) {
|
|
142
|
+
const lines = [
|
|
143
|
+
`Already armed: ${row?.id} — one pending check-in per subject (${subject.type}:${subject.externalKey}), and this is it.`,
|
|
144
|
+
'Nothing in this request was applied: it armed no new check-in and changed neither the note nor the time.',
|
|
145
|
+
];
|
|
146
|
+
if (row) {
|
|
147
|
+
const sameNote = row.why === requestedWhy;
|
|
148
|
+
lines.push(`Armed: ${row.why ? `"${row.why}"` : '(no note)'}, next ${row.nextRunAt ?? 'when its schedule says'}${sameNote ? ' (the same note you gave)' : ''}.`);
|
|
149
|
+
}
|
|
150
|
+
lines.push(`To change the time: skrr followups reschedule ${row?.id ?? '<id>'} --at <instant> or --in <offset>.`, "To change the note: cancel it and create it again (a cancelled check-in still counts against today's check-in budget).");
|
|
151
|
+
return lines.join('\n');
|
|
152
|
+
}
|
|
153
|
+
/** The refusal for an explicit check-in the daily budget will not take, with the number and the way to raise it. */
|
|
154
|
+
function budgetRefusalMessage(agentId, budget) {
|
|
155
|
+
const { used, limit } = (budget && typeof budget === 'object' ? budget : {});
|
|
156
|
+
const spent = typeof used === 'number' && typeof limit === 'number'
|
|
157
|
+
? `${agentId} has used ${used} of its ${limit} check-ins today`
|
|
158
|
+
: `${agentId} has used its daily check-in budget`;
|
|
159
|
+
return [
|
|
160
|
+
`No check-in was armed: ${spent}. The day resets at 00:00 UTC, and a cancelled check-in still counts.`,
|
|
161
|
+
`Raise the limit with: skrr agents triggers policy ${agentId} --followup-budget checkin=<count>`,
|
|
162
|
+
].join(' ');
|
|
163
|
+
}
|
|
@@ -104,7 +104,9 @@ class DedicatedMachinesExec extends base_command_1.BaseCommand {
|
|
|
104
104
|
description: `How long to let it run, such as 30s or 5m (default 2m, max ${dedicated_machines_1.DEDICATED_EXEC_MAX_TIMEOUT_MS / 60000}m). The process group is killed at the deadline.`,
|
|
105
105
|
}),
|
|
106
106
|
'request-id': core_1.Flags.string({
|
|
107
|
-
description: 'Idempotency key for this command. Repeating the invocation with the same id returns the run it already started
|
|
107
|
+
description: 'Idempotency key for this command. Repeating the invocation with the same id returns the run it already started instead of running it again. ' +
|
|
108
|
+
'Output is kept for at most 5 minutes after it ends and at most 60 seconds after the first terminal read, whichever expires sooner. ' +
|
|
109
|
+
'Letters, digits and . _ : / - only.',
|
|
108
110
|
}),
|
|
109
111
|
workspace: core_1.Flags.string({ description: 'Workspace scope' }),
|
|
110
112
|
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ProposalDecisionCommand } from '../../lib/proposal-decision-command';
|
|
2
2
|
export default class ProposalsDiscard extends ProposalDecisionCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
kind: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
4
8
|
static decision: "discard";
|
|
5
9
|
}
|
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const proposal_decision_command_1 = require("../../lib/proposal-decision-command");
|
|
4
4
|
class ProposalsDiscard extends proposal_decision_command_1.ProposalDecisionCommand {
|
|
5
5
|
static description = 'Discard one displayed proposal through its domain authority';
|
|
6
|
+
// Own, not inherited: oclif spreads the command class into the parser input, and a static a
|
|
7
|
+
// subclass only inherits is dropped, which left these commands with no declared KIND/ID (OSK-15346).
|
|
8
|
+
static args = proposal_decision_command_1.ProposalDecisionCommand.args;
|
|
6
9
|
static decision = 'discard';
|
|
7
10
|
}
|
|
8
11
|
exports.default = ProposalsDiscard;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ProposalDecisionCommand } from '../../lib/proposal-decision-command';
|
|
2
2
|
export default class ProposalsKeep extends ProposalDecisionCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
kind: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
4
8
|
static decision: "keep";
|
|
5
9
|
}
|
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const proposal_decision_command_1 = require("../../lib/proposal-decision-command");
|
|
4
4
|
class ProposalsKeep extends proposal_decision_command_1.ProposalDecisionCommand {
|
|
5
5
|
static description = 'Keep one displayed proposal through its domain authority';
|
|
6
|
+
// Own, not inherited: oclif spreads the command class into the parser input, and a static a
|
|
7
|
+
// subclass only inherits is dropped, which left these commands with no declared KIND/ID (OSK-15346).
|
|
8
|
+
static args = proposal_decision_command_1.ProposalDecisionCommand.args;
|
|
6
9
|
static decision = 'keep';
|
|
7
10
|
}
|
|
8
11
|
exports.default = ProposalsKeep;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ProposalDecisionCommand } from '../../lib/proposal-decision-command';
|
|
2
2
|
export default class ProposalsSnooze extends ProposalDecisionCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
kind: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
4
8
|
static decision: "snooze";
|
|
5
9
|
}
|
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const proposal_decision_command_1 = require("../../lib/proposal-decision-command");
|
|
4
4
|
class ProposalsSnooze extends proposal_decision_command_1.ProposalDecisionCommand {
|
|
5
5
|
static description = 'Snooze one displayed proposal through its domain authority';
|
|
6
|
+
// Own, not inherited: oclif spreads the command class into the parser input, and a static a
|
|
7
|
+
// subclass only inherits is dropped, which left these commands with no declared KIND/ID (OSK-15346).
|
|
8
|
+
static args = proposal_decision_command_1.ProposalDecisionCommand.args;
|
|
6
9
|
static decision = 'snooze';
|
|
7
10
|
}
|
|
8
11
|
exports.default = ProposalsSnooze;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
export default class SpacesWorkflowsCancelNode extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
spaceId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
runId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
nodeKey: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
9
|
+
};
|
|
10
|
+
static flags: {
|
|
11
|
+
'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
reason: 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,44 @@
|
|
|
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
|
+
const prompt_1 = require("../../../lib/prompt");
|
|
7
|
+
const workflow_node_control_1 = require("../../../lib/workflow-node-control");
|
|
8
|
+
class SpacesWorkflowsCancelNode extends base_command_1.BaseCommand {
|
|
9
|
+
static description = 'Request cancellation of one exact workflow node attempt and show the returned execution state';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> spaces workflows run <space> <run> --json > reviewed-run.json',
|
|
12
|
+
'<%= config.bin %> spaces workflows cancel-node <space> <run> <node> --from-json reviewed-run.json',
|
|
13
|
+
];
|
|
14
|
+
static args = {
|
|
15
|
+
spaceId: core_1.Args.string({ description: 'Owning Space ID', required: true, ignoreStdin: true }),
|
|
16
|
+
runId: core_1.Args.string({ description: 'Workflow run ID', required: true, ignoreStdin: true }),
|
|
17
|
+
nodeKey: core_1.Args.string({ description: 'Node key to stop', required: true, ignoreStdin: true }),
|
|
18
|
+
};
|
|
19
|
+
static flags = {
|
|
20
|
+
'from-json': core_1.Flags.string({ description: 'Saved canonical workflow run snapshot, or - for stdin', required: true }),
|
|
21
|
+
reason: core_1.Flags.string({ description: 'Cancellation reason (at most 500 characters)' }),
|
|
22
|
+
json: core_1.Flags.boolean({ description: 'Output the updated workflow run as JSON' }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
this.requireAuth();
|
|
26
|
+
const { args, flags } = await this.parse(SpacesWorkflowsCancelNode);
|
|
27
|
+
try {
|
|
28
|
+
const body = (0, workflow_node_control_1.nodeCancellationFromSnapshot)(args.spaceId, args.runId, args.nodeKey, await (0, prompt_1.readJsonBody)(flags['from-json']), flags.reason);
|
|
29
|
+
const run = await data_provider_1.dataService.cancelSpaceWorkflowNode(args.spaceId, args.runId, args.nodeKey, body);
|
|
30
|
+
if (flags.json) {
|
|
31
|
+
this.log(JSON.stringify(run, null, 2));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const node = run.nodes?.find((item) => item.nodeKey === args.nodeKey);
|
|
35
|
+
this.log(`Cancellation for ${args.nodeKey}: ${node?.cancellation?.state ?? 'unknown'}.`);
|
|
36
|
+
this.log(`Returned node state: ${node?.status ?? 'unknown'}.`);
|
|
37
|
+
this.log(`Workflow run ${run.id}: ${run.status}.`);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
this.handleApiError(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.default = SpacesWorkflowsCancelNode;
|
|
@@ -1,4 +1,43 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Child workflow runs a cancelled run was waiting on. A cancelled node keeps its `waitingFor`,
|
|
4
|
+
* and every node kind that starts a child run (`workflow_call` = subworkflow, `loop` iteration,
|
|
5
|
+
* `task_plan`) records that run as `waitingFor.workflowRunId`. Reading the id rather than the
|
|
6
|
+
* kind means a new child-starting node kind is not silently missed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function childWorkflowRunIds(run: {
|
|
9
|
+
id?: string;
|
|
10
|
+
nodes?: Array<{
|
|
11
|
+
waitingFor?: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
}): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Lines for a cancel that has not finished converging. `cancellation.state: settled` with
|
|
16
|
+
* nothing pending is the only converged answer; anything else must not read as "stopped".
|
|
17
|
+
*/
|
|
18
|
+
export declare function describeCancellationProgress(spaceId: string, run: {
|
|
19
|
+
id: string;
|
|
20
|
+
cancellation?: {
|
|
21
|
+
state?: string;
|
|
22
|
+
descendantsPending?: boolean;
|
|
23
|
+
executorsPending?: number;
|
|
24
|
+
};
|
|
25
|
+
}): string[];
|
|
26
|
+
/**
|
|
27
|
+
* The lines that tell a person which child runs a `preserve_children` cancel left running.
|
|
28
|
+
* "Cancelled" next to a child that is still waiting forever is the part nobody could see
|
|
29
|
+
* (OSK-15331), so say it and say how to stop them. Re-cancelling the parent with
|
|
30
|
+
* `--scope subtree` widens the stop to every descendant (the server persists the wider
|
|
31
|
+
* decision before touching any descendant). An unreadable child is reported as unreadable,
|
|
32
|
+
* never as stopped.
|
|
33
|
+
*/
|
|
34
|
+
export declare function describePreservedChildren(spaceId: string, parentRunId: string, children: Array<{
|
|
35
|
+
id: string;
|
|
36
|
+
status?: string;
|
|
37
|
+
unreadable?: boolean;
|
|
38
|
+
}>, { reviewedScope }?: {
|
|
39
|
+
reviewedScope?: boolean;
|
|
40
|
+
}): string[];
|
|
2
41
|
export default class SpacesWorkflowsCancel extends BaseCommand {
|
|
3
42
|
static description: string;
|
|
4
43
|
static args: {
|
|
@@ -7,6 +46,7 @@ export default class SpacesWorkflowsCancel extends BaseCommand {
|
|
|
7
46
|
};
|
|
8
47
|
static flags: {
|
|
9
48
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
49
|
+
scope: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
50
|
yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
51
|
};
|
|
12
52
|
run(): Promise<void>;
|
|
@@ -1,10 +1,84 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.childWorkflowRunIds = childWorkflowRunIds;
|
|
4
|
+
exports.describeCancellationProgress = describeCancellationProgress;
|
|
5
|
+
exports.describePreservedChildren = describePreservedChildren;
|
|
3
6
|
const core_1 = require("@oclif/core");
|
|
4
7
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
8
|
const base_command_1 = require("../../../base-command");
|
|
6
9
|
const prompt_1 = require("../../../lib/prompt");
|
|
7
10
|
const space_output_1 = require("../../../lib/space-output");
|
|
11
|
+
const CANCELLATION_SCOPES = [
|
|
12
|
+
'preserve_children',
|
|
13
|
+
'subtree',
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Child workflow runs a cancelled run was waiting on. A cancelled node keeps its `waitingFor`,
|
|
17
|
+
* and every node kind that starts a child run (`workflow_call` = subworkflow, `loop` iteration,
|
|
18
|
+
* `task_plan`) records that run as `waitingFor.workflowRunId`. Reading the id rather than the
|
|
19
|
+
* kind means a new child-starting node kind is not silently missed.
|
|
20
|
+
*/
|
|
21
|
+
function childWorkflowRunIds(run) {
|
|
22
|
+
const ids = new Set();
|
|
23
|
+
for (const node of run.nodes ?? []) {
|
|
24
|
+
const waitingFor = node.waitingFor;
|
|
25
|
+
const childId = waitingFor?.workflowRunId;
|
|
26
|
+
if (typeof childId === 'string' && childId && childId !== run.id)
|
|
27
|
+
ids.add(childId);
|
|
28
|
+
}
|
|
29
|
+
return [...ids];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Lines for a cancel that has not finished converging. `cancellation.state: settled` with
|
|
33
|
+
* nothing pending is the only converged answer; anything else must not read as "stopped".
|
|
34
|
+
*/
|
|
35
|
+
function describeCancellationProgress(spaceId, run) {
|
|
36
|
+
const c = run.cancellation;
|
|
37
|
+
if (!c)
|
|
38
|
+
return [];
|
|
39
|
+
const pending = c.state !== 'settled' || c.descendantsPending || Number(c.executorsPending) > 0;
|
|
40
|
+
if (!pending)
|
|
41
|
+
return [];
|
|
42
|
+
const detail = `state ${c.state ?? 'unknown'}, descendant runs pending: ${c.descendantsPending ? 'yes' : 'no'}, executors pending: ${Number(c.executorsPending) || 0}`;
|
|
43
|
+
// `failed` means the cleanup gave up: reading again never converges it, only a reconcile retries.
|
|
44
|
+
if (c.state === 'failed') {
|
|
45
|
+
return [
|
|
46
|
+
`Cancellation cleanup gave up (${detail}).`,
|
|
47
|
+
` Retry it with: skrr spaces workflows reconcile ${spaceId} ${run.id}`,
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
return [
|
|
51
|
+
`Cancellation is still converging (${detail}).`,
|
|
52
|
+
` Re-read it with: skrr spaces workflows run ${spaceId} ${run.id}`,
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The lines that tell a person which child runs a `preserve_children` cancel left running.
|
|
57
|
+
* "Cancelled" next to a child that is still waiting forever is the part nobody could see
|
|
58
|
+
* (OSK-15331), so say it and say how to stop them. Re-cancelling the parent with
|
|
59
|
+
* `--scope subtree` widens the stop to every descendant (the server persists the wider
|
|
60
|
+
* decision before touching any descendant). An unreadable child is reported as unreadable,
|
|
61
|
+
* never as stopped.
|
|
62
|
+
*/
|
|
63
|
+
function describePreservedChildren(spaceId, parentRunId, children, { reviewedScope = false } = {}) {
|
|
64
|
+
const live = children.filter((child) => child.unreadable || (0, data_provider_1.isActiveWorkflowRunStatus)(child.status));
|
|
65
|
+
if (live.length === 0)
|
|
66
|
+
return [];
|
|
67
|
+
const lines = [
|
|
68
|
+
`Left running (scope preserve_children): ${live.length} child workflow run${live.length === 1 ? '' : 's'} started by this run.`,
|
|
69
|
+
];
|
|
70
|
+
for (const child of live) {
|
|
71
|
+
lines.push(` ${child.id} (${child.unreadable ? 'status unreadable' : child.status})`);
|
|
72
|
+
}
|
|
73
|
+
if (reviewedScope) {
|
|
74
|
+
// A stop under a reviewed scope is frozen to that review, so cancelling the parent again
|
|
75
|
+
// does not widen it; each child is stopped on its own.
|
|
76
|
+
lines.push(`This run was stopped under a reviewed scope, so cancelling it again will not widen the stop.`, `Stop a child with: skrr spaces workflows cancel ${spaceId} <child-run-id> --scope subtree --yes`);
|
|
77
|
+
return lines;
|
|
78
|
+
}
|
|
79
|
+
lines.push(`Stop them now: skrr spaces workflows cancel ${spaceId} ${parentRunId} --scope subtree --yes`, ` (widens this cancel to every descendant run), or stop one: skrr spaces workflows cancel ${spaceId} <child-run-id> --scope subtree --yes`);
|
|
80
|
+
return lines;
|
|
81
|
+
}
|
|
8
82
|
class SpacesWorkflowsCancel extends base_command_1.BaseCommand {
|
|
9
83
|
static description = 'Cancel a workflow run and stop further graph coordination';
|
|
10
84
|
static args = {
|
|
@@ -12,15 +86,25 @@ class SpacesWorkflowsCancel extends base_command_1.BaseCommand {
|
|
|
12
86
|
runId: core_1.Args.string({ description: 'Workflow run ID', required: true, ignoreStdin: true }),
|
|
13
87
|
};
|
|
14
88
|
static flags = {
|
|
15
|
-
json: core_1.Flags.boolean({
|
|
89
|
+
json: core_1.Flags.boolean({
|
|
90
|
+
description: 'Output the cancelled run as JSON (cancellation.scope and the waitingFor.workflowRunId of the cancelled nodes show which child runs were left running)',
|
|
91
|
+
}),
|
|
92
|
+
scope: core_1.Flags.string({
|
|
93
|
+
description: 'What happens to child workflow runs this run started: preserve_children (default) leaves them running, subtree stops every descendant run too',
|
|
94
|
+
options: [...CANCELLATION_SCOPES],
|
|
95
|
+
}),
|
|
16
96
|
yes: core_1.Flags.boolean({ char: 'y', description: 'Skip confirmation prompt' }),
|
|
17
97
|
};
|
|
18
98
|
async run() {
|
|
19
99
|
this.requireAuth();
|
|
20
100
|
const { args, flags } = await this.parse(SpacesWorkflowsCancel);
|
|
101
|
+
const scope = flags.scope;
|
|
21
102
|
let confirmed;
|
|
22
103
|
try {
|
|
23
|
-
|
|
104
|
+
const scopeNote = scope === 'subtree'
|
|
105
|
+
? ' Child workflow runs it started are cancelled too.'
|
|
106
|
+
: ' Child workflow runs it started keep running (--scope subtree stops them too).';
|
|
107
|
+
confirmed = await (0, prompt_1.confirmDestructive)(`Cancel workflow run ${args.runId}? This stops workflow coordination; already-dispatched task execution may continue.${scopeNote}`, flags.yes);
|
|
24
108
|
}
|
|
25
109
|
catch (error) {
|
|
26
110
|
this.error(error.message, {
|
|
@@ -34,7 +118,7 @@ class SpacesWorkflowsCancel extends base_command_1.BaseCommand {
|
|
|
34
118
|
}
|
|
35
119
|
let run;
|
|
36
120
|
try {
|
|
37
|
-
run = await data_provider_1.dataService.cancelSpaceWorkflowRun(args.spaceId, args.runId);
|
|
121
|
+
run = await data_provider_1.dataService.cancelSpaceWorkflowRun(args.spaceId, args.runId, scope ? { scope } : {});
|
|
38
122
|
}
|
|
39
123
|
catch (error) {
|
|
40
124
|
this.handleApiError(error);
|
|
@@ -45,6 +129,28 @@ class SpacesWorkflowsCancel extends base_command_1.BaseCommand {
|
|
|
45
129
|
return;
|
|
46
130
|
}
|
|
47
131
|
this.log(`Cancelled workflow run ${run.id} (${run.status}).`);
|
|
132
|
+
for (const line of describeCancellationProgress(args.spaceId, run))
|
|
133
|
+
this.log(line);
|
|
134
|
+
if ((run.cancellation?.scope ?? run.cancellationScope ?? scope) === 'subtree')
|
|
135
|
+
return;
|
|
136
|
+
const childIds = childWorkflowRunIds(run);
|
|
137
|
+
if (childIds.length === 0)
|
|
138
|
+
return;
|
|
139
|
+
const children = await Promise.all(childIds.map(async (id) => {
|
|
140
|
+
try {
|
|
141
|
+
const child = await data_provider_1.dataService.getSpaceWorkflowRun(args.spaceId, id);
|
|
142
|
+
return { id, status: child.status };
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return { id, unreadable: true };
|
|
146
|
+
}
|
|
147
|
+
}));
|
|
148
|
+
const reviewedScope = Boolean(run.cancellationExpectedScope);
|
|
149
|
+
for (const line of describePreservedChildren(args.spaceId, run.id, children, {
|
|
150
|
+
reviewedScope,
|
|
151
|
+
})) {
|
|
152
|
+
this.log(line);
|
|
153
|
+
}
|
|
48
154
|
}
|
|
49
155
|
}
|
|
50
156
|
exports.default = SpacesWorkflowsCancel;
|
|
@@ -16,6 +16,15 @@ export declare function describeNodeAttention(node: {
|
|
|
16
16
|
message?: string;
|
|
17
17
|
} | null;
|
|
18
18
|
}): string;
|
|
19
|
+
export declare function describeLoopItemsNote(node: {
|
|
20
|
+
nodeKey?: unknown;
|
|
21
|
+
nodeType?: unknown;
|
|
22
|
+
output?: {
|
|
23
|
+
itemsStatus?: unknown;
|
|
24
|
+
itemsKey?: unknown;
|
|
25
|
+
itemsFoundType?: unknown;
|
|
26
|
+
} | null;
|
|
27
|
+
}): string;
|
|
19
28
|
export default class SpacesWorkflowsRun extends BaseCommand {
|
|
20
29
|
static description: string;
|
|
21
30
|
static args: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.describeNodeAttention = describeNodeAttention;
|
|
4
|
+
exports.describeLoopItemsNote = describeLoopItemsNote;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const base_command_1 = require("../../../base-command");
|
|
@@ -26,6 +27,38 @@ function describeNodeAttention(node) {
|
|
|
26
27
|
return `${reason}: ${message}`;
|
|
27
28
|
return reason || message || 'needs attention';
|
|
28
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* A note for a loop that succeeded having iterated nothing because its
|
|
32
|
+
* collection never arrived, or '' when there is nothing to say (OSK-15324).
|
|
33
|
+
*
|
|
34
|
+
* A zero-iteration loop is `succeeded`, so the plain table reads as healthy
|
|
35
|
+
* whether the list was legitimately empty or the value the author meant never
|
|
36
|
+
* reached the loop. The server records which on the node output; say it. An
|
|
37
|
+
* empty list is the legitimate case and stays silent.
|
|
38
|
+
*/
|
|
39
|
+
/** One printable line: control characters (an ESC sequence included) become spaces. */
|
|
40
|
+
function oneLine(value) {
|
|
41
|
+
// eslint-disable-next-line no-control-regex
|
|
42
|
+
return (0, format_1.collapseWhitespace)(value.replace(/[\u0000-\u001f\u007f-\u009f]/g, ' '));
|
|
43
|
+
}
|
|
44
|
+
function describeLoopItemsNote(node) {
|
|
45
|
+
if (node.nodeType !== 'loop')
|
|
46
|
+
return '';
|
|
47
|
+
const output = node.output;
|
|
48
|
+
// `itemsKey` is author-chosen free text, unlike a node key, so it is printed the way the
|
|
49
|
+
// table prints a cell: one line, no control characters.
|
|
50
|
+
const key = oneLine(typeof output?.itemsKey === 'string' && output.itemsKey ? output.itemsKey : 'items');
|
|
51
|
+
const name = oneLine(String(node.nodeKey ?? 'loop'));
|
|
52
|
+
if (output?.itemsStatus === 'missing') {
|
|
53
|
+
return `${name}: ran 0 iterations because its input "${key}" was missing or null`;
|
|
54
|
+
}
|
|
55
|
+
if (output?.itemsStatus === 'not_array') {
|
|
56
|
+
const found = typeof output.itemsFoundType === 'string' ? output.itemsFoundType : 'a value';
|
|
57
|
+
const article = /^[aeiou]/i.test(found) ? 'an' : 'a';
|
|
58
|
+
return `${name}: ran 0 iterations because its input "${key}" was ${article} ${oneLine(found)}, not a list`;
|
|
59
|
+
}
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
29
62
|
class SpacesWorkflowsRun extends base_command_1.BaseCommand {
|
|
30
63
|
static description = 'Inspect a workflow run and each durable node state';
|
|
31
64
|
static args = {
|
|
@@ -84,6 +117,11 @@ class SpacesWorkflowsRun extends base_command_1.BaseCommand {
|
|
|
84
117
|
? [{ key: 'attention', header: 'ATTENTION' }]
|
|
85
118
|
: []),
|
|
86
119
|
], (line) => this.log(line));
|
|
120
|
+
for (const node of nodes) {
|
|
121
|
+
const note = describeLoopItemsNote(node);
|
|
122
|
+
if (note)
|
|
123
|
+
this.log(`Note: ${note}`);
|
|
124
|
+
}
|
|
87
125
|
}
|
|
88
126
|
}
|
|
89
127
|
}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
import { type TaskApprovalResolveParams } from '@skrr-ai/data-provider';
|
|
1
2
|
import { BaseCommand } from '../../../base-command';
|
|
3
|
+
/**
|
|
4
|
+
* The request body for resolving an approval. The server's field is `comment`
|
|
5
|
+
* (`TaskApprovalResolveParams`); `--reason` is only the flag's name. It was sent
|
|
6
|
+
* as `reason` through an `as unknown as` cast, so the type checker could not see
|
|
7
|
+
* the mismatch and the server's non-strict schema dropped the key: the command
|
|
8
|
+
* succeeded and the reason was stored nowhere (OSK-15362).
|
|
9
|
+
*/
|
|
10
|
+
export declare function approvalResolutionBody(flags: {
|
|
11
|
+
status: 'approved' | 'rejected';
|
|
12
|
+
reason?: string;
|
|
13
|
+
}): TaskApprovalResolveParams;
|
|
2
14
|
export default class TasksApprovalsResolve extends BaseCommand {
|
|
3
15
|
static description: string;
|
|
4
16
|
static examples: string[];
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.approvalResolutionBody = approvalResolutionBody;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const base_command_1 = require("../../../base-command");
|
|
7
|
+
/**
|
|
8
|
+
* The request body for resolving an approval. The server's field is `comment`
|
|
9
|
+
* (`TaskApprovalResolveParams`); `--reason` is only the flag's name. It was sent
|
|
10
|
+
* as `reason` through an `as unknown as` cast, so the type checker could not see
|
|
11
|
+
* the mismatch and the server's non-strict schema dropped the key: the command
|
|
12
|
+
* succeeded and the reason was stored nowhere (OSK-15362).
|
|
13
|
+
*/
|
|
14
|
+
function approvalResolutionBody(flags) {
|
|
15
|
+
const body = { status: flags.status };
|
|
16
|
+
if (flags.reason)
|
|
17
|
+
body.comment = flags.reason;
|
|
18
|
+
return body;
|
|
19
|
+
}
|
|
6
20
|
class TasksApprovalsResolve extends base_command_1.BaseCommand {
|
|
7
21
|
static description = 'Resolve (approve or reject) a task approval';
|
|
8
22
|
static examples = [
|
|
@@ -27,15 +41,15 @@ class TasksApprovalsResolve extends base_command_1.BaseCommand {
|
|
|
27
41
|
this.requireAuth();
|
|
28
42
|
const { args, flags } = await this.parse(TasksApprovalsResolve);
|
|
29
43
|
const taskRef = await this.resolveEntityRef('task', args.id);
|
|
30
|
-
const data = { status: flags.status };
|
|
31
|
-
if (flags.reason)
|
|
32
|
-
data.reason = flags.reason;
|
|
33
44
|
let result;
|
|
34
45
|
try {
|
|
35
46
|
result = await data_provider_1.dataService.resolveTaskApproval({
|
|
36
47
|
taskId: taskRef,
|
|
37
48
|
approvalId: args.approvalId,
|
|
38
|
-
data:
|
|
49
|
+
data: approvalResolutionBody({
|
|
50
|
+
status: flags.status,
|
|
51
|
+
reason: flags.reason,
|
|
52
|
+
}),
|
|
39
53
|
});
|
|
40
54
|
}
|
|
41
55
|
catch (err) {
|
|
@@ -46,7 +60,9 @@ class TasksApprovalsResolve extends base_command_1.BaseCommand {
|
|
|
46
60
|
return;
|
|
47
61
|
}
|
|
48
62
|
const a = result;
|
|
49
|
-
|
|
63
|
+
// Say what was recorded, so a reason that was not stored cannot pass unseen.
|
|
64
|
+
const recorded = typeof a.comment === 'string' && a.comment ? ` (reason: ${a.comment})` : '';
|
|
65
|
+
this.log(`Approval ${a.id ?? a._id ?? args.approvalId} → ${flags.status}${recorded}`);
|
|
50
66
|
}
|
|
51
67
|
}
|
|
52
68
|
exports.default = TasksApprovalsResolve;
|
|
@@ -28,7 +28,7 @@ class TasksSchedule extends base_command_1.BaseCommand {
|
|
|
28
28
|
dependsOn: ['cron'],
|
|
29
29
|
}),
|
|
30
30
|
'max-runs': core_1.Flags.integer({
|
|
31
|
-
description: 'Cap total
|
|
31
|
+
description: 'Cap total occurrences (recurring only): each scheduled fire counts, and so does an occurrence you complete by hand before the scheduler touches it',
|
|
32
32
|
dependsOn: ['cron'],
|
|
33
33
|
}),
|
|
34
34
|
'end-date': core_1.Flags.string({
|
|
@@ -37,6 +37,13 @@ class TriggersCapabilities extends base_command_1.BaseCommand {
|
|
|
37
37
|
? capabilities.templateVariables.map((v) => typeof v === 'object' && v !== null ? String(v.name) : String(v))
|
|
38
38
|
: capabilities.templateVariableNames;
|
|
39
39
|
this.log(`Template vars: ${Array.isArray(vars) ? vars.join(', ') : '-'}`);
|
|
40
|
+
// Some scopes cannot create a trigger until something else is set up, and the refusal
|
|
41
|
+
// otherwise arrives only after submitting.
|
|
42
|
+
const needs = capabilities.prerequisites;
|
|
43
|
+
if (Array.isArray(needs)) {
|
|
44
|
+
for (const need of needs)
|
|
45
|
+
this.log(`Needs: ${String(need)}`);
|
|
46
|
+
}
|
|
40
47
|
// Beside the modes, because `external_work_task` is a mode that cannot be
|
|
41
48
|
// authored without one of these.
|
|
42
49
|
const contracts = capabilities.effectContracts;
|
|
@@ -20,7 +20,10 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
20
20
|
'from-json': core_1.Flags.string({
|
|
21
21
|
description: 'Path to a JSON file (or "-" for stdin) to use as the request body',
|
|
22
22
|
}),
|
|
23
|
-
scope: core_1.Flags.string({
|
|
23
|
+
scope: core_1.Flags.string({
|
|
24
|
+
description: 'Trigger scope kind. A scope can have prerequisites (a space_oracle Space needs a Leader agent): `triggers capabilities <scope>` lists them under "Needs"',
|
|
25
|
+
options: [...triggers_1.TRIGGER_SCOPE_KINDS],
|
|
26
|
+
}),
|
|
24
27
|
ref: core_1.Flags.string({
|
|
25
28
|
description: 'Scope ref as key=value (repeatable), for example --ref agentId=abc',
|
|
26
29
|
multiple: true,
|
|
@@ -88,7 +91,9 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
88
91
|
multiple: true,
|
|
89
92
|
}),
|
|
90
93
|
timezone: core_1.Flags.string({ description: 'IANA timezone for schedule triggers' }),
|
|
91
|
-
'max-fires-per-day': core_1.Flags.integer({
|
|
94
|
+
'max-fires-per-day': core_1.Flags.integer({
|
|
95
|
+
description: 'Daily fire cap (schedule, stochastic and self_scheduled triggers only)',
|
|
96
|
+
}),
|
|
92
97
|
'max-runs': core_1.Flags.integer({ description: 'Lifetime fire cap for schedule triggers' }),
|
|
93
98
|
'end-at': core_1.Flags.string({
|
|
94
99
|
description: 'ISO-8601 datetime after which a schedule stops firing',
|
|
@@ -189,6 +194,9 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
189
194
|
let payload;
|
|
190
195
|
try {
|
|
191
196
|
payload = await (0, prompt_1.readJsonBody)(flags['from-json']);
|
|
197
|
+
// A flag for a kind other than --kind is refused, not dropped: the block it fills is not
|
|
198
|
+
// sent, so the caller would believe a limit was set that nothing holds (OSK-15491).
|
|
199
|
+
(0, triggers_1.assertKindFlagsApply)(flags.kind ?? payload.kind, flags);
|
|
192
200
|
const refs = (0, triggers_1.parseKeyValueFlags)(flags.ref, '--ref', flags.scope ?? payload.scope?.kind);
|
|
193
201
|
if (flags.scope || Object.keys(refs).length > 0) {
|
|
194
202
|
payload.scope = {
|
|
@@ -264,22 +272,8 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
264
272
|
filterField: flags['filter-field'],
|
|
265
273
|
filterValues,
|
|
266
274
|
});
|
|
267
|
-
(0, triggers_1.
|
|
268
|
-
|
|
269
|
-
eventType: flags.event,
|
|
270
|
-
filterMode: flags['filter-mode'],
|
|
271
|
-
filterField: flags['filter-field'],
|
|
272
|
-
filterValue: filterValues && filterValues.length > 1 ? filterValues : filterValues?.[0],
|
|
273
|
-
debounceMs: flags['debounce-ms'],
|
|
274
|
-
maxPerHour: flags['max-per-hour'],
|
|
275
|
-
});
|
|
276
|
-
const stochastic = {};
|
|
277
|
-
(0, triggers_1.setDefined)(stochastic, {
|
|
278
|
-
probability: flags.probability === undefined ? undefined : Number(flags.probability),
|
|
279
|
-
jitterMs: flags['jitter-ms'],
|
|
280
|
-
maxFiresPerDay: flags['max-fires-per-day'],
|
|
281
|
-
evalIntervalMinutes: flags['eval-interval-minutes'],
|
|
282
|
-
});
|
|
275
|
+
Object.assign(event, (0, triggers_1.buildEventConfigFromFlags)(flags, filterValues));
|
|
276
|
+
const stochastic = (0, triggers_1.buildStochasticConfigFromFlags)(flags);
|
|
283
277
|
const selfScheduled = (0, triggers_1.buildSelfScheduledConfigFromFlags)(flags);
|
|
284
278
|
const form = (0, triggers_1.buildFormConfigFromFlags)(flags);
|
|
285
279
|
const chatMessage = (0, triggers_1.buildChatMessageConfigFromFlags)(flags);
|