@parall/cli 1.35.0 → 1.36.1
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/commands/external-triggers.d.ts +19 -0
- package/dist/commands/external-triggers.d.ts.map +1 -0
- package/dist/commands/external-triggers.js +488 -0
- package/dist/commands/messages.d.ts.map +1 -1
- package/dist/commands/messages.js +3 -0
- package/dist/commands/refs.d.ts +7 -0
- package/dist/commands/refs.d.ts.map +1 -1
- package/dist/commands/refs.js +25 -1
- package/dist/commands/search.d.ts +20 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +70 -0
- package/dist/commands/tasks.d.ts.map +1 -1
- package/dist/commands/tasks.js +15 -0
- package/dist/commands/wiki.d.ts.map +1 -1
- package/dist/commands/wiki.js +90 -0
- package/dist/index.js +4 -0
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +6 -0
- package/dist/lib/output.d.ts +12 -0
- package/dist/lib/output.d.ts.map +1 -1
- package/dist/lib/output.js +27 -0
- package/dist/lib/wiki-files.d.ts +76 -0
- package/dist/lib/wiki-files.d.ts.map +1 -0
- package/dist/lib/wiki-files.js +169 -0
- package/dist/lib/wiki-tools.d.ts +3 -2
- package/dist/lib/wiki-tools.d.ts.map +1 -1
- package/dist/lib/wiki-tools.js +171 -2
- package/dist/lib/wiki.d.ts +12 -0
- package/dist/lib/wiki.d.ts.map +1 -1
- package/dist/lib/wiki.js +26 -13
- package/package.json +3 -3
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExternalConnection } from '@parall/sdk';
|
|
2
|
+
import type { Command } from 'commander';
|
|
3
|
+
export declare const EXTERNAL_TRIGGERS_FLAG = "external-triggers";
|
|
4
|
+
type ExternalTriggerFeatureFlagClient = {
|
|
5
|
+
getFeatureFlags(orgId: string): Promise<{
|
|
6
|
+
flags: Record<string, boolean | string | number>;
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
type IngressTokenOutputOptions = {
|
|
10
|
+
tokenFile?: string;
|
|
11
|
+
showToken?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function isFeatureFlagEnabled(value: boolean | string | number | undefined): boolean;
|
|
14
|
+
export declare function requireExternalTriggersEnabled(client: ExternalTriggerFeatureFlagClient, orgId: string): Promise<void>;
|
|
15
|
+
export declare function validateIngressTokenOutputOptions(opts: IngressTokenOutputOptions): void;
|
|
16
|
+
export declare function connectionTokenOutput(connection: ExternalConnection, opts: IngressTokenOutputOptions): Promise<ExternalConnection | Record<string, unknown>>;
|
|
17
|
+
export declare function registerExternalTriggerCommands(program: Command): void;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=external-triggers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-triggers.d.ts","sourceRoot":"","sources":["../../src/commands/external-triggers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,kBAAkB,EAInB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D,KAAK,gCAAgC,GAAG;IACtC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/F,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAsDF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAM1F;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,gCAAgC,EACxC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAKf;AAQD,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,yBAAyB,GAAG,IAAI,CAKvF;AAED,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,kBAAkB,EAC9B,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqBvD;AAkBD,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,OAAO,QAqZ/D"}
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { chmod, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { resolveCredentials } from '../lib/client.js';
|
|
3
|
+
import { printError, printJson, printRefHint, stripPrllScheme } from '../lib/output.js';
|
|
4
|
+
const connectionStatuses = ['active', 'disabled'];
|
|
5
|
+
const triggerStatuses = ['active', 'paused'];
|
|
6
|
+
export const EXTERNAL_TRIGGERS_FLAG = 'external-triggers';
|
|
7
|
+
function stripUndefined(obj) {
|
|
8
|
+
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
|
|
9
|
+
}
|
|
10
|
+
function parseIds(value, flag) {
|
|
11
|
+
const ids = value
|
|
12
|
+
.split(',')
|
|
13
|
+
.map((s) => stripPrllScheme(s.trim()))
|
|
14
|
+
.filter(Boolean);
|
|
15
|
+
if (ids.length === 0) {
|
|
16
|
+
throw new Error(`${flag} must include at least one ID.`);
|
|
17
|
+
}
|
|
18
|
+
return ids;
|
|
19
|
+
}
|
|
20
|
+
function parsePositiveInt(value, flag) {
|
|
21
|
+
if (value === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
const normalized = value.trim();
|
|
24
|
+
const parsed = Number(normalized);
|
|
25
|
+
if (normalized === '' || !Number.isInteger(parsed) || parsed <= 0) {
|
|
26
|
+
throw new Error(`${flag} must be a positive integer.`);
|
|
27
|
+
}
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
function parseEnum(value, allowed, flag) {
|
|
31
|
+
if (value === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (allowed.includes(value))
|
|
34
|
+
return value;
|
|
35
|
+
throw new Error(`${flag} must be one of: ${allowed.join(', ')}.`);
|
|
36
|
+
}
|
|
37
|
+
function parseJsonObject(value, flag) {
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
let parsed;
|
|
41
|
+
try {
|
|
42
|
+
parsed = JSON.parse(value);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new Error(`${flag} must be a valid JSON object.`);
|
|
46
|
+
}
|
|
47
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
48
|
+
throw new Error(`${flag} must be a JSON object.`);
|
|
49
|
+
}
|
|
50
|
+
return parsed;
|
|
51
|
+
}
|
|
52
|
+
export function isFeatureFlagEnabled(value) {
|
|
53
|
+
return (value === true ||
|
|
54
|
+
(typeof value === 'string' && value !== '') ||
|
|
55
|
+
(typeof value === 'number' && value !== 0));
|
|
56
|
+
}
|
|
57
|
+
export async function requireExternalTriggersEnabled(client, orgId) {
|
|
58
|
+
const res = await client.getFeatureFlags(orgId);
|
|
59
|
+
if (!isFeatureFlagEnabled(res.flags[EXTERNAL_TRIGGERS_FLAG])) {
|
|
60
|
+
throw new Error('External Triggers are disabled for this organization.');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function resolveExternalTriggerCommandContext() {
|
|
64
|
+
const ctx = resolveCredentials();
|
|
65
|
+
await requireExternalTriggersEnabled(ctx.client, ctx.orgId);
|
|
66
|
+
return ctx;
|
|
67
|
+
}
|
|
68
|
+
export function validateIngressTokenOutputOptions(opts) {
|
|
69
|
+
const count = [opts.tokenFile, opts.showToken].filter(Boolean).length;
|
|
70
|
+
if (count !== 1) {
|
|
71
|
+
throw new Error('Choose exactly one token output mode: --token-file <path> or --show-token.');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export async function connectionTokenOutput(connection, opts) {
|
|
75
|
+
validateIngressTokenOutputOptions(opts);
|
|
76
|
+
if (!connection.ingress_token) {
|
|
77
|
+
throw new Error('Server did not return an ingress token.');
|
|
78
|
+
}
|
|
79
|
+
if (opts.showToken)
|
|
80
|
+
return connection;
|
|
81
|
+
if (!opts.tokenFile) {
|
|
82
|
+
throw new Error('Choose exactly one token output mode: --token-file <path> or --show-token.');
|
|
83
|
+
}
|
|
84
|
+
await writeFile(opts.tokenFile, connection.ingress_token, { mode: 0o600 });
|
|
85
|
+
await chmod(opts.tokenFile, 0o600);
|
|
86
|
+
const redacted = { ...connection };
|
|
87
|
+
delete redacted.ingress_token;
|
|
88
|
+
delete redacted.ingress_url;
|
|
89
|
+
return {
|
|
90
|
+
...redacted,
|
|
91
|
+
ingress_token_redacted: true,
|
|
92
|
+
ingress_url_redacted: true,
|
|
93
|
+
ingress_token_file: opts.tokenFile,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function resolveTemplate(opts) {
|
|
97
|
+
if (opts.template !== undefined && opts.templateFile !== undefined) {
|
|
98
|
+
throw new Error('Do not pass --template together with --template-file.');
|
|
99
|
+
}
|
|
100
|
+
if (opts.templateFile !== undefined) {
|
|
101
|
+
return readFile(opts.templateFile, 'utf8');
|
|
102
|
+
}
|
|
103
|
+
if (opts.template !== undefined)
|
|
104
|
+
return opts.template;
|
|
105
|
+
if (opts.required)
|
|
106
|
+
throw new Error('Provide --template or --template-file.');
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
export function registerExternalTriggerCommands(program) {
|
|
110
|
+
const externalTriggers = program
|
|
111
|
+
.command('external-triggers')
|
|
112
|
+
.description('Manage External Triggers (incoming platform triggers for agents)');
|
|
113
|
+
externalTriggers
|
|
114
|
+
.command('connections')
|
|
115
|
+
.description('List External Trigger Connections in the organization')
|
|
116
|
+
.option('--limit <n>', 'Maximum number of connections to return', '50')
|
|
117
|
+
.option('--cursor <cursor>', 'Pagination cursor')
|
|
118
|
+
.action(async (opts) => {
|
|
119
|
+
try {
|
|
120
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
121
|
+
const result = await client.listExternalConnections(orgId, stripUndefined({
|
|
122
|
+
limit: parsePositiveInt(opts.limit, '--limit'),
|
|
123
|
+
cursor: opts.cursor,
|
|
124
|
+
}));
|
|
125
|
+
printJson(result);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
printError(err);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
externalTriggers
|
|
132
|
+
.command('create-connection')
|
|
133
|
+
.description('Create an External Trigger Connection and return its incoming endpoint')
|
|
134
|
+
.requiredOption('--name <name>', 'Connection display name')
|
|
135
|
+
.option('--token-file <path>', 'Write the one-time token to a file with mode 0600')
|
|
136
|
+
.option('--show-token', 'Print the one-time token to stdout')
|
|
137
|
+
.action(async (opts) => {
|
|
138
|
+
try {
|
|
139
|
+
validateIngressTokenOutputOptions(opts);
|
|
140
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
141
|
+
const result = await client.createExternalConnection(orgId, {
|
|
142
|
+
display_name: opts.name,
|
|
143
|
+
});
|
|
144
|
+
printJson(await connectionTokenOutput(result, opts));
|
|
145
|
+
printRefHint(result.id);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
printError(err);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
externalTriggers
|
|
152
|
+
.command('connection')
|
|
153
|
+
.description('Get an External Trigger Connection by ID')
|
|
154
|
+
.argument('<connectionId>', 'External Trigger Connection ID')
|
|
155
|
+
.action(async (connectionId) => {
|
|
156
|
+
try {
|
|
157
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
158
|
+
const result = await client.getExternalConnection(orgId, stripPrllScheme(connectionId));
|
|
159
|
+
printJson(result);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
printError(err);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
externalTriggers
|
|
166
|
+
.command('update-connection')
|
|
167
|
+
.description('Update an External Trigger Connection')
|
|
168
|
+
.argument('<connectionId>', 'External Trigger Connection ID')
|
|
169
|
+
.option('--name <name>', 'Connection display name')
|
|
170
|
+
.option('--status <status>', 'active | disabled')
|
|
171
|
+
.action(async (connectionId, opts) => {
|
|
172
|
+
try {
|
|
173
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
174
|
+
const patch = stripUndefined({
|
|
175
|
+
display_name: opts.name,
|
|
176
|
+
status: parseEnum(opts.status, connectionStatuses, '--status'),
|
|
177
|
+
});
|
|
178
|
+
if (Object.keys(patch).length === 0) {
|
|
179
|
+
printError(new Error('No fields to update. Provide at least one option.'));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const result = await client.updateExternalConnection(orgId, stripPrllScheme(connectionId), patch);
|
|
183
|
+
printJson(result);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
printError(err);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
externalTriggers
|
|
190
|
+
.command('regenerate-connection-token')
|
|
191
|
+
.description('Regenerate a connection ingress token; old webhook URLs stop working')
|
|
192
|
+
.argument('<connectionId>', 'External Trigger Connection ID')
|
|
193
|
+
.option('--token-file <path>', 'Write the one-time token to a file with mode 0600')
|
|
194
|
+
.option('--show-token', 'Print the one-time token to stdout')
|
|
195
|
+
.action(async (connectionId, opts) => {
|
|
196
|
+
try {
|
|
197
|
+
validateIngressTokenOutputOptions(opts);
|
|
198
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
199
|
+
const result = await client.regenerateExternalConnectionIngressToken(orgId, stripPrllScheme(connectionId));
|
|
200
|
+
printJson(await connectionTokenOutput(result, opts));
|
|
201
|
+
printRefHint(result.id, 'Regenerated');
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
printError(err);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
externalTriggers
|
|
208
|
+
.command('delete-connection')
|
|
209
|
+
.description('Archive an External Trigger Connection')
|
|
210
|
+
.argument('<connectionId>', 'External Trigger Connection ID')
|
|
211
|
+
.action(async (connectionId) => {
|
|
212
|
+
try {
|
|
213
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
214
|
+
await client.deleteExternalConnection(orgId, stripPrllScheme(connectionId));
|
|
215
|
+
printJson({ ok: true });
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
printError(err);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
externalTriggers
|
|
222
|
+
.command('schema')
|
|
223
|
+
.description('Inspect CEL/template variables supported by a connection')
|
|
224
|
+
.argument('<connectionId>', 'External Trigger Connection ID')
|
|
225
|
+
.action(async (connectionId) => {
|
|
226
|
+
try {
|
|
227
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
228
|
+
const result = await client.getExternalTriggerSchema(orgId, stripPrllScheme(connectionId));
|
|
229
|
+
printJson(result);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
printError(err);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
externalTriggers
|
|
236
|
+
.command('list')
|
|
237
|
+
.description('List External Triggers in the organization')
|
|
238
|
+
.option('--connection <connectionId>', 'Filter by External Trigger Connection ID')
|
|
239
|
+
.option('--creator-id <id>', 'Filter by creator user ID')
|
|
240
|
+
.option('--limit <n>', 'Maximum number of triggers to return', '50')
|
|
241
|
+
.option('--cursor <cursor>', 'Pagination cursor')
|
|
242
|
+
.action(async (opts) => {
|
|
243
|
+
try {
|
|
244
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
245
|
+
const result = await client.listExternalTriggers(orgId, stripUndefined({
|
|
246
|
+
connection_id: opts.connection ? stripPrllScheme(opts.connection) : undefined,
|
|
247
|
+
creator_id: opts.creatorId ? stripPrllScheme(opts.creatorId) : undefined,
|
|
248
|
+
limit: parsePositiveInt(opts.limit, '--limit'),
|
|
249
|
+
cursor: opts.cursor,
|
|
250
|
+
}));
|
|
251
|
+
printJson(result);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
printError(err);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
externalTriggers
|
|
258
|
+
.command('create')
|
|
259
|
+
.description('Create an External Trigger targeting one or more agents')
|
|
260
|
+
.requiredOption('--connection <connectionId>', 'External Trigger Connection ID')
|
|
261
|
+
.requiredOption('--name <name>', 'Trigger name')
|
|
262
|
+
.requiredOption('--target-ids <ids>', 'Comma-separated target agent user IDs')
|
|
263
|
+
.option('--description <text>', 'Human-facing trigger description')
|
|
264
|
+
.option('--attached-to-uri <uri>', 'Attach to a prll:// resource URI')
|
|
265
|
+
.option('--filter <expr>', 'CEL filter expression', 'true')
|
|
266
|
+
.option('--filter-metadata-json <json>', 'JSON object with UI/display metadata for the filter')
|
|
267
|
+
.option('--template <text>', 'Liquid template for the agent input body')
|
|
268
|
+
.option('--template-file <path>', 'Read the Liquid template from a file')
|
|
269
|
+
.option('--max-runs <n>', 'Maximum delivered runs before the trigger auto-archives')
|
|
270
|
+
.option('--expires-at <ts>', 'Expiration time (RFC3339)')
|
|
271
|
+
.option('--client-context-json <json>', 'JSON object stored with the trigger')
|
|
272
|
+
.action(async (opts) => {
|
|
273
|
+
try {
|
|
274
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
275
|
+
const agentInputTemplate = await resolveTemplate({ ...opts, required: true });
|
|
276
|
+
const data = {
|
|
277
|
+
connection_id: stripPrllScheme(opts.connection),
|
|
278
|
+
name: opts.name,
|
|
279
|
+
target_agent_ids: parseIds(opts.targetIds, '--target-ids'),
|
|
280
|
+
filter_expr: opts.filter,
|
|
281
|
+
agent_input_template: agentInputTemplate ?? '',
|
|
282
|
+
...stripUndefined({
|
|
283
|
+
description: opts.description,
|
|
284
|
+
attached_to_uri: opts.attachedToUri,
|
|
285
|
+
filter_display_metadata: parseJsonObject(opts.filterMetadataJson, '--filter-metadata-json'),
|
|
286
|
+
max_runs: parsePositiveInt(opts.maxRuns, '--max-runs'),
|
|
287
|
+
expires_at: opts.expiresAt,
|
|
288
|
+
client_context: parseJsonObject(opts.clientContextJson, '--client-context-json'),
|
|
289
|
+
}),
|
|
290
|
+
};
|
|
291
|
+
const result = await client.createExternalTrigger(orgId, data);
|
|
292
|
+
printJson(result);
|
|
293
|
+
printRefHint(result.id);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
printError(err);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
externalTriggers
|
|
300
|
+
.command('get')
|
|
301
|
+
.description('Get an External Trigger by ID')
|
|
302
|
+
.argument('<triggerId>', 'External Trigger ID')
|
|
303
|
+
.action(async (triggerId) => {
|
|
304
|
+
try {
|
|
305
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
306
|
+
const result = await client.getExternalTrigger(orgId, stripPrllScheme(triggerId));
|
|
307
|
+
printJson(result);
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
printError(err);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
externalTriggers
|
|
314
|
+
.command('update')
|
|
315
|
+
.description('Update an External Trigger')
|
|
316
|
+
.argument('<triggerId>', 'External Trigger ID')
|
|
317
|
+
.option('--name <name>', 'Trigger name')
|
|
318
|
+
.option('--description <text>', 'Human-facing trigger description')
|
|
319
|
+
.option('--status <status>', 'active | paused')
|
|
320
|
+
.option('--target-ids <ids>', 'Comma-separated target agent user IDs')
|
|
321
|
+
.option('--attached-to-uri <uri>', 'Attach to a prll:// resource URI')
|
|
322
|
+
.option('--clear-attached-to', 'Explicitly clear attached_to_uri')
|
|
323
|
+
.option('--filter <expr>', 'CEL filter expression')
|
|
324
|
+
.option('--filter-metadata-json <json>', 'JSON object with UI/display metadata for the filter')
|
|
325
|
+
.option('--template <text>', 'Liquid template for the agent input body')
|
|
326
|
+
.option('--template-file <path>', 'Read the Liquid template from a file')
|
|
327
|
+
.option('--max-runs <n>', 'Maximum delivered runs before the trigger auto-archives')
|
|
328
|
+
.option('--clear-max-runs', 'Explicitly clear max_runs')
|
|
329
|
+
.option('--expires-at <ts>', 'Expiration time (RFC3339)')
|
|
330
|
+
.option('--clear-expires-at', 'Explicitly clear expires_at')
|
|
331
|
+
.option('--client-context-json <json>', 'JSON object stored with the trigger')
|
|
332
|
+
.action(async (triggerId, opts) => {
|
|
333
|
+
try {
|
|
334
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
335
|
+
const conflicts = [
|
|
336
|
+
[opts.attachedToUri, opts.clearAttachedTo, '--attached-to-uri', '--clear-attached-to'],
|
|
337
|
+
[opts.maxRuns, opts.clearMaxRuns, '--max-runs', '--clear-max-runs'],
|
|
338
|
+
[opts.expiresAt, opts.clearExpiresAt, '--expires-at', '--clear-expires-at'],
|
|
339
|
+
];
|
|
340
|
+
for (const [value, clear, valueFlag, clearFlag] of conflicts) {
|
|
341
|
+
if (value !== undefined && clear) {
|
|
342
|
+
printError(new Error(`Do not pass ${valueFlag} together with ${clearFlag}.`));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const agentInputTemplate = await resolveTemplate(opts);
|
|
347
|
+
const patch = stripUndefined({
|
|
348
|
+
name: opts.name,
|
|
349
|
+
description: opts.description,
|
|
350
|
+
status: parseEnum(opts.status, triggerStatuses, '--status'),
|
|
351
|
+
target_agent_ids: opts.targetIds !== undefined ? parseIds(opts.targetIds, '--target-ids') : undefined,
|
|
352
|
+
attached_to_uri: opts.attachedToUri,
|
|
353
|
+
attached_to_uri_clear: opts.clearAttachedTo || undefined,
|
|
354
|
+
filter_expr: opts.filter,
|
|
355
|
+
filter_display_metadata: parseJsonObject(opts.filterMetadataJson, '--filter-metadata-json'),
|
|
356
|
+
agent_input_template: agentInputTemplate,
|
|
357
|
+
max_runs: parsePositiveInt(opts.maxRuns, '--max-runs'),
|
|
358
|
+
max_runs_clear: opts.clearMaxRuns || undefined,
|
|
359
|
+
expires_at: opts.expiresAt,
|
|
360
|
+
expires_at_clear: opts.clearExpiresAt || undefined,
|
|
361
|
+
client_context: parseJsonObject(opts.clientContextJson, '--client-context-json'),
|
|
362
|
+
});
|
|
363
|
+
if (Object.keys(patch).length === 0) {
|
|
364
|
+
printError(new Error('No fields to update. Provide at least one option.'));
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const result = await client.updateExternalTrigger(orgId, stripPrllScheme(triggerId), patch);
|
|
368
|
+
printJson(result);
|
|
369
|
+
}
|
|
370
|
+
catch (err) {
|
|
371
|
+
printError(err);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
externalTriggers
|
|
375
|
+
.command('pause')
|
|
376
|
+
.description('Pause an External Trigger')
|
|
377
|
+
.argument('<triggerId>', 'External Trigger ID')
|
|
378
|
+
.action(async (triggerId) => {
|
|
379
|
+
try {
|
|
380
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
381
|
+
const result = await client.updateExternalTrigger(orgId, stripPrllScheme(triggerId), {
|
|
382
|
+
status: 'paused',
|
|
383
|
+
});
|
|
384
|
+
printJson(result);
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
printError(err);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
externalTriggers
|
|
391
|
+
.command('resume')
|
|
392
|
+
.description('Resume a paused External Trigger')
|
|
393
|
+
.argument('<triggerId>', 'External Trigger ID')
|
|
394
|
+
.action(async (triggerId) => {
|
|
395
|
+
try {
|
|
396
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
397
|
+
const result = await client.updateExternalTrigger(orgId, stripPrllScheme(triggerId), {
|
|
398
|
+
status: 'active',
|
|
399
|
+
});
|
|
400
|
+
printJson(result);
|
|
401
|
+
}
|
|
402
|
+
catch (err) {
|
|
403
|
+
printError(err);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
externalTriggers
|
|
407
|
+
.command('delete')
|
|
408
|
+
.description('Archive an External Trigger')
|
|
409
|
+
.argument('<triggerId>', 'External Trigger ID')
|
|
410
|
+
.action(async (triggerId) => {
|
|
411
|
+
try {
|
|
412
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
413
|
+
await client.deleteExternalTrigger(orgId, stripPrllScheme(triggerId));
|
|
414
|
+
printJson({ ok: true });
|
|
415
|
+
}
|
|
416
|
+
catch (err) {
|
|
417
|
+
printError(err);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
externalTriggers
|
|
421
|
+
.command('runs')
|
|
422
|
+
.description('List run history for an External Trigger')
|
|
423
|
+
.argument('<triggerId>', 'External Trigger ID')
|
|
424
|
+
.option('--limit <n>', 'Maximum number of runs to return', '50')
|
|
425
|
+
.option('--cursor <cursor>', 'Pagination cursor')
|
|
426
|
+
.action(async (triggerId, opts) => {
|
|
427
|
+
try {
|
|
428
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
429
|
+
const result = await client.listExternalTriggerRuns(orgId, stripUndefined({
|
|
430
|
+
trigger_id: stripPrllScheme(triggerId),
|
|
431
|
+
limit: parsePositiveInt(opts.limit, '--limit'),
|
|
432
|
+
cursor: opts.cursor,
|
|
433
|
+
}));
|
|
434
|
+
printJson(result);
|
|
435
|
+
}
|
|
436
|
+
catch (err) {
|
|
437
|
+
printError(err);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
externalTriggers
|
|
441
|
+
.command('run')
|
|
442
|
+
.description('Get a single External Trigger run')
|
|
443
|
+
.argument('<runId>', 'External Trigger Run ID (xrn_...)')
|
|
444
|
+
.action(async (runId) => {
|
|
445
|
+
try {
|
|
446
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
447
|
+
const result = await client.getExternalTriggerRun(orgId, stripPrllScheme(runId));
|
|
448
|
+
printJson(result);
|
|
449
|
+
}
|
|
450
|
+
catch (err) {
|
|
451
|
+
printError(err);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
externalTriggers
|
|
455
|
+
.command('events')
|
|
456
|
+
.description('List incoming events received by External Trigger Connections')
|
|
457
|
+
.option('--connection <connectionId>', 'Filter by External Trigger Connection ID')
|
|
458
|
+
.option('--limit <n>', 'Maximum number of events to return', '50')
|
|
459
|
+
.option('--cursor <cursor>', 'Pagination cursor')
|
|
460
|
+
.action(async (opts) => {
|
|
461
|
+
try {
|
|
462
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
463
|
+
const result = await client.listExternalIngressEvents(orgId, stripUndefined({
|
|
464
|
+
connection_id: opts.connection ? stripPrllScheme(opts.connection) : undefined,
|
|
465
|
+
limit: parsePositiveInt(opts.limit, '--limit'),
|
|
466
|
+
cursor: opts.cursor,
|
|
467
|
+
}));
|
|
468
|
+
printJson(result);
|
|
469
|
+
}
|
|
470
|
+
catch (err) {
|
|
471
|
+
printError(err);
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
externalTriggers
|
|
475
|
+
.command('event')
|
|
476
|
+
.description('Get a single incoming event by ID')
|
|
477
|
+
.argument('<eventId>', 'External Trigger Event ID (xin_...)')
|
|
478
|
+
.action(async (eventId) => {
|
|
479
|
+
try {
|
|
480
|
+
const { client, orgId } = await resolveExternalTriggerCommandContext();
|
|
481
|
+
const result = await client.getExternalIngressEvent(orgId, stripPrllScheme(eventId));
|
|
482
|
+
printJson(result);
|
|
483
|
+
}
|
|
484
|
+
catch (err) {
|
|
485
|
+
printError(err);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAwJvD"}
|
|
@@ -11,6 +11,7 @@ export function registerMessageCommands(program) {
|
|
|
11
11
|
.option('--limit <n>', 'Maximum number of messages to return', '20')
|
|
12
12
|
.option('--before <cursor>', 'Cursor for messages before')
|
|
13
13
|
.option('--after <cursor>', 'Cursor for messages after')
|
|
14
|
+
.option('--since <date>', 'Only messages at/after this time (RFC3339 or YYYY-MM-DD)')
|
|
14
15
|
.option('--thread-root-id <id>', 'Filter by thread root message ID')
|
|
15
16
|
.option('--top-level', 'Only return top-level messages')
|
|
16
17
|
.action(async (chatId, opts) => {
|
|
@@ -21,6 +22,8 @@ export function registerMessageCommands(program) {
|
|
|
21
22
|
params.before = stripPrllScheme(opts.before);
|
|
22
23
|
if (opts.after !== undefined)
|
|
23
24
|
params.after = stripPrllScheme(opts.after);
|
|
25
|
+
if (opts.since !== undefined)
|
|
26
|
+
params.since = opts.since;
|
|
24
27
|
if (opts.threadRootId !== undefined)
|
|
25
28
|
params.thread_root_id = stripPrllScheme(opts.threadRootId);
|
|
26
29
|
if (opts.topLevel)
|
package/dist/commands/refs.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
/** Build the SDK ref-graph params from the positional URI + CLI flags. */
|
|
3
|
+
export declare function buildRefGraphParams(uri: string, opts: {
|
|
4
|
+
depth?: string;
|
|
5
|
+
}): {
|
|
6
|
+
uri: string;
|
|
7
|
+
depth?: number;
|
|
8
|
+
};
|
|
2
9
|
export declare function registerRefCommands(program: Command): void;
|
|
3
10
|
//# sourceMappingURL=refs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../src/commands/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QA+
|
|
1
|
+
{"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../src/commands/refs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,0EAA0E;AAC1E,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACvB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAOjC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QA+DnD"}
|
package/dist/commands/refs.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { resolveCredentials } from '../lib/client.js';
|
|
2
|
-
import {
|
|
2
|
+
import { ensurePrllScheme, parsePositiveInt, printError, printJson } from '../lib/output.js';
|
|
3
|
+
/** Build the SDK ref-graph params from the positional URI + CLI flags. */
|
|
4
|
+
export function buildRefGraphParams(uri, opts) {
|
|
5
|
+
const params = { uri: ensurePrllScheme(uri) };
|
|
6
|
+
// Drop a non-positive-integer --depth (NaN / 1.5 / -2) so the server applies
|
|
7
|
+
// its default; the server clamps the valid range (1–4) regardless.
|
|
8
|
+
const depth = parsePositiveInt(opts.depth);
|
|
9
|
+
if (depth !== undefined)
|
|
10
|
+
params.depth = depth;
|
|
11
|
+
return params;
|
|
12
|
+
}
|
|
3
13
|
export function registerRefCommands(program) {
|
|
4
14
|
const refs = program.command('refs').description('Reference resolution and backlinks');
|
|
5
15
|
refs
|
|
@@ -34,6 +44,20 @@ export function registerRefCommands(program) {
|
|
|
34
44
|
printError(err);
|
|
35
45
|
}
|
|
36
46
|
});
|
|
47
|
+
refs
|
|
48
|
+
.command('graph <uri>')
|
|
49
|
+
.description('Multi-hop traversal of the prll:// reference graph around an entity-level URI (no path/anchor)')
|
|
50
|
+
.option('--depth <n>', 'Hops to traverse outward (server clamps to 1–4)', '2')
|
|
51
|
+
.action(async (uri, opts) => {
|
|
52
|
+
try {
|
|
53
|
+
const { client, orgId } = resolveCredentials();
|
|
54
|
+
const result = await client.getRefsGraph(orgId, buildRefGraphParams(uri, opts));
|
|
55
|
+
printJson(result);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
printError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
37
61
|
refs
|
|
38
62
|
.command('check')
|
|
39
63
|
.description('Check for broken references in the organization (admin only)')
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SearchParams } from '@parall/sdk';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a `--types m,t,w` flag into the server's CSV of canonical entity
|
|
5
|
+
* names (`message,task,wiki`). Unknown tokens pass through unchanged so the
|
|
6
|
+
* server can reject/ignore them. Returns undefined for an empty/absent flag so
|
|
7
|
+
* the server applies its default (search all three).
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalizeSearchTypes(raw?: string): string | undefined;
|
|
10
|
+
export interface SearchOpts {
|
|
11
|
+
types?: string;
|
|
12
|
+
channel?: string;
|
|
13
|
+
limit?: string;
|
|
14
|
+
wikiType?: string;
|
|
15
|
+
since?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Build the SDK search params from the positional query + CLI flags. */
|
|
18
|
+
export declare function buildSearchParams(query: string, opts: SearchOpts): SearchParams;
|
|
19
|
+
export declare function registerSearchCommands(program: Command): void;
|
|
20
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASrE;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,YAAY,CAY/E;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,QA4BtD"}
|