epismo 0.1.7 → 0.3.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 +101 -14
- package/dist/agents.js +40 -0
- package/dist/agents.js.map +1 -0
- package/dist/auth.js +2 -2
- package/dist/auth.js.map +1 -1
- package/dist/context.js +2 -2
- package/dist/context.js.map +1 -1
- package/dist/packs.js +9 -2
- package/dist/packs.js.map +1 -1
- package/dist/program.js +385 -85
- package/dist/program.js.map +1 -1
- package/dist/projects.js +66 -0
- package/dist/projects.js.map +1 -0
- package/dist/token.js +10 -0
- package/dist/token.js.map +1 -0
- package/dist/tracks.js +30 -16
- package/dist/tracks.js.map +1 -1
- package/dist/workspace.js +4 -6
- package/dist/workspace.js.map +1 -1
- package/dist/workspaces.js +54 -0
- package/dist/workspaces.js.map +1 -0
- package/package.json +1 -1
package/dist/program.js
CHANGED
|
@@ -3,18 +3,19 @@ import { clearWorkspace, getCurrentWorkspace, listAvailableWorkspaces, login, lo
|
|
|
3
3
|
import { resolveExecutionContext } from "./context.js";
|
|
4
4
|
import { mergeDefined, parseJsonArrayOption, parseJsonObjectOption, parseOptionalPositiveInteger, parseStringArrayInput, readJsonObjectInput } from "./input.js";
|
|
5
5
|
import { printJson, printWarning } from "./output.js";
|
|
6
|
-
import { deleteTrack, getTrack, searchTracks,
|
|
7
|
-
import { deletePack, getPack, likePack, searchPacks,
|
|
6
|
+
import { applyTracks, createTrack, deleteTrack, getTrack, searchTracks, updateTrack } from "./tracks.js";
|
|
7
|
+
import { createPack, deletePack, getPack, likePack, searchPacks, updatePack } from "./packs.js";
|
|
8
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
|
+
import { addAgents, listAgents, removeAgents } from "./agents.js";
|
|
12
|
+
import { createWorkspace, deleteWorkspaceMember, getWorkspaceCheckout, listWorkspaceMembers, updateWorkspace, upsertWorkspaceMember } from "./workspaces.js";
|
|
13
|
+
import { addProjectMember, createProject, deleteProject, deleteProjectMember, listProjectMembers, listProjects, updateProject } from "./projects.js";
|
|
14
|
+
import { createToken } from "./token.js";
|
|
11
15
|
const TRACK_TYPES = ["task", "goal"];
|
|
12
16
|
const PACK_TYPES = ["workflow", "context"];
|
|
13
17
|
const PACK_VISIBILITIES = ["public", "private"];
|
|
14
|
-
//
|
|
15
|
-
const WORKSPACE_ID_OPT = "--workspace-id <workspaceId>";
|
|
16
|
-
const WORKSPACE_ID_DESC = "workspace to use; resolved in order: CLI arg → saved default → personal space";
|
|
17
|
-
// #2: centralize warning codes so wording is consistent everywhere
|
|
18
|
+
// centralize warning codes so wording is consistent everywhere
|
|
18
19
|
const WARNING_ENV_TOKEN_WORKSPACE_IGNORED = "EPISMO_TOKEN_WORKSPACE_IGNORED";
|
|
19
20
|
async function resolveInput(options, overrides) {
|
|
20
21
|
const base = await readJsonObjectInput(options.input);
|
|
@@ -27,8 +28,8 @@ function getExplicitOptionOverride(command, optionName, value) {
|
|
|
27
28
|
}
|
|
28
29
|
return value;
|
|
29
30
|
}
|
|
30
|
-
async function resolveContext(
|
|
31
|
-
const context = await resolveExecutionContext(
|
|
31
|
+
async function resolveContext() {
|
|
32
|
+
const context = await resolveExecutionContext();
|
|
32
33
|
if (context.warning) {
|
|
33
34
|
printWarning({
|
|
34
35
|
warning: { code: WARNING_ENV_TOKEN_WORKSPACE_IGNORED, message: context.warning }
|
|
@@ -48,11 +49,12 @@ export function buildProgram(version) {
|
|
|
48
49
|
.exitOverride();
|
|
49
50
|
program.addHelpText("after", `
|
|
50
51
|
Workspace resolution:
|
|
51
|
-
|
|
52
|
-
1.
|
|
53
|
-
2.
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
All commands resolve workspace in this order:
|
|
53
|
+
1. Saved default (epismo workspace use)
|
|
54
|
+
2. Personal space (fallback)
|
|
55
|
+
When EPISMO_TOKEN is set, the saved default is skipped — the workspace is
|
|
56
|
+
resolved from the token itself. Use epismo token create --workspace-id to
|
|
57
|
+
issue a workspace-scoped token for CI/CD.
|
|
56
58
|
|
|
57
59
|
Examples:
|
|
58
60
|
epismo login
|
|
@@ -105,17 +107,17 @@ Examples:
|
|
|
105
107
|
program
|
|
106
108
|
.command("whoami")
|
|
107
109
|
.description("show the currently authenticated user")
|
|
108
|
-
.
|
|
109
|
-
|
|
110
|
-
const context = await resolveContext({ workspaceId: options.workspaceId });
|
|
110
|
+
.action(async () => {
|
|
111
|
+
const context = await resolveContext();
|
|
111
112
|
printJson(await whoami({ workspaceId: context.workspaceId, auth: context.auth }));
|
|
112
113
|
});
|
|
113
114
|
program.commands.at(-1)?.addHelpText("after", `
|
|
114
115
|
Examples:
|
|
115
116
|
epismo whoami
|
|
116
|
-
EPISMO_TOKEN=<access-token> epismo whoami
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
EPISMO_TOKEN=<access-token> epismo whoami`);
|
|
118
|
+
const workspace = program
|
|
119
|
+
.command("workspace")
|
|
120
|
+
.description("manage workspaces and the saved default workspace");
|
|
119
121
|
workspace
|
|
120
122
|
.command("list")
|
|
121
123
|
.description("list accessible workspaces")
|
|
@@ -153,53 +155,252 @@ Example:
|
|
|
153
155
|
workspace.commands.at(-1)?.addHelpText("after", `
|
|
154
156
|
Example:
|
|
155
157
|
epismo workspace clear`);
|
|
156
|
-
|
|
157
|
-
.command("
|
|
158
|
-
.description("
|
|
159
|
-
|
|
158
|
+
workspace
|
|
159
|
+
.command("create")
|
|
160
|
+
.description("create a new workspace")
|
|
161
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
162
|
+
.option("--name <name>", "workspace name")
|
|
163
|
+
.addOption(new Option("--plan <plan>", "basic | pro").choices(["basic", "pro"]))
|
|
164
|
+
.action(async (options) => {
|
|
165
|
+
const payload = await resolveInput({ input: options.input }, { name: options.name, plan: options.plan });
|
|
166
|
+
const context = await resolveContext();
|
|
167
|
+
const created = await createWorkspace(context, payload);
|
|
168
|
+
const workspaceId = created.workspace?.id;
|
|
169
|
+
if (workspaceId) {
|
|
170
|
+
const checkout = await getWorkspaceCheckout(context, workspaceId);
|
|
171
|
+
printJson({ ...created, ...checkout });
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
printJson(created);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
workspace.commands.at(-1)?.addHelpText("after", `
|
|
178
|
+
Examples:
|
|
179
|
+
epismo workspace create --name my-team --plan basic
|
|
180
|
+
epismo workspace create --input @workspace.json`);
|
|
181
|
+
workspace
|
|
182
|
+
.command("checkout")
|
|
183
|
+
.description("get the billing URL for a workspace (to complete or retry payment)")
|
|
184
|
+
.requiredOption("--id <id>", "workspace id")
|
|
185
|
+
.action(async (options) => {
|
|
186
|
+
const context = await resolveContext();
|
|
187
|
+
printJson(await getWorkspaceCheckout(context, options.id));
|
|
188
|
+
});
|
|
189
|
+
workspace.commands.at(-1)?.addHelpText("after", `
|
|
190
|
+
Examples:
|
|
191
|
+
epismo workspace checkout --id <workspace-id>`);
|
|
192
|
+
workspace
|
|
193
|
+
.command("update")
|
|
194
|
+
.description("update a workspace you own (PATCH — omitted fields are unchanged)")
|
|
195
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
196
|
+
.requiredOption("--id <id>", "workspace id to update")
|
|
197
|
+
.option("--name <name>", "updated workspace name")
|
|
198
|
+
.addOption(new Option("--plan <plan>", "basic | pro").choices(["basic", "pro"]))
|
|
199
|
+
.action(async (options) => {
|
|
200
|
+
const payload = await resolveInput({ input: options.input }, { name: options.name, plan: options.plan });
|
|
201
|
+
const context = await resolveContext();
|
|
202
|
+
printJson(await updateWorkspace(context, options.id, payload));
|
|
203
|
+
});
|
|
204
|
+
const workspaceMember = workspace.command("member").description("manage workspace members");
|
|
205
|
+
workspaceMember
|
|
206
|
+
.command("list")
|
|
207
|
+
.description("list members in a workspace")
|
|
208
|
+
.action(async () => {
|
|
209
|
+
const context = await resolveContext();
|
|
210
|
+
printJson(await listWorkspaceMembers(context, { workspaceId: context.workspaceId }));
|
|
211
|
+
});
|
|
212
|
+
workspaceMember
|
|
160
213
|
.command("upsert")
|
|
161
|
-
.description("
|
|
214
|
+
.description("add a workspace member or update the member role")
|
|
215
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
216
|
+
.option("--user-id <userId>", "user id")
|
|
217
|
+
.addOption(new Option("--role <role>", "owner | admin | member").choices([
|
|
218
|
+
"owner",
|
|
219
|
+
"admin",
|
|
220
|
+
"member"
|
|
221
|
+
]))
|
|
222
|
+
.action(async (options) => {
|
|
223
|
+
const context = await resolveContext();
|
|
224
|
+
const payload = await resolveInput({ input: options.input }, {
|
|
225
|
+
workspaceId: context.workspaceId,
|
|
226
|
+
userId: options.userId,
|
|
227
|
+
role: options.role
|
|
228
|
+
});
|
|
229
|
+
printJson(await upsertWorkspaceMember(context, payload));
|
|
230
|
+
});
|
|
231
|
+
workspaceMember
|
|
232
|
+
.command("delete")
|
|
233
|
+
.description("remove a workspace member")
|
|
234
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
235
|
+
.option("--user-id <userId>", "user id")
|
|
236
|
+
.action(async (options) => {
|
|
237
|
+
const context = await resolveContext();
|
|
238
|
+
const payload = await resolveInput({ input: options.input }, {
|
|
239
|
+
workspaceId: context.workspaceId,
|
|
240
|
+
userId: options.userId
|
|
241
|
+
});
|
|
242
|
+
printJson(await deleteWorkspaceMember(context, payload));
|
|
243
|
+
});
|
|
244
|
+
const project = program.command("project").description("manage workspace projects");
|
|
245
|
+
project
|
|
246
|
+
.command("list")
|
|
247
|
+
.description("list projects visible in the selected workspace")
|
|
248
|
+
.action(async () => {
|
|
249
|
+
const context = await resolveContext();
|
|
250
|
+
printJson(await listProjects(context));
|
|
251
|
+
});
|
|
252
|
+
project
|
|
253
|
+
.command("create")
|
|
254
|
+
.description("create a project in the selected workspace")
|
|
255
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
256
|
+
.option("--name <name>", "project name")
|
|
257
|
+
.option("--description <description>", "project description")
|
|
258
|
+
.action(async (options) => {
|
|
259
|
+
const payload = await resolveInput(options, {
|
|
260
|
+
name: options.name,
|
|
261
|
+
description: options.description
|
|
262
|
+
});
|
|
263
|
+
const context = await resolveContext();
|
|
264
|
+
printJson(await createProject(context, payload));
|
|
265
|
+
});
|
|
266
|
+
project
|
|
267
|
+
.command("update")
|
|
268
|
+
.description("update a project you can access (PATCH — omitted fields are unchanged)")
|
|
269
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
270
|
+
.requiredOption("--id <id>", "project id to update")
|
|
271
|
+
.option("--name <name>", "updated project name")
|
|
272
|
+
.option("--description <description>", "updated project description")
|
|
273
|
+
.action(async (options) => {
|
|
274
|
+
const payload = await resolveInput(options, {
|
|
275
|
+
name: options.name,
|
|
276
|
+
description: options.description
|
|
277
|
+
});
|
|
278
|
+
const context = await resolveContext();
|
|
279
|
+
printJson(await updateProject(context, options.id, payload));
|
|
280
|
+
});
|
|
281
|
+
project
|
|
282
|
+
.command("delete")
|
|
283
|
+
.description("delete a project you can access in the selected workspace")
|
|
284
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
285
|
+
.option("--id <id>", "project id")
|
|
286
|
+
.action(async (options) => {
|
|
287
|
+
const payload = await resolveInput(options, {
|
|
288
|
+
id: options.id
|
|
289
|
+
});
|
|
290
|
+
const context = await resolveContext();
|
|
291
|
+
printJson(await deleteProject(context, payload));
|
|
292
|
+
});
|
|
293
|
+
const projectMember = project.command("member").description("manage project members");
|
|
294
|
+
projectMember
|
|
295
|
+
.command("list")
|
|
296
|
+
.description("list members across one or more projects")
|
|
297
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
298
|
+
.option("--project-ids <projectIds>", "JSON array or comma-separated project ids")
|
|
299
|
+
.action(async (options) => {
|
|
300
|
+
const payload = await resolveInput(options, {
|
|
301
|
+
projectIds: parseStringArrayInput(options.projectIds, "--project-ids")
|
|
302
|
+
});
|
|
303
|
+
const context = await resolveContext();
|
|
304
|
+
printJson(await listProjectMembers(context, payload));
|
|
305
|
+
});
|
|
306
|
+
projectMember
|
|
307
|
+
.command("add")
|
|
308
|
+
.description("add a member to a project")
|
|
309
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
310
|
+
.option("--project-id <projectId>", "project id")
|
|
311
|
+
.option("--user-id <userId>", "user id")
|
|
312
|
+
.action(async (options) => {
|
|
313
|
+
const payload = await resolveInput(options, {
|
|
314
|
+
projectId: options.projectId,
|
|
315
|
+
userId: options.userId
|
|
316
|
+
});
|
|
317
|
+
const context = await resolveContext();
|
|
318
|
+
printJson(await addProjectMember(context, payload));
|
|
319
|
+
});
|
|
320
|
+
projectMember
|
|
321
|
+
.command("delete")
|
|
322
|
+
.description("remove a user from a project")
|
|
323
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
324
|
+
.option("--project-id <projectId>", "project id")
|
|
325
|
+
.option("--user-id <userId>", "user id")
|
|
326
|
+
.action(async (options) => {
|
|
327
|
+
const payload = await resolveInput(options, {
|
|
328
|
+
projectId: options.projectId,
|
|
329
|
+
userId: options.userId
|
|
330
|
+
});
|
|
331
|
+
const context = await resolveContext();
|
|
332
|
+
printJson(await deleteProjectMember(context, payload));
|
|
333
|
+
});
|
|
334
|
+
const track = program.command("track").description("manage project tracks (tasks and goals)");
|
|
335
|
+
track
|
|
336
|
+
.command("create")
|
|
337
|
+
.description("create a new project track (task or goal)")
|
|
162
338
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
163
339
|
.addOption(new Option("--type <type>", "task | goal").choices(TRACK_TYPES))
|
|
164
|
-
.option("--id <id>", "existing item id")
|
|
165
340
|
.option("--title <title>", "title")
|
|
166
341
|
.option("--content <content>", "markdown content")
|
|
167
342
|
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
168
343
|
.option("--task <task>", 'task-specific fields as JSON object e.g. \'{"status":"todo","dueDate":"2025-12-31"}\'')
|
|
169
344
|
.option("--goal <goal>", 'goal-specific fields as JSON object e.g. \'{"status":"on_track","dueDate":"2025-12-31"}\'')
|
|
170
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
171
345
|
.action(async (options) => {
|
|
172
346
|
const payload = await resolveInput(options, {
|
|
173
347
|
type: options.type,
|
|
174
|
-
id: options.id,
|
|
175
348
|
title: options.title,
|
|
176
349
|
content: options.content,
|
|
177
350
|
projects: parseStringArrayInput(options.projects, "--projects"),
|
|
178
351
|
task: parseJsonObjectOption(options.task, "--task"),
|
|
179
352
|
goal: parseJsonObjectOption(options.goal, "--goal")
|
|
180
353
|
});
|
|
181
|
-
const context = await resolveContext(
|
|
182
|
-
printJson(await
|
|
354
|
+
const context = await resolveContext();
|
|
355
|
+
printJson(await createTrack(context, payload));
|
|
183
356
|
});
|
|
184
357
|
track.commands.at(-1)?.addHelpText("after", `
|
|
185
358
|
Notes:
|
|
186
359
|
Use --task or --goal to pass type-specific fields.
|
|
187
360
|
|
|
188
361
|
Examples:
|
|
189
|
-
epismo track
|
|
190
|
-
epismo track
|
|
191
|
-
epismo track
|
|
362
|
+
epismo track create --type task --title "Fix bug" --content "Details..."
|
|
363
|
+
epismo track create --input @task.json
|
|
364
|
+
epismo track create --type goal --title "Launch" --goal '{"status":"on_track"}'`);
|
|
365
|
+
track
|
|
366
|
+
.command("update")
|
|
367
|
+
.description("update an existing project track (PATCH — omitted fields are unchanged)")
|
|
368
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
369
|
+
.requiredOption("--id <id>", "track id to update")
|
|
370
|
+
.option("--title <title>", "updated title")
|
|
371
|
+
.option("--content <content>", "updated markdown content")
|
|
372
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
373
|
+
.option("--task <task>", 'task-specific fields as partial JSON object e.g. \'{"status":"done"}\'')
|
|
374
|
+
.option("--goal <goal>", 'goal-specific fields as partial JSON object e.g. \'{"progress":50}\'')
|
|
375
|
+
.action(async (options) => {
|
|
376
|
+
const payload = await resolveInput(options, {
|
|
377
|
+
title: options.title,
|
|
378
|
+
content: options.content,
|
|
379
|
+
projects: parseStringArrayInput(options.projects, "--projects"),
|
|
380
|
+
task: parseJsonObjectOption(options.task, "--task"),
|
|
381
|
+
goal: parseJsonObjectOption(options.goal, "--goal")
|
|
382
|
+
});
|
|
383
|
+
const context = await resolveContext();
|
|
384
|
+
printJson(await updateTrack(context, options.id, payload));
|
|
385
|
+
});
|
|
386
|
+
track.commands.at(-1)?.addHelpText("after", `
|
|
387
|
+
Notes:
|
|
388
|
+
Omitted fields keep their existing value.
|
|
389
|
+
|
|
390
|
+
Examples:
|
|
391
|
+
epismo track update --id <id> --title "Updated title"
|
|
392
|
+
epismo track update --id <id> --task '{"status":"done"}'
|
|
393
|
+
epismo track update --id <id> --goal '{"progress":75}'`);
|
|
192
394
|
track
|
|
193
395
|
.command("get")
|
|
194
396
|
.description("fetch one project track")
|
|
195
397
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
196
398
|
.option("--id <id>", "item id")
|
|
197
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
198
399
|
.action(async (options) => {
|
|
199
400
|
const payload = await resolveInput(options, {
|
|
200
401
|
id: options.id
|
|
201
402
|
});
|
|
202
|
-
const context = await resolveContext(
|
|
403
|
+
const context = await resolveContext();
|
|
203
404
|
printJson(await getTrack(context, payload));
|
|
204
405
|
});
|
|
205
406
|
track.commands.at(-1)?.addHelpText("after", `
|
|
@@ -214,7 +415,6 @@ Example:
|
|
|
214
415
|
.option("--page <page>", "1-based page number")
|
|
215
416
|
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
216
417
|
.option("--filter <filter>", 'filter as JSON object; each value is an array of accepted values e.g. \'{"status":["todo","in_progress"]}\' (use --input @file.json for complex filters)')
|
|
217
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
218
418
|
.action(async (options, command) => {
|
|
219
419
|
const payload = await resolveInput(options, {
|
|
220
420
|
type: getExplicitOptionOverride(command, "type", options.type),
|
|
@@ -223,7 +423,7 @@ Example:
|
|
|
223
423
|
projects: getExplicitOptionOverride(command, "projects", parseStringArrayInput(options.projects, "--projects")),
|
|
224
424
|
filter: getExplicitOptionOverride(command, "filter", parseJsonObjectOption(options.filter, "--filter"))
|
|
225
425
|
});
|
|
226
|
-
const context = await resolveContext(
|
|
426
|
+
const context = await resolveContext();
|
|
227
427
|
printJson(await searchTracks(context, payload));
|
|
228
428
|
});
|
|
229
429
|
track.commands.at(-1)?.addHelpText("after", `
|
|
@@ -236,27 +436,43 @@ Examples:
|
|
|
236
436
|
.description("delete one project track")
|
|
237
437
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
238
438
|
.option("--id <id>", "item id")
|
|
239
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
240
439
|
.action(async (options) => {
|
|
241
440
|
const payload = await resolveInput(options, {
|
|
242
441
|
id: options.id
|
|
243
442
|
});
|
|
244
|
-
const context = await resolveContext(
|
|
443
|
+
const context = await resolveContext();
|
|
245
444
|
printJson(await deleteTrack(context, payload));
|
|
246
445
|
});
|
|
247
446
|
track.commands.at(-1)?.addHelpText("after", `
|
|
248
447
|
Example:
|
|
249
448
|
epismo track delete --id <id>`);
|
|
250
|
-
|
|
251
|
-
.command("
|
|
252
|
-
.
|
|
253
|
-
.
|
|
254
|
-
|
|
255
|
-
.
|
|
256
|
-
|
|
449
|
+
track
|
|
450
|
+
.command("apply")
|
|
451
|
+
.description("create, update, and delete multiple tracks in a single request")
|
|
452
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
453
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
454
|
+
.action(async (options) => {
|
|
455
|
+
const payload = await resolveInput(options, {
|
|
456
|
+
projects: parseStringArrayInput(options.projects, "--projects")
|
|
457
|
+
});
|
|
458
|
+
const context = await resolveContext();
|
|
459
|
+
printJson(await applyTracks(context, payload));
|
|
460
|
+
});
|
|
461
|
+
track.commands.at(-1)?.addHelpText("after", `
|
|
462
|
+
Notes:
|
|
463
|
+
updateDrafts: use a non-UUID string as id (e.g. "t001") to create a new track, or a UUID to update an existing one.
|
|
464
|
+
Labels in task.parentId, task.dependsOn, and task.goalId are resolved by the server, so you can wire
|
|
465
|
+
up dependencies between new entries in the same request.
|
|
466
|
+
deleteDrafts: provide UUIDs of tracks to delete.
|
|
467
|
+
|
|
468
|
+
Examples:
|
|
469
|
+
epismo track apply --input @batch.json
|
|
470
|
+
epismo track apply --input '{"updateDrafts":[{"id":"t001","title":"Task A","task":{"status":"todo"}},{"id":"t002","title":"Task B","task":{"status":"todo","dependsOn":["t001"]}}]}'`);
|
|
471
|
+
const pack = program.command("pack").description("manage agent packs (workflows and contexts)");
|
|
472
|
+
pack.command("create")
|
|
473
|
+
.description("create a new agent pack")
|
|
257
474
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
258
475
|
.addOption(new Option("--type <type>", "workflow | context").choices(PACK_TYPES))
|
|
259
|
-
.option("--id <id>", "existing pack id")
|
|
260
476
|
.option("--title <title>", "title")
|
|
261
477
|
.option("--content <content>", "markdown content")
|
|
262
478
|
.option("--category <category>", "pack category")
|
|
@@ -264,11 +480,9 @@ Example:
|
|
|
264
480
|
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
265
481
|
.option("--steps <steps>", "workflow steps as JSON array (use --input @file.json for complex payloads)")
|
|
266
482
|
.option("--blocks <blocks>", "context blocks as JSON array (for type=context; use --input @file.json for complex payloads)")
|
|
267
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
268
483
|
.action(async (options) => {
|
|
269
484
|
const payload = await resolveInput(options, {
|
|
270
485
|
type: options.type,
|
|
271
|
-
id: options.id,
|
|
272
486
|
title: options.title,
|
|
273
487
|
content: options.content,
|
|
274
488
|
category: options.category,
|
|
@@ -277,17 +491,54 @@ Example:
|
|
|
277
491
|
steps: parseJsonArrayOption(options.steps, "--steps"),
|
|
278
492
|
blocks: parseJsonArrayOption(options.blocks, "--blocks")
|
|
279
493
|
});
|
|
280
|
-
const context = await resolveContext(
|
|
281
|
-
printJson(await
|
|
494
|
+
const context = await resolveContext();
|
|
495
|
+
printJson(await createPack(context, payload));
|
|
282
496
|
});
|
|
283
497
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
284
498
|
Examples:
|
|
285
|
-
epismo pack
|
|
286
|
-
epismo pack
|
|
287
|
-
epismo pack
|
|
288
|
-
epismo pack
|
|
289
|
-
pack
|
|
290
|
-
.
|
|
499
|
+
epismo pack create --type workflow --title "My workflow" --input @workflow.json
|
|
500
|
+
epismo pack create --type workflow --title "My workflow" --steps '[{"title":"Step 1","content":"..."}]'
|
|
501
|
+
epismo pack create --type context --title "My context" --input @context.json
|
|
502
|
+
epismo pack create --type context --title "My context" --blocks '[{"title":"Block 1","content":"..."}]'`);
|
|
503
|
+
pack.command("update")
|
|
504
|
+
.description("update an existing agent pack (PATCH semantics — omitted fields are unchanged)")
|
|
505
|
+
.requiredOption("--id <id>", "pack id to update")
|
|
506
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
507
|
+
.option("--title <title>", "updated title")
|
|
508
|
+
.option("--content <content>", "updated markdown content")
|
|
509
|
+
.option("--category <category>", "updated pack category")
|
|
510
|
+
.addOption(new Option("--visibility <visibility>", "public | private").choices(PACK_VISIBILITIES))
|
|
511
|
+
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
512
|
+
.option("--steps <steps>", 'step operations as JSON array with op field: [{"op":"add","title":"..."},{"op":"update","id":"s001","content":"..."},{"op":"remove","id":"s002"}]')
|
|
513
|
+
.option("--blocks <blocks>", 'block operations as JSON array with op field: [{"op":"add","title":"..."},{"op":"update","id":"b001","content":"..."},{"op":"remove","id":"b002"}]')
|
|
514
|
+
.action(async (options) => {
|
|
515
|
+
const payload = await resolveInput(options, {
|
|
516
|
+
title: options.title,
|
|
517
|
+
content: options.content,
|
|
518
|
+
category: options.category,
|
|
519
|
+
visibility: options.visibility,
|
|
520
|
+
projects: parseStringArrayInput(options.projects, "--projects"),
|
|
521
|
+
steps: parseJsonArrayOption(options.steps, "--steps"),
|
|
522
|
+
blocks: parseJsonArrayOption(options.blocks, "--blocks")
|
|
523
|
+
});
|
|
524
|
+
const context = await resolveContext();
|
|
525
|
+
printJson(await updatePack(context, options.id, payload));
|
|
526
|
+
});
|
|
527
|
+
pack.commands.at(-1)?.addHelpText("after", `
|
|
528
|
+
Notes:
|
|
529
|
+
Omitted fields keep their existing value.
|
|
530
|
+
steps/blocks use operation objects with an "op" field (add | update | remove).
|
|
531
|
+
Omitting steps/blocks keeps them unchanged. Passing an empty array [] is a no-op.
|
|
532
|
+
To remove all items, send a remove op for each existing item ID.
|
|
533
|
+
|
|
534
|
+
Examples:
|
|
535
|
+
epismo pack update --id <id> --category ""
|
|
536
|
+
epismo pack update --id <id> --visibility public --category productivity
|
|
537
|
+
epismo pack update --id <id> --blocks '[{"op":"add","title":"New Block","content":"..."}]'
|
|
538
|
+
epismo pack update --id <id> --blocks '[{"op":"update","id":"b001","content":"updated..."}]'
|
|
539
|
+
epismo pack update --id <id> --blocks '[{"op":"remove","id":"b002"}]'
|
|
540
|
+
epismo pack update --id <id> --input @changes.json`);
|
|
541
|
+
pack.command("get")
|
|
291
542
|
.description("fetch one agent pack")
|
|
292
543
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
293
544
|
.option("--id <id>", "pack id")
|
|
@@ -295,14 +546,13 @@ Examples:
|
|
|
295
546
|
.option("--full", "include nested item content")
|
|
296
547
|
.option("--block-id <blockId>", "context block id to extract (type=context only)")
|
|
297
548
|
.option("--step-id <stepId>", "workflow step id to extract (type=workflow only)")
|
|
298
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
299
549
|
.action(async (options) => {
|
|
300
550
|
const payload = await resolveInput(options, {
|
|
301
551
|
id: options.id,
|
|
302
552
|
alias: options.alias,
|
|
303
553
|
full: options.full ? true : undefined
|
|
304
554
|
});
|
|
305
|
-
const context = await resolveContext(
|
|
555
|
+
const context = await resolveContext();
|
|
306
556
|
printJson(await getPack(context, payload, {
|
|
307
557
|
blockId: options.blockId,
|
|
308
558
|
stepId: options.stepId
|
|
@@ -316,8 +566,7 @@ Examples:
|
|
|
316
566
|
epismo pack get --id <id> --full
|
|
317
567
|
epismo pack get --id <id> --block-id b001
|
|
318
568
|
epismo pack get --id <id> --step-id s001`);
|
|
319
|
-
pack
|
|
320
|
-
.command("search")
|
|
569
|
+
pack.command("search")
|
|
321
570
|
.description("search agent packs")
|
|
322
571
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
323
572
|
.addOption(new Option("--type <type>", "workflow | context").choices(PACK_TYPES))
|
|
@@ -325,7 +574,6 @@ Examples:
|
|
|
325
574
|
.option("--page <page>", "1-based page number")
|
|
326
575
|
.option("--projects <projects>", "JSON array or comma-separated project ids")
|
|
327
576
|
.option("--filter <filter>", 'filter as JSON object; each value is an array of accepted values e.g. \'{"visibility":["public"]}\' (use --input @file.json for complex filters)')
|
|
328
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
329
577
|
.action(async (options, command) => {
|
|
330
578
|
const payload = await resolveInput(options, {
|
|
331
579
|
type: getExplicitOptionOverride(command, "type", options.type),
|
|
@@ -334,7 +582,7 @@ Examples:
|
|
|
334
582
|
projects: getExplicitOptionOverride(command, "projects", parseStringArrayInput(options.projects, "--projects")),
|
|
335
583
|
filter: getExplicitOptionOverride(command, "filter", parseJsonObjectOption(options.filter, "--filter"))
|
|
336
584
|
});
|
|
337
|
-
const context = await resolveContext(
|
|
585
|
+
const context = await resolveContext();
|
|
338
586
|
printJson(await searchPacks(context, payload));
|
|
339
587
|
});
|
|
340
588
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
@@ -342,14 +590,12 @@ Examples:
|
|
|
342
590
|
epismo pack search --type workflow --query "onboarding"
|
|
343
591
|
epismo pack search --type workflow --filter '{"visibility":["public"]}'
|
|
344
592
|
epismo pack search --type context --query "meeting notes"`);
|
|
345
|
-
pack
|
|
346
|
-
.command("like")
|
|
593
|
+
pack.command("like")
|
|
347
594
|
.description("like or unlike an agent pack")
|
|
348
595
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
349
596
|
.option("--id <id>", "pack id")
|
|
350
597
|
.option("--liked", "mark as liked")
|
|
351
598
|
.option("--no-liked", "remove like")
|
|
352
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
353
599
|
.action(async (options) => {
|
|
354
600
|
const payload = await resolveInput(options, {
|
|
355
601
|
id: options.id,
|
|
@@ -362,53 +608,91 @@ Examples:
|
|
|
362
608
|
hint: "Use --liked to add a like, or --no-liked to remove one."
|
|
363
609
|
});
|
|
364
610
|
}
|
|
365
|
-
const context = await resolveContext(
|
|
611
|
+
const context = await resolveContext();
|
|
366
612
|
printJson(await likePack(context, payload));
|
|
367
613
|
});
|
|
368
614
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
369
615
|
Examples:
|
|
370
616
|
epismo pack like --id <id> --liked
|
|
371
617
|
epismo pack like --id <id> --no-liked`);
|
|
372
|
-
pack
|
|
373
|
-
.command("delete")
|
|
618
|
+
pack.command("delete")
|
|
374
619
|
.description("delete one agent pack and any of your aliases that point to it")
|
|
375
620
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
376
621
|
.option("--id <id>", "pack id")
|
|
377
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
378
622
|
.action(async (options) => {
|
|
379
623
|
const payload = await resolveInput(options, {
|
|
380
624
|
id: options.id
|
|
381
625
|
});
|
|
382
|
-
const context = await resolveContext(
|
|
626
|
+
const context = await resolveContext();
|
|
383
627
|
printJson(await deletePack(context, payload));
|
|
384
628
|
});
|
|
385
629
|
pack.commands.at(-1)?.addHelpText("after", `
|
|
386
630
|
Examples:
|
|
387
631
|
epismo pack delete --id <id> # also removes your aliases for that pack`);
|
|
632
|
+
const agent = program.command("agent").description("manage agent availability");
|
|
633
|
+
agent
|
|
634
|
+
.command("list")
|
|
635
|
+
.description("list AI teammates and whether they appear in the assignee roster")
|
|
636
|
+
.action(async () => {
|
|
637
|
+
const context = await resolveContext();
|
|
638
|
+
printJson(await listAgents(context));
|
|
639
|
+
});
|
|
640
|
+
agent.commands.at(-1)?.addHelpText("after", `
|
|
641
|
+
Examples:
|
|
642
|
+
epismo agent list`);
|
|
643
|
+
agent
|
|
644
|
+
.command("add")
|
|
645
|
+
.description("add AI teammates to the assignee roster")
|
|
646
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
647
|
+
.option("--agent-ids <agentIds>", "JSON array or comma-separated agent ids")
|
|
648
|
+
.action(async (options) => {
|
|
649
|
+
const payload = await resolveInput(options, {
|
|
650
|
+
agentIds: parseStringArrayInput(options.agentIds, "--agent-ids")
|
|
651
|
+
});
|
|
652
|
+
const context = await resolveContext();
|
|
653
|
+
printJson(await addAgents(context, payload));
|
|
654
|
+
});
|
|
655
|
+
agent.commands.at(-1)?.addHelpText("after", `
|
|
656
|
+
Examples:
|
|
657
|
+
epismo agent add --agent-ids agent_a
|
|
658
|
+
epismo agent add --agent-ids '["agent_a","agent_b"]'`);
|
|
659
|
+
agent
|
|
660
|
+
.command("remove")
|
|
661
|
+
.description("remove AI teammates from the assignee roster")
|
|
662
|
+
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
663
|
+
.option("--agent-ids <agentIds>", "JSON array or comma-separated agent ids")
|
|
664
|
+
.action(async (options) => {
|
|
665
|
+
const payload = await resolveInput(options, {
|
|
666
|
+
agentIds: parseStringArrayInput(options.agentIds, "--agent-ids")
|
|
667
|
+
});
|
|
668
|
+
const context = await resolveContext();
|
|
669
|
+
printJson(await removeAgents(context, payload));
|
|
670
|
+
});
|
|
671
|
+
agent.commands.at(-1)?.addHelpText("after", `
|
|
672
|
+
Examples:
|
|
673
|
+
epismo agent remove --agent-ids agent_a
|
|
674
|
+
epismo agent remove --agent-ids '["agent_a","agent_b"]'`);
|
|
388
675
|
const credit = program.command("credit").description("view balance and purchase credits");
|
|
389
676
|
credit
|
|
390
677
|
.command("balance")
|
|
391
678
|
.description("show current credit balance")
|
|
392
|
-
.
|
|
393
|
-
|
|
394
|
-
const context = await resolveContext({ workspaceId: options.workspaceId });
|
|
679
|
+
.action(async () => {
|
|
680
|
+
const context = await resolveContext();
|
|
395
681
|
printJson(await creditBalance(context));
|
|
396
682
|
});
|
|
397
683
|
credit.commands.at(-1)?.addHelpText("after", `
|
|
398
684
|
Examples:
|
|
399
|
-
epismo credit balance
|
|
400
|
-
epismo credit balance --workspace-id <workspace-id>`);
|
|
685
|
+
epismo credit balance`);
|
|
401
686
|
credit
|
|
402
687
|
.command("checkout")
|
|
403
688
|
.description("start a credit purchase and get a checkout URL")
|
|
404
689
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
405
690
|
.option("--allocations <allocations>", 'JSON array of { userId, quantity } e.g. \'[{"userId":"u_1","quantity":10}]\'')
|
|
406
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
407
691
|
.action(async (options) => {
|
|
408
692
|
const payload = await resolveInput(options, {
|
|
409
693
|
allocations: parseJsonArrayOption(options.allocations, "--allocations")
|
|
410
694
|
});
|
|
411
|
-
const context = await resolveContext(
|
|
695
|
+
const context = await resolveContext();
|
|
412
696
|
printJson(await creditCheckout(context, payload));
|
|
413
697
|
});
|
|
414
698
|
credit.commands.at(-1)?.addHelpText("after", `
|
|
@@ -422,14 +706,13 @@ Example:
|
|
|
422
706
|
.addOption(new Option("--type <type>", "workflow | context").choices(PACK_TYPES))
|
|
423
707
|
.option("--id <id>", "target pack id")
|
|
424
708
|
.option("--alias <alias>", "alias name")
|
|
425
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
426
709
|
.action(async (options) => {
|
|
427
710
|
const payload = await resolveInput(options, {
|
|
428
711
|
type: options.type,
|
|
429
712
|
id: options.id,
|
|
430
713
|
alias: options.alias
|
|
431
714
|
});
|
|
432
|
-
const context = await resolveContext(
|
|
715
|
+
const context = await resolveContext();
|
|
433
716
|
printJson(await upsertAlias(context, payload));
|
|
434
717
|
});
|
|
435
718
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
@@ -441,12 +724,11 @@ Examples:
|
|
|
441
724
|
.description("resolve one alias")
|
|
442
725
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
443
726
|
.option("--alias <alias>", "alias reference (`alias` or `@handle/alias`)")
|
|
444
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
445
727
|
.action(async (options) => {
|
|
446
728
|
const payload = await resolveInput(options, {
|
|
447
729
|
alias: options.alias
|
|
448
730
|
});
|
|
449
|
-
const context = await resolveContext(
|
|
731
|
+
const context = await resolveContext();
|
|
450
732
|
printJson(await getAlias(context, payload));
|
|
451
733
|
});
|
|
452
734
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
@@ -457,9 +739,8 @@ Examples:
|
|
|
457
739
|
.command("list")
|
|
458
740
|
.description("list your aliases")
|
|
459
741
|
.addOption(new Option("--type <type>", "workflow | context").choices(PACK_TYPES))
|
|
460
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
461
742
|
.action(async (options) => {
|
|
462
|
-
const context = await resolveContext(
|
|
743
|
+
const context = await resolveContext();
|
|
463
744
|
printJson(await listAliases(context, { type: options.type }));
|
|
464
745
|
});
|
|
465
746
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
@@ -471,17 +752,36 @@ Example:
|
|
|
471
752
|
.description("delete one alias")
|
|
472
753
|
.option("--input <input>", "JSON object, @file, or - for stdin")
|
|
473
754
|
.option("--alias <alias>", "alias name")
|
|
474
|
-
.option(WORKSPACE_ID_OPT, WORKSPACE_ID_DESC)
|
|
475
755
|
.action(async (options) => {
|
|
476
756
|
const payload = await resolveInput(options, {
|
|
477
757
|
alias: options.alias
|
|
478
758
|
});
|
|
479
|
-
const context = await resolveContext(
|
|
759
|
+
const context = await resolveContext();
|
|
480
760
|
printJson(await deleteAlias(context, payload));
|
|
481
761
|
});
|
|
482
762
|
alias.commands.at(-1)?.addHelpText("after", `
|
|
483
763
|
Example:
|
|
484
764
|
epismo alias delete --alias myproject`);
|
|
765
|
+
const token = program.command("token").description("manage CLI tokens for CI/CD");
|
|
766
|
+
token
|
|
767
|
+
.command("create")
|
|
768
|
+
.description("issue a workspace-scoped CLI token for use in CI/CD pipelines")
|
|
769
|
+
.option("--workspace-id <workspaceId>", "workspace to scope the token to (omit for personal space)")
|
|
770
|
+
.action(async (options) => {
|
|
771
|
+
const context = await resolveContext();
|
|
772
|
+
printJson(await createToken(context, options.workspaceId ?? context.workspaceId));
|
|
773
|
+
});
|
|
774
|
+
token.commands.at(-1)?.addHelpText("after", `
|
|
775
|
+
Notes:
|
|
776
|
+
The issued token has the same scopes as a normal CLI token (read, write, offline_access)
|
|
777
|
+
but carries the workspace ID embedded. Use it via the EPISMO_TOKEN environment variable
|
|
778
|
+
in CI/CD so no --workspace-id flag is needed at runtime.
|
|
779
|
+
If --workspace-id is omitted, the saved default workspace is used (epismo workspace use),
|
|
780
|
+
falling back to personal space when no default is set.
|
|
781
|
+
|
|
782
|
+
Examples:
|
|
783
|
+
epismo token create --workspace-id <workspace-id>
|
|
784
|
+
epismo token create # uses saved default workspace, or personal space if none`);
|
|
485
785
|
return program;
|
|
486
786
|
}
|
|
487
787
|
//# sourceMappingURL=program.js.map
|