epismo 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -40
- package/dist/input.js +0 -24
- package/dist/input.js.map +1 -1
- package/dist/packs.js +17 -20
- package/dist/packs.js.map +1 -1
- package/dist/program.js +207 -176
- package/dist/program.js.map +1 -1
- package/dist/projects.js +20 -15
- package/dist/projects.js.map +1 -1
- package/dist/tracks.js +3 -5
- package/dist/tracks.js.map +1 -1
- package/dist/workspaces.js +19 -11
- package/dist/workspaces.js.map +1 -1
- package/package.json +1 -1
package/dist/program.js
CHANGED
|
@@ -9,8 +9,8 @@ import { deleteAlias, getAlias, listAliases, upsertAlias } from "./aliases.js";
|
|
|
9
9
|
import { creditBalance, creditCheckout } from "./credits.js";
|
|
10
10
|
import { CliError } from "./errors.js";
|
|
11
11
|
import { addAgents, listAgents, removeAgents } from "./agents.js";
|
|
12
|
-
import { createWorkspace,
|
|
13
|
-
import {
|
|
12
|
+
import { createWorkspace, deleteWorkspaceMembers, getWorkspaceCheckout, listWorkspaceMembers, updateWorkspace, upsertWorkspaceMembers } from "./workspaces.js";
|
|
13
|
+
import { addProjectMembers, createProject, deleteProject, deleteProjectMembers, listProjectMembers, listProjects, updateProject } from "./projects.js";
|
|
14
14
|
import { createToken } from "./token.js";
|
|
15
15
|
const TRACK_TYPES = ["task", "goal"];
|
|
16
16
|
const PACK_TYPES = ["workflow", "context"];
|
|
@@ -31,15 +31,53 @@ function getExplicitOptionOverride(command, optionName, value) {
|
|
|
31
31
|
}
|
|
32
32
|
return value;
|
|
33
33
|
}
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
function buildScopeOption(command, options) {
|
|
35
|
+
const personalExplicit = getExplicitOptionOverride(command, "personal", options.personal);
|
|
36
|
+
const projectsExplicit = getExplicitOptionOverride(command, "projects", parseStringArrayInput(options.projects, "--projects"));
|
|
37
|
+
if (personalExplicit !== undefined && projectsExplicit !== undefined) {
|
|
38
|
+
throw new CliError({
|
|
39
|
+
code: "INVALID_INPUT",
|
|
40
|
+
message: "--personal and --projects cannot be combined."
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (personalExplicit === true) {
|
|
44
|
+
return { type: "personal" };
|
|
45
|
+
}
|
|
46
|
+
if (projectsExplicit !== undefined) {
|
|
47
|
+
const ids = projectsExplicit;
|
|
48
|
+
if (ids.length === 0) {
|
|
49
|
+
throw new CliError({
|
|
50
|
+
code: "INVALID_INPUT",
|
|
51
|
+
message: "--projects requires at least one project id."
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return { type: "projects", ids };
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
function buildSharedWithOption(command, options) {
|
|
59
|
+
const values = getExplicitOptionOverride(command, "shareWith", parseStringArrayInput(options.shareWith, "--share-with"));
|
|
60
|
+
if (values === undefined) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const emails = [];
|
|
64
|
+
const userIds = [];
|
|
65
|
+
for (const value of values) {
|
|
66
|
+
if (value.includes("@")) {
|
|
67
|
+
emails.push(value);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
userIds.push(value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const result = {};
|
|
74
|
+
if (userIds.length > 0) {
|
|
75
|
+
result.userIds = userIds;
|
|
76
|
+
}
|
|
77
|
+
if (emails.length > 0) {
|
|
78
|
+
result.emails = emails;
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
43
81
|
}
|
|
44
82
|
function buildSearchTargets(command, options) {
|
|
45
83
|
const targets = mergeDefined({}, {
|
|
@@ -104,9 +142,9 @@ Examples:
|
|
|
104
142
|
epismo alias list
|
|
105
143
|
epismo track search --query "bug"
|
|
106
144
|
epismo pack search --query "meeting notes"
|
|
107
|
-
epismo pack get
|
|
108
|
-
epismo pack get
|
|
109
|
-
epismo pack get
|
|
145
|
+
epismo pack get <id> --block-id b001
|
|
146
|
+
epismo pack get @myproject
|
|
147
|
+
epismo pack get @handle/myproject`);
|
|
110
148
|
program
|
|
111
149
|
.command("login")
|
|
112
150
|
.description("log in to Epismo; default flow uses email + OTP, or open a browser to sign in")
|
|
@@ -181,13 +219,13 @@ Example:
|
|
|
181
219
|
workspace
|
|
182
220
|
.command("use")
|
|
183
221
|
.description("set the default workspace")
|
|
184
|
-
.
|
|
185
|
-
.action(async (
|
|
186
|
-
printJson(await useWorkspace({ workspaceId
|
|
222
|
+
.argument("<workspace-id>", "workspace id to set as default")
|
|
223
|
+
.action(async (workspaceId) => {
|
|
224
|
+
printJson(await useWorkspace({ workspaceId }));
|
|
187
225
|
});
|
|
188
226
|
workspace.commands.at(-1)?.addHelpText("after", `
|
|
189
227
|
Example:
|
|
190
|
-
epismo workspace use
|
|
228
|
+
epismo workspace use <workspace-id>`);
|
|
191
229
|
workspace
|
|
192
230
|
.command("clear")
|
|
193
231
|
.description("clear the saved workspace (reverts to personal space)")
|
|
@@ -223,25 +261,25 @@ Examples:
|
|
|
223
261
|
workspace
|
|
224
262
|
.command("checkout")
|
|
225
263
|
.description("get the billing URL for a workspace (to complete or retry payment)")
|
|
226
|
-
.
|
|
227
|
-
.action(async (
|
|
264
|
+
.argument("<workspace-id>", "workspace id")
|
|
265
|
+
.action(async (workspaceId) => {
|
|
228
266
|
const context = await resolveContext();
|
|
229
|
-
printJson(await getWorkspaceCheckout(context,
|
|
267
|
+
printJson(await getWorkspaceCheckout(context, workspaceId));
|
|
230
268
|
});
|
|
231
269
|
workspace.commands.at(-1)?.addHelpText("after", `
|
|
232
270
|
Examples:
|
|
233
|
-
epismo workspace checkout
|
|
271
|
+
epismo workspace checkout <workspace-id>`);
|
|
234
272
|
workspace
|
|
235
273
|
.command("update")
|
|
236
274
|
.description("update a workspace you own (PATCH — omitted fields are unchanged)")
|
|
275
|
+
.argument("<workspace-id>", "workspace id to update")
|
|
237
276
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
238
|
-
.requiredOption("--id <id>", "workspace id to update")
|
|
239
277
|
.option("--name <name>", "updated workspace name")
|
|
240
278
|
.addOption(new Option("--plan <plan>", "basic | pro").choices(["basic", "pro"]))
|
|
241
|
-
.action(async (options) => {
|
|
279
|
+
.action(async (workspaceId, options) => {
|
|
242
280
|
const payload = await resolveInput({ input: options.input }, { name: options.name, plan: options.plan });
|
|
243
281
|
const context = await resolveContext();
|
|
244
|
-
printJson(await updateWorkspace(context,
|
|
282
|
+
printJson(await updateWorkspace(context, workspaceId, payload));
|
|
245
283
|
});
|
|
246
284
|
const workspaceMember = workspace.command("member").description("manage workspace members");
|
|
247
285
|
workspaceMember
|
|
@@ -254,34 +292,35 @@ Examples:
|
|
|
254
292
|
workspaceMember
|
|
255
293
|
.command("upsert")
|
|
256
294
|
.description("add a workspace member or update the member role")
|
|
257
|
-
.
|
|
258
|
-
.
|
|
259
|
-
.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
"
|
|
263
|
-
|
|
264
|
-
|
|
295
|
+
.argument("<user-ids>", "user id(s); comma-separated for multiple")
|
|
296
|
+
.addOption(new Option("--role <role>", "owner | admin | member")
|
|
297
|
+
.choices(["owner", "admin", "member"])
|
|
298
|
+
.makeOptionMandatory())
|
|
299
|
+
.action(async (userIdsArg, options) => {
|
|
300
|
+
const userIds = parseStringArrayInput(userIdsArg, "<user-ids>") ?? [];
|
|
301
|
+
if (userIds.length === 0) {
|
|
302
|
+
throw new CliError({
|
|
303
|
+
code: "INVALID_INPUT",
|
|
304
|
+
message: "At least one user id is required."
|
|
305
|
+
});
|
|
306
|
+
}
|
|
265
307
|
const context = await resolveContext();
|
|
266
|
-
|
|
267
|
-
workspaceId: context.workspaceId,
|
|
268
|
-
userId: options.userId,
|
|
269
|
-
role: options.role
|
|
270
|
-
});
|
|
271
|
-
printJson(await upsertWorkspaceMember(context, payload));
|
|
308
|
+
printJson(await upsertWorkspaceMembers(context, userIds, options.role));
|
|
272
309
|
});
|
|
273
310
|
workspaceMember
|
|
274
311
|
.command("delete")
|
|
275
312
|
.description("remove a workspace member")
|
|
276
|
-
.
|
|
277
|
-
.
|
|
278
|
-
|
|
313
|
+
.argument("<user-ids>", "user id(s); comma-separated for multiple")
|
|
314
|
+
.action(async (userIdsArg) => {
|
|
315
|
+
const userIds = parseStringArrayInput(userIdsArg, "<user-ids>") ?? [];
|
|
316
|
+
if (userIds.length === 0) {
|
|
317
|
+
throw new CliError({
|
|
318
|
+
code: "INVALID_INPUT",
|
|
319
|
+
message: "At least one user id is required."
|
|
320
|
+
});
|
|
321
|
+
}
|
|
279
322
|
const context = await resolveContext();
|
|
280
|
-
|
|
281
|
-
workspaceId: context.workspaceId,
|
|
282
|
-
userId: options.userId
|
|
283
|
-
});
|
|
284
|
-
printJson(await deleteWorkspaceMember(context, payload));
|
|
323
|
+
printJson(await deleteWorkspaceMembers(context, userIds));
|
|
285
324
|
});
|
|
286
325
|
const project = program.command("project").description("manage workspace projects");
|
|
287
326
|
project
|
|
@@ -308,29 +347,25 @@ Examples:
|
|
|
308
347
|
project
|
|
309
348
|
.command("update")
|
|
310
349
|
.description("update a project you can access (PATCH — omitted fields are unchanged)")
|
|
350
|
+
.argument("<project-id>", "project id to update")
|
|
311
351
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
312
|
-
.requiredOption("--id <id>", "project id to update")
|
|
313
352
|
.option("--name <name>", "updated project name")
|
|
314
353
|
.option("--description <description>", "updated project description")
|
|
315
|
-
.action(async (options) => {
|
|
354
|
+
.action(async (projectId, options) => {
|
|
316
355
|
const payload = await resolveInput(options, {
|
|
317
356
|
name: options.name,
|
|
318
357
|
description: options.description
|
|
319
358
|
});
|
|
320
359
|
const context = await resolveContext();
|
|
321
|
-
printJson(await updateProject(context,
|
|
360
|
+
printJson(await updateProject(context, projectId, payload));
|
|
322
361
|
});
|
|
323
362
|
project
|
|
324
363
|
.command("delete")
|
|
325
364
|
.description("delete a project you can access in the selected workspace")
|
|
326
|
-
.
|
|
327
|
-
.
|
|
328
|
-
.action(async (options) => {
|
|
329
|
-
const payload = await resolveInput(options, {
|
|
330
|
-
id: options.id
|
|
331
|
-
});
|
|
365
|
+
.argument("<project-id>", "project id")
|
|
366
|
+
.action(async (projectId) => {
|
|
332
367
|
const context = await resolveContext();
|
|
333
|
-
printJson(await deleteProject(context,
|
|
368
|
+
printJson(await deleteProject(context, projectId));
|
|
334
369
|
});
|
|
335
370
|
const projectMember = project.command("member").description("manage project members");
|
|
336
371
|
projectMember
|
|
@@ -347,31 +382,39 @@ Examples:
|
|
|
347
382
|
});
|
|
348
383
|
projectMember
|
|
349
384
|
.command("add")
|
|
350
|
-
.description("add
|
|
351
|
-
.
|
|
352
|
-
.
|
|
353
|
-
.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
385
|
+
.description("add member(s) to a project")
|
|
386
|
+
.argument("<user-ids>", "user id(s); comma-separated for multiple")
|
|
387
|
+
.requiredOption("--project-id <projectId>", "project id")
|
|
388
|
+
.action(async (userIdsArg, options) => {
|
|
389
|
+
const userIds = parseStringArrayInput(userIdsArg, "<user-ids>") ?? [];
|
|
390
|
+
if (userIds.length === 0) {
|
|
391
|
+
throw new CliError({
|
|
392
|
+
code: "INVALID_INPUT",
|
|
393
|
+
message: "At least one user id is required."
|
|
394
|
+
});
|
|
395
|
+
}
|
|
359
396
|
const context = await resolveContext();
|
|
360
|
-
printJson(
|
|
397
|
+
printJson({
|
|
398
|
+
results: await addProjectMembers(context, options.projectId, userIds)
|
|
399
|
+
});
|
|
361
400
|
});
|
|
362
401
|
projectMember
|
|
363
402
|
.command("delete")
|
|
364
|
-
.description("remove
|
|
365
|
-
.
|
|
366
|
-
.
|
|
367
|
-
.
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
403
|
+
.description("remove user(s) from a project")
|
|
404
|
+
.argument("<user-ids>", "user id(s); comma-separated for multiple")
|
|
405
|
+
.requiredOption("--project-id <projectId>", "project id")
|
|
406
|
+
.action(async (userIdsArg, options) => {
|
|
407
|
+
const userIds = parseStringArrayInput(userIdsArg, "<user-ids>") ?? [];
|
|
408
|
+
if (userIds.length === 0) {
|
|
409
|
+
throw new CliError({
|
|
410
|
+
code: "INVALID_INPUT",
|
|
411
|
+
message: "At least one user id is required."
|
|
412
|
+
});
|
|
413
|
+
}
|
|
373
414
|
const context = await resolveContext();
|
|
374
|
-
printJson(
|
|
415
|
+
printJson({
|
|
416
|
+
results: await deleteProjectMembers(context, options.projectId, userIds)
|
|
417
|
+
});
|
|
375
418
|
});
|
|
376
419
|
const track = program.command("track").description("manage project tracks (tasks and goals)");
|
|
377
420
|
track
|
|
@@ -381,9 +424,9 @@ Examples:
|
|
|
381
424
|
.addOption(new Option("--type <type>", "task | goal").choices(TRACK_TYPES))
|
|
382
425
|
.option("--title <title>", "title")
|
|
383
426
|
.option("--content <content>", "markdown content")
|
|
384
|
-
.option("--
|
|
385
|
-
.option("--
|
|
386
|
-
.option("--
|
|
427
|
+
.option("--personal", "keep private to the current user (mutually exclusive with --projects)")
|
|
428
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids (mutually exclusive with --personal)")
|
|
429
|
+
.option("--share-with <shareWith>", "JSON array or comma-separated list of user ids and/or emails (values containing '@' are emails)")
|
|
387
430
|
.option("--task <task>", 'task-specific fields as JSON object e.g. \'{"status":"todo","dueDate":"2025-12-31"}\'')
|
|
388
431
|
.option("--goal <goal>", 'goal-specific fields as JSON object e.g. \'{"status":"on_track","dueDate":"2025-12-31"}\'')
|
|
389
432
|
.action(async (options, command) => {
|
|
@@ -391,7 +434,8 @@ Examples:
|
|
|
391
434
|
type: options.type,
|
|
392
435
|
title: options.title,
|
|
393
436
|
content: options.content,
|
|
394
|
-
|
|
437
|
+
scope: buildScopeOption(command, options),
|
|
438
|
+
sharedWith: buildSharedWithOption(command, options),
|
|
395
439
|
task: parseJsonObjectOption(options.task, "--task"),
|
|
396
440
|
goal: parseJsonObjectOption(options.goal, "--goal")
|
|
397
441
|
});
|
|
@@ -409,49 +453,47 @@ Examples:
|
|
|
409
453
|
track
|
|
410
454
|
.command("update")
|
|
411
455
|
.description("update an existing project track (PATCH — omitted fields are unchanged)")
|
|
456
|
+
.argument("<id>", "track id to update")
|
|
412
457
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
413
|
-
.requiredOption("--id <id>", "track id to update")
|
|
414
458
|
.option("--title <title>", "updated title")
|
|
415
459
|
.option("--content <content>", "updated markdown content")
|
|
416
|
-
.option("--
|
|
417
|
-
.option("--
|
|
418
|
-
.option("--
|
|
460
|
+
.option("--personal", "set scope to personal (mutually exclusive with --projects)")
|
|
461
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids (mutually exclusive with --personal)")
|
|
462
|
+
.option("--share-with <shareWith>", "JSON array or comma-separated list of user ids and/or emails (values containing '@' are emails)")
|
|
419
463
|
.option("--task <task>", 'task-specific fields as partial JSON object e.g. \'{"status":"done"}\'')
|
|
420
464
|
.option("--goal <goal>", "goal-specific fields as partial JSON object e.g. '{\"progress\":50}'")
|
|
421
|
-
.action(async (options, command) => {
|
|
465
|
+
.action(async (id, options, command) => {
|
|
422
466
|
const payload = await resolveInput(options, {
|
|
423
467
|
title: options.title,
|
|
424
468
|
content: options.content,
|
|
425
|
-
|
|
469
|
+
scope: buildScopeOption(command, options),
|
|
470
|
+
sharedWith: buildSharedWithOption(command, options),
|
|
426
471
|
task: parseJsonObjectOption(options.task, "--task"),
|
|
427
472
|
goal: parseJsonObjectOption(options.goal, "--goal")
|
|
428
473
|
});
|
|
429
474
|
const context = await resolveContext();
|
|
430
|
-
printJson(await updateTrack(context,
|
|
475
|
+
printJson(await updateTrack(context, id, payload));
|
|
431
476
|
});
|
|
432
477
|
track.commands.at(-1)?.addHelpText("after", `
|
|
433
478
|
Notes:
|
|
434
479
|
Omitted fields keep their existing value.
|
|
435
480
|
|
|
436
481
|
Examples:
|
|
437
|
-
epismo track update
|
|
438
|
-
epismo track update
|
|
439
|
-
epismo track update
|
|
482
|
+
epismo track update <id> --title "Updated title"
|
|
483
|
+
epismo track update <id> --task '{"status":"done"}'
|
|
484
|
+
epismo track update <id> --goal '{"progress":75}'`);
|
|
440
485
|
track
|
|
441
486
|
.command("get")
|
|
442
487
|
.description("fetch one project track")
|
|
488
|
+
.argument("<id>", "track id")
|
|
443
489
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
444
|
-
.
|
|
445
|
-
.action(async (options) => {
|
|
446
|
-
const payload = await resolveInput(options, {
|
|
447
|
-
id: options.id
|
|
448
|
-
});
|
|
490
|
+
.action(async (id) => {
|
|
449
491
|
const context = await resolveContext();
|
|
450
|
-
printJson(await getTrack(context,
|
|
492
|
+
printJson(await getTrack(context, id));
|
|
451
493
|
});
|
|
452
494
|
track.commands.at(-1)?.addHelpText("after", `
|
|
453
495
|
Example:
|
|
454
|
-
epismo track get
|
|
496
|
+
epismo track get <id>`);
|
|
455
497
|
track
|
|
456
498
|
.command("search")
|
|
457
499
|
.description("search project tracks")
|
|
@@ -482,28 +524,25 @@ Examples:
|
|
|
482
524
|
track
|
|
483
525
|
.command("delete")
|
|
484
526
|
.description("delete one project track")
|
|
485
|
-
.
|
|
486
|
-
.
|
|
487
|
-
.action(async (options) => {
|
|
488
|
-
const payload = await resolveInput(options, {
|
|
489
|
-
id: options.id
|
|
490
|
-
});
|
|
527
|
+
.argument("<id>", "track id")
|
|
528
|
+
.action(async (id) => {
|
|
491
529
|
const context = await resolveContext();
|
|
492
|
-
printJson(await deleteTrack(context,
|
|
530
|
+
printJson(await deleteTrack(context, id));
|
|
493
531
|
});
|
|
494
532
|
track.commands.at(-1)?.addHelpText("after", `
|
|
495
533
|
Example:
|
|
496
|
-
epismo track delete
|
|
534
|
+
epismo track delete <id>`);
|
|
497
535
|
track
|
|
498
536
|
.command("apply")
|
|
499
537
|
.description("create, update, and delete multiple tracks in a single request")
|
|
500
538
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
501
|
-
.option("--
|
|
502
|
-
.option("--
|
|
503
|
-
.option("--
|
|
539
|
+
.option("--personal", "set scope to personal (mutually exclusive with --projects)")
|
|
540
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids (mutually exclusive with --personal)")
|
|
541
|
+
.option("--share-with <shareWith>", "JSON array or comma-separated list of user ids and/or emails (values containing '@' are emails)")
|
|
504
542
|
.action(async (options, command) => {
|
|
505
543
|
const payload = await resolveInput(options, {
|
|
506
|
-
|
|
544
|
+
scope: buildScopeOption(command, options),
|
|
545
|
+
sharedWith: buildSharedWithOption(command, options)
|
|
507
546
|
});
|
|
508
547
|
const context = await resolveContext();
|
|
509
548
|
printJson(await applyTracks(context, payload));
|
|
@@ -527,9 +566,9 @@ Examples:
|
|
|
527
566
|
.option("--content <content>", "markdown content")
|
|
528
567
|
.option("--category <category>", "pack category")
|
|
529
568
|
.addOption(new Option("--visibility <visibility>", "public | private").choices(PACK_VISIBILITIES))
|
|
530
|
-
.option("--
|
|
531
|
-
.option("--
|
|
532
|
-
.option("--
|
|
569
|
+
.option("--personal", "keep private to the current user (mutually exclusive with --projects)")
|
|
570
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids (mutually exclusive with --personal)")
|
|
571
|
+
.option("--share-with <shareWith>", "JSON array or comma-separated list of user ids and/or emails (values containing '@' are emails)")
|
|
533
572
|
.option("--steps <steps>", "workflow steps as JSON array (use --input @file.json for complex payloads)")
|
|
534
573
|
.option("--blocks <blocks>", "context blocks as JSON array (for type=context; use --input @file.json for complex payloads)")
|
|
535
574
|
.action(async (options, command) => {
|
|
@@ -539,7 +578,8 @@ Examples:
|
|
|
539
578
|
content: options.content,
|
|
540
579
|
category: options.category,
|
|
541
580
|
visibility: options.visibility,
|
|
542
|
-
|
|
581
|
+
scope: buildScopeOption(command, options),
|
|
582
|
+
sharedWith: buildSharedWithOption(command, options),
|
|
543
583
|
steps: parseJsonArrayOption(options.steps, "--steps"),
|
|
544
584
|
blocks: parseJsonArrayOption(options.blocks, "--blocks")
|
|
545
585
|
});
|
|
@@ -564,29 +604,30 @@ Examples:
|
|
|
564
604
|
epismo pack create --type context --title "My context" --blocks '[{"title":"Block 1","content":"..."}]'`);
|
|
565
605
|
pack.command("update")
|
|
566
606
|
.description("update an existing agent pack (PATCH semantics — omitted fields are unchanged)")
|
|
567
|
-
.
|
|
607
|
+
.argument("<reference>", "pack reference: id, alias, share URL, or hub URL")
|
|
568
608
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
569
609
|
.option("--title <title>", "updated title")
|
|
570
610
|
.option("--content <content>", "updated markdown content")
|
|
571
611
|
.option("--category <category>", "updated pack category")
|
|
572
612
|
.addOption(new Option("--visibility <visibility>", "public | private").choices(PACK_VISIBILITIES))
|
|
573
|
-
.option("--
|
|
574
|
-
.option("--
|
|
575
|
-
.option("--
|
|
613
|
+
.option("--personal", "set scope to personal (mutually exclusive with --projects)")
|
|
614
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids (mutually exclusive with --personal)")
|
|
615
|
+
.option("--share-with <shareWith>", "JSON array or comma-separated list of user ids and/or emails (values containing '@' are emails)")
|
|
576
616
|
.option("--steps <steps>", 'step operations as JSON array with op field: [{"op":"add","title":"..."},{"op":"update","id":"s001","content":"..."},{"op":"remove","id":"s002"}]')
|
|
577
617
|
.option("--blocks <blocks>", 'block operations as JSON array with op field: [{"op":"add","title":"..."},{"op":"update","id":"b001","content":"..."},{"op":"remove","id":"b002"}]')
|
|
578
|
-
.action(async (options, command) => {
|
|
618
|
+
.action(async (reference, options, command) => {
|
|
579
619
|
const payload = await resolveInput(options, {
|
|
580
620
|
title: options.title,
|
|
581
621
|
content: options.content,
|
|
582
622
|
category: options.category,
|
|
583
623
|
visibility: options.visibility,
|
|
584
|
-
|
|
624
|
+
scope: buildScopeOption(command, options),
|
|
625
|
+
sharedWith: buildSharedWithOption(command, options),
|
|
585
626
|
steps: parseJsonArrayOption(options.steps, "--steps"),
|
|
586
627
|
blocks: parseJsonArrayOption(options.blocks, "--blocks")
|
|
587
628
|
});
|
|
588
629
|
const context = await resolveContext();
|
|
589
|
-
printJson(await updatePack(context,
|
|
630
|
+
printJson(await updatePack(context, reference, payload));
|
|
590
631
|
});
|
|
591
632
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
592
633
|
Notes:
|
|
@@ -596,41 +637,41 @@ Notes:
|
|
|
596
637
|
To remove all items, send a remove op for each existing item ID.
|
|
597
638
|
|
|
598
639
|
Examples:
|
|
599
|
-
epismo pack update
|
|
600
|
-
epismo pack update
|
|
601
|
-
epismo pack update
|
|
602
|
-
epismo pack update
|
|
603
|
-
epismo pack update
|
|
604
|
-
epismo pack update
|
|
640
|
+
epismo pack update <id> --category ""
|
|
641
|
+
epismo pack update @myproject --visibility public
|
|
642
|
+
epismo pack update <id> --visibility public --category productivity
|
|
643
|
+
epismo pack update <id> --blocks '[{"op":"add","title":"New Block","content":"..."}]'
|
|
644
|
+
epismo pack update <id> --blocks '[{"op":"update","id":"b001","content":"updated..."}]'
|
|
645
|
+
epismo pack update <id> --blocks '[{"op":"remove","id":"b002"}]'
|
|
646
|
+
epismo pack update <id> --input @changes.json`);
|
|
605
647
|
pack.command("get")
|
|
606
648
|
.description("fetch one agent pack")
|
|
649
|
+
.argument("<reference>", "pack reference: id, alias, share URL, or hub URL")
|
|
607
650
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
608
|
-
.option("--id <id>", "pack id")
|
|
609
|
-
.addOption(new Option("--alias <alias>", "pack alias (`@alias` or `@handle/alias`)").conflicts("id"))
|
|
610
651
|
.option("--full", "include nested item content")
|
|
611
652
|
.option("--block-id <blockId>", "context block id to extract; comma-separated or repeatable (type=context only)", collectOption)
|
|
612
653
|
.option("--step-id <stepId>", "workflow step id to extract; comma-separated or repeatable (type=workflow only)", collectOption)
|
|
613
|
-
.action(async (options) => {
|
|
654
|
+
.action(async (reference, options) => {
|
|
614
655
|
const payload = await resolveInput(options, {
|
|
615
|
-
id: options.id,
|
|
616
|
-
alias: options.alias,
|
|
617
656
|
full: options.full ? true : undefined
|
|
618
657
|
});
|
|
619
658
|
const context = await resolveContext();
|
|
620
|
-
printJson(await getPack(context, payload, {
|
|
659
|
+
printJson(await getPack(context, reference, payload, {
|
|
621
660
|
blockIds: options.blockId,
|
|
622
661
|
stepIds: options.stepId
|
|
623
662
|
}));
|
|
624
663
|
});
|
|
625
664
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
626
665
|
Examples:
|
|
627
|
-
epismo pack get
|
|
628
|
-
epismo pack get
|
|
629
|
-
epismo pack get
|
|
630
|
-
epismo pack get
|
|
631
|
-
epismo pack get
|
|
632
|
-
epismo pack get
|
|
633
|
-
epismo pack get
|
|
666
|
+
epismo pack get <id>
|
|
667
|
+
epismo pack get @myproject
|
|
668
|
+
epismo pack get @handle/myproject
|
|
669
|
+
epismo pack get https://epismo.ai/share/<token>
|
|
670
|
+
epismo pack get https://epismo.ai/hub/workflows/<id>
|
|
671
|
+
epismo pack get <id> --full
|
|
672
|
+
epismo pack get <id> --block-id b001
|
|
673
|
+
epismo pack get <id> --block-id b001 --block-id b002
|
|
674
|
+
epismo pack get <id> --step-id s001,s002`);
|
|
634
675
|
pack.command("search")
|
|
635
676
|
.description("search agent packs")
|
|
636
677
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
@@ -659,13 +700,12 @@ Examples:
|
|
|
659
700
|
epismo pack search --type context --query "meeting notes"`);
|
|
660
701
|
pack.command("like")
|
|
661
702
|
.description("like or unlike an agent pack")
|
|
703
|
+
.argument("<reference>", "pack reference: id, alias, share URL, or hub URL")
|
|
662
704
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
663
|
-
.option("--id <id>", "pack id")
|
|
664
705
|
.option("--liked", "mark as liked")
|
|
665
706
|
.option("--no-liked", "remove like")
|
|
666
|
-
.action(async (options) => {
|
|
707
|
+
.action(async (reference, options) => {
|
|
667
708
|
const payload = await resolveInput(options, {
|
|
668
|
-
id: options.id,
|
|
669
709
|
liked: options.liked
|
|
670
710
|
});
|
|
671
711
|
if (typeof payload.liked !== "boolean") {
|
|
@@ -676,26 +716,25 @@ Examples:
|
|
|
676
716
|
});
|
|
677
717
|
}
|
|
678
718
|
const context = await resolveContext();
|
|
679
|
-
printJson(await likePack(context, payload));
|
|
719
|
+
printJson(await likePack(context, reference, payload));
|
|
680
720
|
});
|
|
681
721
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
682
722
|
Examples:
|
|
683
|
-
epismo pack like
|
|
684
|
-
epismo pack like
|
|
723
|
+
epismo pack like <id> --liked
|
|
724
|
+
epismo pack like @myproject --liked
|
|
725
|
+
epismo pack like <id> --no-liked`);
|
|
685
726
|
pack.command("delete")
|
|
686
727
|
.description("delete one agent pack and any of your aliases that point to it")
|
|
687
|
-
.
|
|
688
|
-
.
|
|
689
|
-
.action(async (options) => {
|
|
690
|
-
const payload = await resolveInput(options, {
|
|
691
|
-
id: options.id
|
|
692
|
-
});
|
|
728
|
+
.argument("<reference>", "pack reference: id, alias, share URL, or hub URL")
|
|
729
|
+
.action(async (reference) => {
|
|
693
730
|
const context = await resolveContext();
|
|
694
|
-
printJson(await deletePack(context,
|
|
731
|
+
printJson(await deletePack(context, reference));
|
|
695
732
|
});
|
|
696
733
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
697
734
|
Examples:
|
|
698
|
-
epismo pack delete
|
|
735
|
+
epismo pack delete <id> # also removes your aliases for that pack
|
|
736
|
+
epismo pack delete @myproject
|
|
737
|
+
epismo pack delete https://epismo.ai/share/<token>`);
|
|
699
738
|
const agent = program.command("agent").description("manage agent availability");
|
|
700
739
|
agent
|
|
701
740
|
.command("list")
|
|
@@ -769,39 +808,35 @@ Example:
|
|
|
769
808
|
alias
|
|
770
809
|
.command("upsert")
|
|
771
810
|
.description("create or update one alias")
|
|
811
|
+
.argument("<alias>", "alias name (`alias` or `@alias`; stored without `@`)")
|
|
772
812
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
773
813
|
.addOption(new Option("--type <type>", "workflow | context").choices(PACK_TYPES))
|
|
774
814
|
.option("--id <id>", "target pack id")
|
|
775
|
-
.
|
|
776
|
-
.action(async (options) => {
|
|
815
|
+
.action(async (aliasName, options) => {
|
|
777
816
|
const payload = await resolveInput(options, {
|
|
778
817
|
type: options.type,
|
|
779
818
|
id: options.id,
|
|
780
|
-
alias:
|
|
819
|
+
alias: aliasName
|
|
781
820
|
});
|
|
782
821
|
const context = await resolveContext();
|
|
783
822
|
printJson(await upsertAlias(context, payload));
|
|
784
823
|
});
|
|
785
824
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
786
825
|
Examples:
|
|
787
|
-
epismo alias upsert --type workflow --id <id>
|
|
788
|
-
epismo alias upsert --type context --id <id
|
|
826
|
+
epismo alias upsert @myproject --type workflow --id <id>
|
|
827
|
+
epismo alias upsert @mycontext --type context --id <id>`);
|
|
789
828
|
alias
|
|
790
829
|
.command("get")
|
|
791
830
|
.description("resolve one alias")
|
|
792
|
-
.
|
|
793
|
-
.
|
|
794
|
-
.action(async (options) => {
|
|
795
|
-
const payload = await resolveInput(options, {
|
|
796
|
-
alias: options.alias
|
|
797
|
-
});
|
|
831
|
+
.argument("<alias>", "alias reference (`@alias` or `@handle/alias`)")
|
|
832
|
+
.action(async (aliasRef) => {
|
|
798
833
|
const context = await resolveContext();
|
|
799
|
-
printJson(await getAlias(context,
|
|
834
|
+
printJson(await getAlias(context, { alias: aliasRef }));
|
|
800
835
|
});
|
|
801
836
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
802
837
|
Examples:
|
|
803
|
-
epismo alias get
|
|
804
|
-
epismo alias get
|
|
838
|
+
epismo alias get @myproject
|
|
839
|
+
epismo alias get @handle/myproject`);
|
|
805
840
|
alias
|
|
806
841
|
.command("list")
|
|
807
842
|
.description("list your aliases")
|
|
@@ -817,18 +852,14 @@ Example:
|
|
|
817
852
|
alias
|
|
818
853
|
.command("delete")
|
|
819
854
|
.description("delete one alias")
|
|
820
|
-
.
|
|
821
|
-
.
|
|
822
|
-
.action(async (options) => {
|
|
823
|
-
const payload = await resolveInput(options, {
|
|
824
|
-
alias: options.alias
|
|
825
|
-
});
|
|
855
|
+
.argument("<alias>", "alias name (`alias` or `@alias`; stored without `@`)")
|
|
856
|
+
.action(async (aliasName) => {
|
|
826
857
|
const context = await resolveContext();
|
|
827
|
-
printJson(await deleteAlias(context,
|
|
858
|
+
printJson(await deleteAlias(context, { alias: aliasName }));
|
|
828
859
|
});
|
|
829
860
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
830
861
|
Example:
|
|
831
|
-
epismo alias delete
|
|
862
|
+
epismo alias delete @myproject`);
|
|
832
863
|
const token = program.command("token").description("manage CLI tokens for CI/CD");
|
|
833
864
|
token
|
|
834
865
|
.command("create")
|