@wspc/cli 0.1.16 → 0.1.18
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/cli.js +234 -109
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/spec/openapi.json +40 -12
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command86 } from "commander";
|
|
5
5
|
import { realpathSync } from "fs";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
|
|
@@ -1215,6 +1215,15 @@ var todoTypeList = (options) => (options.client ?? client).get({
|
|
|
1215
1215
|
url: "/todo/types",
|
|
1216
1216
|
...options
|
|
1217
1217
|
});
|
|
1218
|
+
var todoTypeCreate = (options) => (options?.client ?? client).post({
|
|
1219
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1220
|
+
url: "/todo/types",
|
|
1221
|
+
...options,
|
|
1222
|
+
headers: {
|
|
1223
|
+
"Content-Type": "application/json",
|
|
1224
|
+
...options?.headers
|
|
1225
|
+
}
|
|
1226
|
+
});
|
|
1218
1227
|
var todoCommentDelete = (options) => (options.client ?? client).delete({
|
|
1219
1228
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1220
1229
|
url: "/todo/comments/{id}",
|
|
@@ -1271,6 +1280,20 @@ var todoUpdate = (options) => (options.client ?? client).patch({
|
|
|
1271
1280
|
...options.headers
|
|
1272
1281
|
}
|
|
1273
1282
|
});
|
|
1283
|
+
var todoTypeDelete = (options) => (options.client ?? client).delete({
|
|
1284
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1285
|
+
url: "/todo/types/{id}",
|
|
1286
|
+
...options
|
|
1287
|
+
});
|
|
1288
|
+
var todoTypeUpdate = (options) => (options.client ?? client).patch({
|
|
1289
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1290
|
+
url: "/todo/types/{id}",
|
|
1291
|
+
...options,
|
|
1292
|
+
headers: {
|
|
1293
|
+
"Content-Type": "application/json",
|
|
1294
|
+
...options.headers
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1274
1297
|
var todoRestore = (options) => (options.client ?? client).post({
|
|
1275
1298
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1276
1299
|
url: "/todo/items/{id}/restore",
|
|
@@ -1280,6 +1303,11 @@ var todoRestore = (options) => (options.client ?? client).post({
|
|
|
1280
1303
|
...options.headers
|
|
1281
1304
|
}
|
|
1282
1305
|
});
|
|
1306
|
+
var todoTypeRestore = (options) => (options.client ?? client).post({
|
|
1307
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1308
|
+
url: "/todo/types/{id}/restore",
|
|
1309
|
+
...options
|
|
1310
|
+
});
|
|
1283
1311
|
|
|
1284
1312
|
// src/handwritten/config/index.ts
|
|
1285
1313
|
import { promises as fs } from "fs";
|
|
@@ -1529,9 +1557,9 @@ function createConsistencyFetch(opts) {
|
|
|
1529
1557
|
}
|
|
1530
1558
|
|
|
1531
1559
|
// src/version.ts
|
|
1532
|
-
var VERSION = "0.1.
|
|
1533
|
-
var SPEC_SHA = "
|
|
1534
|
-
var SPEC_FETCHED_AT = "2026-07-
|
|
1560
|
+
var VERSION = "0.1.18";
|
|
1561
|
+
var SPEC_SHA = "c11a618e";
|
|
1562
|
+
var SPEC_FETCHED_AT = "2026-07-13T08:36:32.305Z";
|
|
1535
1563
|
var API_BASE = "https://api.wspc.ai";
|
|
1536
1564
|
|
|
1537
1565
|
// src/index.ts
|
|
@@ -2241,7 +2269,7 @@ function formatCell(value, fmt, colorMap, opts) {
|
|
|
2241
2269
|
}
|
|
2242
2270
|
|
|
2243
2271
|
// src/generated/cli/invite/accept.ts
|
|
2244
|
-
var inviteAcceptCommand = new Command("accept").description("Accept an invite and switch into the inviting organization").argument("<id>", "id").action(async (id, opts) => {
|
|
2272
|
+
var inviteAcceptCommand = new Command("accept").description("Accept an invite and switch into the inviting organization").addHelpText("after", "\nSwitches the caller's org to the invite's org and records the previous org. The caller loses access to data scoped to their previous org.\n\nExamples:\n $ wspc invite accept inv_...\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2245
2273
|
const client2 = await loadSdkClient();
|
|
2246
2274
|
const result = await inviteAccept({
|
|
2247
2275
|
client: client2._rawClient,
|
|
@@ -2262,7 +2290,7 @@ var inviteAcceptCommand = new Command("accept").description("Accept an invite an
|
|
|
2262
2290
|
|
|
2263
2291
|
// src/generated/cli/keys/create.ts
|
|
2264
2292
|
import { Command as Command2 } from "commander";
|
|
2265
|
-
var keyCreateCommand = new Command2("create").description("Create a new API key (full value returned once)").option("--label <value>", "Human-readable label for the new key (1\u201360 chars after trimming). Pick something that identifies where the key will live \u2014 agent name, machine, or environment \u2014 so you can recognise it later in `wspc keys list`.").action(async (opts) => {
|
|
2293
|
+
var keyCreateCommand = new Command2("create").description("Create a new API key (full value returned once)").addHelpText("after", '\n### Overview\nCreates and provisions a new long-lived API key for the authenticated user. The complete plaintext API key value (`api_key`) is returned **only once** in this endpoint\'s response and cannot be retrieved again.\n\n### When to Use\n- Use this endpoint when a user requests a new API key (e.g., `wspc keys create --label "My Agent"`) to isolate access for specific environments, applications, or developers.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **Key Limit**: A user is limited to a maximum of 25 active API keys. Requesting a new key beyond this limit will result in a `KEY_LIMIT_EXCEEDED` error.\n- **Label Validation**: The `label` parameter must be between 1 and 60 characters after trimming whitespace. Failing to provide a valid label results in an `INVALID_LABEL` error.\n\n### Troubleshooting\n- **401 Unauthorized**: The Bearer token is missing or invalid.\n- **400 Bad Request**: The `label` parameter is empty, too long, or missing.\n- **400 Bad Request (Limit Exceeded)**: The user has hit the maximum limit of 25 active keys. An existing active key must be revoked before creating a new one.\n').option("--label <value>", "Human-readable label for the new key (1\u201360 chars after trimming). Pick something that identifies where the key will live \u2014 agent name, machine, or environment \u2014 so you can recognise it later in `wspc keys list`.").action(async (opts) => {
|
|
2266
2294
|
const client2 = await loadSdkClient();
|
|
2267
2295
|
const result = await keyCreate({
|
|
2268
2296
|
client: client2._rawClient,
|
|
@@ -2283,7 +2311,7 @@ var keyCreateCommand = new Command2("create").description("Create a new API key
|
|
|
2283
2311
|
|
|
2284
2312
|
// src/generated/cli/keys/ls.ts
|
|
2285
2313
|
import { Command as Command3 } from "commander";
|
|
2286
|
-
var keyListCommand = new Command3("ls").description("List active API keys").action(async (opts) => {
|
|
2314
|
+
var keyListCommand = new Command3("ls").description("List active API keys").addHelpText("after", "\n### Overview\nReturns a list of all active (non-revoked) API keys belonging to the authenticated user. It also includes the `current_key_id` identifying the specific key used to authenticate the current request.\n\n### When to Use\n- Use this endpoint to view active API keys (e.g., when running `wspc keys list` or displaying API key management screens in user profiles).\n- Use the `current_key_id` to identify which key is making the current call, facilitating self-rotation or auditing.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Only active keys are returned; keys that have been revoked are filtered out and excluded from the response.\n- The full secret key is never returned; only the last 4 characters (`key_last4`) are provided for identification.\n\n### Troubleshooting\n- **401 Unauthorized**: The provided Bearer token is missing, expired, or invalid. Ensure you are passing a valid, active API key.\n").action(async (opts) => {
|
|
2287
2315
|
const client2 = await loadSdkClient();
|
|
2288
2316
|
const result = await keyList({
|
|
2289
2317
|
client: client2._rawClient
|
|
@@ -2301,7 +2329,7 @@ var keyListCommand = new Command3("ls").description("List active API keys").acti
|
|
|
2301
2329
|
|
|
2302
2330
|
// src/generated/cli/org/invite.ts
|
|
2303
2331
|
import { Command as Command4 } from "commander";
|
|
2304
|
-
var orgInviteCreateCommand = new Command4("invite").description("Invite an email to join the caller's organization").option("--email <value>", "Email address to invite into the caller's organization.").action(async (opts) => {
|
|
2332
|
+
var orgInviteCreateCommand = new Command4("invite").description("Invite an email to join the caller's organization").addHelpText("after", "\nCreates a pending invite for `email` and sends an invite email. Idempotent for an existing pending invite. The invitee accepts after signing in with the invited email.\n\nExamples:\n $ wspc org invite bob@example.com\n").option("--email <value>", "Email address to invite into the caller's organization.").action(async (opts) => {
|
|
2305
2333
|
const client2 = await loadSdkClient();
|
|
2306
2334
|
const result = await orgInviteCreate({
|
|
2307
2335
|
client: client2._rawClient,
|
|
@@ -2322,7 +2350,7 @@ var orgInviteCreateCommand = new Command4("invite").description("Invite an email
|
|
|
2322
2350
|
|
|
2323
2351
|
// src/generated/cli/org/invites.ts
|
|
2324
2352
|
import { Command as Command5 } from "commander";
|
|
2325
|
-
var orgInvitesListCommand = new Command5("invites").description("List invites issued by the caller's organization").action(async (opts) => {
|
|
2353
|
+
var orgInvitesListCommand = new Command5("invites").description("List invites issued by the caller's organization").addHelpText("after", "\nRetrieves a list of all active pending or expired organization invites issued by the caller's organization.\n").action(async (opts) => {
|
|
2326
2354
|
const client2 = await loadSdkClient();
|
|
2327
2355
|
const result = await orgInvitesList({
|
|
2328
2356
|
client: client2._rawClient
|
|
@@ -2340,7 +2368,7 @@ var orgInvitesListCommand = new Command5("invites").description("List invites is
|
|
|
2340
2368
|
|
|
2341
2369
|
// src/generated/cli/org/show.ts
|
|
2342
2370
|
import { Command as Command6 } from "commander";
|
|
2343
|
-
var orgGetCommand = new Command6("show").description("Get the authenticated user's organization").action(async (opts) => {
|
|
2371
|
+
var orgGetCommand = new Command6("show").description("Get the authenticated user's organization").addHelpText("after", "\n### Overview\nReturns the metadata of the organization owned by the authenticated user. In the current version, this represents the user's personal organization space containing all their projects and tokens.\n\n### When to Use\n- Use this endpoint to retrieve the organization ID and name for display or context setup (e.g., when running `wspc org show` or rendering user dashboards).\n- Use this to verify that the API token / credentials are linked to a valid organization.\n\n### Constraints\n- Requires a valid Bearer token (API Key or Session Token) in the `Authorization` header.\n- In the current API version (v1), every user is automatically provisioned a single personal organization. Selecting or switching organizations is not supported.\n\n### Troubleshooting\n- **401 Unauthorized**: The provided Bearer token is missing, expired, or invalid. Verify your `Authorization` header format (`Bearer <token>`).\n- **403 Forbidden**: The token does not have access to read organization metadata.\n- **404 Not Found**: The organization associated with this token could not be found or has been deactivated.\n\nExamples:\n $ wspc org show\n $ wspc org show --json\n").action(async (opts) => {
|
|
2344
2372
|
const client2 = await loadSdkClient();
|
|
2345
2373
|
const result = await orgGet({
|
|
2346
2374
|
client: client2._rawClient
|
|
@@ -2358,7 +2386,7 @@ var orgGetCommand = new Command6("show").description("Get the authenticated user
|
|
|
2358
2386
|
|
|
2359
2387
|
// src/generated/cli/org/rename.ts
|
|
2360
2388
|
import { Command as Command7 } from "commander";
|
|
2361
|
-
var orgUpdateCommand = new Command7("rename").description("Update the authenticated user's organization").option("--name <value>", "The new name for the organization. Cannot be empty or purely whitespace.").action(async (opts) => {
|
|
2389
|
+
var orgUpdateCommand = new Command7("rename").description("Update the authenticated user's organization").addHelpText("after", '\n### Overview\nUpdates the metadata (currently, the name) of the organization associated with the authenticated user.\n\n### Constraints\n- Requires a valid Bearer token.\n- The organization name cannot be empty or purely whitespace.\n- Maximum length is capped by `MAX_ORG_NAME_LEN`.\n\nExamples:\n $ wspc org rename "New Name"\n $ wspc org rename "New Name" --json\n').option("--name <value>", "The new name for the organization. Cannot be empty or purely whitespace.").action(async (opts) => {
|
|
2362
2390
|
const client2 = await loadSdkClient();
|
|
2363
2391
|
const result = await orgUpdate({
|
|
2364
2392
|
client: client2._rawClient,
|
|
@@ -2379,7 +2407,7 @@ var orgUpdateCommand = new Command7("rename").description("Update the authentica
|
|
|
2379
2407
|
|
|
2380
2408
|
// src/generated/cli/invite/show.ts
|
|
2381
2409
|
import { Command as Command8 } from "commander";
|
|
2382
|
-
var inviteGetCommand = new Command8("show").description("Get a single invite addressed to the caller").argument("<id>", "id").action(async (id, opts) => {
|
|
2410
|
+
var inviteGetCommand = new Command8("show").description("Get a single invite addressed to the caller").addHelpText("after", "\nRetrieves the metadata of a specific organization invite addressed to the caller by its ID.\n\nExamples:\n $ wspc invite show inv_...\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2383
2411
|
const client2 = await loadSdkClient();
|
|
2384
2412
|
const result = await inviteGet({
|
|
2385
2413
|
client: client2._rawClient,
|
|
@@ -2400,7 +2428,7 @@ var inviteGetCommand = new Command8("show").description("Get a single invite add
|
|
|
2400
2428
|
|
|
2401
2429
|
// src/generated/cli/auth/me.ts
|
|
2402
2430
|
import { Command as Command9 } from "commander";
|
|
2403
|
-
var authMeCommand = new Command9("me").description("Fetch the user identified by the bearer token").action(async (opts) => {
|
|
2431
|
+
var authMeCommand = new Command9("me").description("Fetch the user identified by the bearer token").addHelpText("after", "\n### Overview\nRetrieves the stable identity profile (user ID, email, and optional display name) of the user associated with the active Bearer token. Works for both long-lived `wspc_*` API keys and OAuth access tokens.\n\n### When to Use\n- Use this endpoint (e.g., in `wspc verify` or `wspc whoami`) to confirm that the active environment's API key or OAuth access token remains valid.\n- Use it in UIs to display the logged-in user's profile details and retrieve the stable `user_id`.\n\n### Constraints\n- Requires a valid Bearer token (either a long-lived `wspc_*` API key or a temporary OAuth access token) in the `Authorization` header.\n- **Response Fields**: The `api_key_id` field is only returned if authenticated via a WSPC API key (prefixed with `wspc_`). OAuth access tokens will omit `api_key_id`. `display_name` is omitted if not configured.\n\n### Troubleshooting\n- **401 Unauthorized**: The Bearer token is missing, malformed, or has been revoked. Ensure the `Authorization` header matches the `Bearer <token>` format.\n\nExamples:\n $ wspc auth me\n $ wspc auth me --json\n").action(async (opts) => {
|
|
2404
2432
|
const client2 = await loadSdkClient();
|
|
2405
2433
|
const result = await authMe({
|
|
2406
2434
|
client: client2._rawClient
|
|
@@ -2418,7 +2446,7 @@ var authMeCommand = new Command9("me").description("Fetch the user identified by
|
|
|
2418
2446
|
|
|
2419
2447
|
// src/generated/cli/invites.ts
|
|
2420
2448
|
import { Command as Command10 } from "commander";
|
|
2421
|
-
var invitesListCommand = new Command10("invites").description("List invites addressed to the authenticated user's email").action(async (opts) => {
|
|
2449
|
+
var invitesListCommand = new Command10("invites").description("List invites addressed to the authenticated user's email").addHelpText("after", "\nRetrieves all pending or expired organization invites addressed to the caller's verified email address.\n").action(async (opts) => {
|
|
2422
2450
|
const client2 = await loadSdkClient();
|
|
2423
2451
|
const result = await invitesList({
|
|
2424
2452
|
client: client2._rawClient
|
|
@@ -2436,7 +2464,7 @@ var invitesListCommand = new Command10("invites").description("List invites addr
|
|
|
2436
2464
|
|
|
2437
2465
|
// src/generated/cli/org/members.ts
|
|
2438
2466
|
import { Command as Command11 } from "commander";
|
|
2439
|
-
var orgMembersListCommand = new Command11("members").description("List members of the authenticated user's organization").option("--cursor <value>", "Opaque pagination cursor. Pass the `next_cursor` returned by the previous page to fetch the next slice. Omit on the first call.").option("--limit <value>", "Maximum members to return. Clamped to [1, 100]. Defaults to 50.").action(async (opts) => {
|
|
2467
|
+
var orgMembersListCommand = new Command11("members").description("List members of the authenticated user's organization").addHelpText("after", "\n### Overview\nRetrieves a paginated list of all members belonging to the authenticated user's organization, including their basic profile information, emails, and roles.\n\n### When to Use\n- Use this endpoint to list members in command-line tools (e.g., `wspc org members ls`) or to display a team directory in a user dashboard.\n- Use this to paginate through large lists of organization members using cursor-based pagination.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- In the current version (v1), organizations are single-user only, meaning this endpoint will always return exactly one member (the caller).\n- **Pagination**: Supports cursor-based pagination. The `limit` query parameter must be a positive integer, defaulting to 50 and capped at a maximum of 100. Pass `cursor` from the previous response's `next_cursor` to fetch subsequent pages.\n\n### Troubleshooting\n- **401 Unauthorized**: The Bearer token is invalid or has expired.\n- **400 Bad Request**: The query parameters `limit` or `cursor` are malformed. Ensure `limit` is an integer between 1 and 100.\n- **404 Not Found**: The organization associated with this user was not found.\n").option("--cursor <value>", "Opaque pagination cursor. Pass the `next_cursor` returned by the previous page to fetch the next slice. Omit on the first call.").option("--limit <value>", "Maximum members to return. Clamped to [1, 100]. Defaults to 50.").action(async (opts) => {
|
|
2440
2468
|
const client2 = await loadSdkClient();
|
|
2441
2469
|
const result = await orgMembersList({
|
|
2442
2470
|
client: client2._rawClient,
|
|
@@ -2458,7 +2486,7 @@ var orgMembersListCommand = new Command11("members").description("List members o
|
|
|
2458
2486
|
|
|
2459
2487
|
// src/generated/cli/invite/reject.ts
|
|
2460
2488
|
import { Command as Command12 } from "commander";
|
|
2461
|
-
var inviteRejectCommand = new Command12("reject").description("Reject an invite").argument("<id>", "id").action(async (id, opts) => {
|
|
2489
|
+
var inviteRejectCommand = new Command12("reject").description("Reject an invite").addHelpText("after", "\nRejects an organization invite addressed to the caller. The invite will be marked as rejected.\n\nExamples:\n $ wspc invite reject inv_...\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2462
2490
|
const client2 = await loadSdkClient();
|
|
2463
2491
|
const result = await inviteReject({
|
|
2464
2492
|
client: client2._rawClient,
|
|
@@ -2479,7 +2507,7 @@ var inviteRejectCommand = new Command12("reject").description("Reject an invite"
|
|
|
2479
2507
|
|
|
2480
2508
|
// src/generated/cli/keys/rm.ts
|
|
2481
2509
|
import { Command as Command13 } from "commander";
|
|
2482
|
-
var keyRevokeCommand = new Command13("rm").description("Soft-revoke an API key").argument("<id>", "id").action(async (id, opts) => {
|
|
2510
|
+
var keyRevokeCommand = new Command13("rm").description("Soft-revoke an API key").addHelpText("after", "\n### Overview\nPermanently revokes an active API key by its unique ID. Once revoked, the key becomes immediately invalid and will be rejected by all services.\n\n### When to Use\n- Use this endpoint to permanently deactivate an API key (e.g., when running `wspc keys revoke <id>`) due to token rotation, key leakage, or decommissioning of a machine/service.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Revocation is permanent and cannot be undone.\n- A user can revoke any key they own, including the one they are currently using to make the call. If they revoke the current key, subsequent requests using that key will return `401 Unauthorized`.\n\n### Troubleshooting\n- **401 Unauthorized**: The active token is missing, expired, or invalid.\n- **404 Not Found**: The specified key ID does not exist, belongs to another user, or has already been revoked.\n- **400 Bad Request**: The `id` path parameter format is invalid. It must be in the format `key_<ULID>`.\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2483
2511
|
const client2 = await loadSdkClient();
|
|
2484
2512
|
const result = await keyRevoke({
|
|
2485
2513
|
client: client2._rawClient,
|
|
@@ -2500,7 +2528,7 @@ var keyRevokeCommand = new Command13("rm").description("Soft-revoke an API key")
|
|
|
2500
2528
|
|
|
2501
2529
|
// src/generated/cli/keys/edit.ts
|
|
2502
2530
|
import { Command as Command14 } from "commander";
|
|
2503
|
-
var keyUpdateCommand = new Command14("edit").description("Update an active API key's label").argument("<id>", "id").option("--label <value>", "Human-readable label for the key (1\u201360 chars after trimming).").action(async (id, opts) => {
|
|
2531
|
+
var keyUpdateCommand = new Command14("edit").description("Update an active API key's label").addHelpText("after", "\n### Overview\nUpdates the human-readable label of an active API key. Only active (non-revoked) keys owned by the authenticated user can be updated.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **Label Validation**: The `label` parameter must be between 1 and 60 characters after trimming whitespace. Failing to provide a valid label results in an `INVALID_LABEL` error.\n").argument("<id>", "id").option("--label <value>", "Human-readable label for the key (1\u201360 chars after trimming).").action(async (id, opts) => {
|
|
2504
2532
|
const client2 = await loadSdkClient();
|
|
2505
2533
|
const result = await keyUpdate({
|
|
2506
2534
|
client: client2._rawClient,
|
|
@@ -2524,7 +2552,7 @@ var keyUpdateCommand = new Command14("edit").description("Update an active API k
|
|
|
2524
2552
|
|
|
2525
2553
|
// src/generated/cli/org/invite/revoke.ts
|
|
2526
2554
|
import { Command as Command15 } from "commander";
|
|
2527
|
-
var orgInviteRevokeCommand = new Command15("revoke").description("Revoke a pending invite").argument("<id>", "id").action(async (id, opts) => {
|
|
2555
|
+
var orgInviteRevokeCommand = new Command15("revoke").description("Revoke a pending invite").addHelpText("after", "\nPermanently revokes a pending organization invite. The invitee will no longer be able to accept it.\n\nExamples:\n $ wspc org invite revoke inv_...\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2528
2556
|
const client2 = await loadSdkClient();
|
|
2529
2557
|
const result = await orgInviteRevoke({
|
|
2530
2558
|
client: client2._rawClient,
|
|
@@ -2630,7 +2658,7 @@ function parseAttendee(input) {
|
|
|
2630
2658
|
}
|
|
2631
2659
|
|
|
2632
2660
|
// src/generated/cli/event/add.ts
|
|
2633
|
-
var eventCreateCommand = new Command16("add").description("Schedule a calendar event").argument("<title>", "title").option("--description <value>", "Free-form notes about the event (agenda, dial-in instructions, etc.). Markdown formatted (CommonMark + GFM tables, strikethrough, task lists); stored verbatim. Invitation emails include the raw source \u2014 most email clients display it as plain text.").option("--start <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("--end <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("-l, --location <value>", "Free-text location \u2014 physical address, room, or short note. Separate from `url` (meeting link).").option("-u, --url <value>", "Optional meeting link (Zoom / Meet / etc.). Kept separate from `location` so calendar clients can render it as a join action.").option("--status <value>", "Lifecycle status. `confirmed`: the event will happen (default). `tentative`: organizer has not finalized; still visible in lists. `cancelled`: the event was called off but the record is kept so attendees can be notified and history audited; distinct from soft-delete (DELETE `/calendar/events/{id}`) which hides the event from default list responses.").option("--attendee <value>", "Up to 50 unique attendees (deduped case-insensitively by email). If non-empty, each attendee receives an invitation email with an `.ics` REQUEST attachment as a side effect of creation.", (val, memo) => {
|
|
2661
|
+
var eventCreateCommand = new Command16("add").description("Schedule a calendar event").addHelpText("after", '\n### Overview\nCreate a new calendar event owned by the authenticated user.\n\n### When to Use\nBook a meeting, lunch, all-day trip, or any time-bound item. Optionally provide `attendees` to automatically dispatch invitation emails containing an `.ics` REQUEST attachment to each participant as a side effect.\n\n### Constraints\n- **Format Integrity**: `start` and `end` must be of the exact same type (both ISO 8601 datetimes with offset, or both ISO date-only for all-day).\n- **Chronological Order**: `end` must be strictly after `start`.\n- **All-Day boundary**: All-day events use RFC 5545 exclusive end (e.g., a one-day event on June 1st is specified as `start=2026-06-01` and `end=2026-06-02`).\n- **Attendee Limit**: Up to 50 unique attendees are supported after case-insensitive email address deduplication.\n\n### Troubleshooting\n- Returns 400 `VALIDATION_ERROR` if `start` and `end` format mismatch, or if `end <= start`.\n- Returns 400 `ATTENDEE_LIMIT_EXCEEDED` if more than 50 unique attendees are supplied.\n- Invitation emails are processed and dispatched asynchronously via Cloudflare `waitUntil`; the analytics counter `event_created` is emitted automatically.\n\nExamples:\n $ wspc event add "Lunch with Alice" --start "tomorrow 12:30pm" --end "tomorrow 1:30pm"\n $ wspc event add "Team offsite" --all-day --start 2026-06-01 --end 2026-06-01\n').argument("<title>", "title").option("--description <value>", "Free-form notes about the event (agenda, dial-in instructions, etc.). Markdown formatted (CommonMark + GFM tables, strikethrough, task lists); stored verbatim. Invitation emails include the raw source \u2014 most email clients display it as plain text.").option("--start <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("--end <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("-l, --location <value>", "Free-text location \u2014 physical address, room, or short note. Separate from `url` (meeting link).").option("-u, --url <value>", "Optional meeting link (Zoom / Meet / etc.). Kept separate from `location` so calendar clients can render it as a join action.").option("--status <value>", "Lifecycle status. `confirmed`: the event will happen (default). `tentative`: organizer has not finalized; still visible in lists. `cancelled`: the event was called off but the record is kept so attendees can be notified and history audited; distinct from soft-delete (DELETE `/calendar/events/{id}`) which hides the event from default list responses.").option("--attendee <value>", "Up to 50 unique attendees (deduped case-insensitively by email). If non-empty, each attendee receives an invitation email with an `.ics` REQUEST attachment as a side effect of creation.", (val, memo) => {
|
|
2634
2662
|
memo.push(val);
|
|
2635
2663
|
return memo;
|
|
2636
2664
|
}, []).option("--idempotency-key <value>", "idempotency_key").option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (title, opts) => {
|
|
@@ -2681,7 +2709,7 @@ var eventCreateCommand = new Command16("add").description("Schedule a calendar e
|
|
|
2681
2709
|
|
|
2682
2710
|
// src/generated/cli/event/ls.ts
|
|
2683
2711
|
import { Command as Command17 } from "commander";
|
|
2684
|
-
var eventListCommand = new Command17("ls").description("List calendar events").option("--q <value>", "Optional full-text search across title, description, and location (case-insensitive substring).").option("--from <value>", "Inclusive lower bound on the event `start` (ISO datetime with offset, or ISO date-only). When ANY of `start_from`/`start_to`/`end_from`/`end_to` is provided, the implicit past filter is disabled.").option("--to <value>", "Inclusive upper bound on the event `start`.").option("--end-from <value>", "Inclusive lower bound on the event `end`.").option("--end-to <value>", "Inclusive upper bound on the event `end`.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").option("--limit <value>", "Maximum number of events to return. Clamped to `[1, 200]`. Default is server-defined.").option("--include-deleted", "include_deleted").option("--include-past <value>", "When omitted or `false`, events whose `end` is before now are hidden. Pass `true` to include them. Ignored when any of `start_from`/`start_to`/`end_from`/`end_to` is provided \u2014 explicit time bounds always win.").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (opts) => {
|
|
2712
|
+
var eventListCommand = new Command17("ls").description("List calendar events").addHelpText("after", '\n### Overview\nReturn the authenticated user\'s events, ordered by `start` ascending, with cursor pagination.\n\n### When to Use\nRender calendar list/grid views, search for specific terms using full-text search, query events within a specific time window, or retrieve historically past events.\n\n### Constraints\n- **Default Visibility**: By default, soft-deleted events and past events (events where `end` is before the current time) are automatically hidden.\n- **Time Bounds Override**: Supplying any explicit time bound query parameter (`start_from`, `start_to`, `end_from`, `end_to`) or passing `include_past=true` overrides and disables the implicit past filter.\n- **Search Scope**: `q` performs a case-insensitive substring search across `title`, `description`, and `location`.\n- **Pagination**: The `limit` query parameter is clamped to `[1, 200]`; cursor pagination is enabled via the opaque `cursor` parameter.\n\n### Troubleshooting\n- Returns 400 `VALIDATION_ERROR` if date query bounds are invalid (e.g. `start_from > start_to` or `end_from > end_to`).\n\nExamples:\n $ wspc event ls\n $ wspc event ls --from "today" --to "next week"\n').option("--q <value>", "Optional full-text search across title, description, and location (case-insensitive substring).").option("--from <value>", "Inclusive lower bound on the event `start` (ISO datetime with offset, or ISO date-only). When ANY of `start_from`/`start_to`/`end_from`/`end_to` is provided, the implicit past filter is disabled.").option("--to <value>", "Inclusive upper bound on the event `start`.").option("--end-from <value>", "Inclusive lower bound on the event `end`.").option("--end-to <value>", "Inclusive upper bound on the event `end`.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").option("--limit <value>", "Maximum number of events to return. Clamped to `[1, 200]`. Default is server-defined.").option("--include-deleted", "include_deleted").option("--include-past <value>", "When omitted or `false`, events whose `end` is before now are hidden. Pass `true` to include them. Ignored when any of `start_from`/`start_to`/`end_from`/`end_to` is provided \u2014 explicit time bounds always win.").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (opts) => {
|
|
2685
2713
|
const zone = resolveTimezone(opts.tz);
|
|
2686
2714
|
let fromValue;
|
|
2687
2715
|
if (opts.from !== void 0) {
|
|
@@ -2719,7 +2747,7 @@ var eventListCommand = new Command17("ls").description("List calendar events").o
|
|
|
2719
2747
|
|
|
2720
2748
|
// src/generated/cli/event/rm.ts
|
|
2721
2749
|
import { Command as Command18 } from "commander";
|
|
2722
|
-
var eventDeleteCommand = new Command18("rm").description("Soft-delete a calendar event").argument("<id>", "id").option("--expected-version <value>", "Optional optimistic lock. Omit to let the server use the current version; pass only to fail with 409 `VERSION_CONFLICT` if someone else has mutated the event since you last read.").action(async (id, opts) => {
|
|
2750
|
+
var eventDeleteCommand = new Command18("rm").description("Soft-delete a calendar event").addHelpText("after", "\n### Overview\nSoft-delete an existing calendar event, hiding it from default listings.\n\n### When to Use\nRemove an event entirely from the user's historical view and calendar client. If the meeting was cancelled but should remain in history (notifying participants of cancellation), use `PATCH /calendar/events/{id}` with `status: cancelled` instead.\n\n### Constraints\n- **Optimistic Locking**: Supports optional optimistic locking via `expected_version` in the request body.\n- **Side Effects**: When soft-deleting an event with attendees, all participants will asynchronously receive a cancellation email containing an `.ics` CANCEL attachment via Cloudflare `waitUntil`.\n- **Recovery**: The record is preserved in the database as a soft-deleted row and can be brought back using `POST /calendar/events/{id}/restore`.\n\n### Troubleshooting\n- Returns 404 `NOT_FOUND` if the event does not exist, or has already been soft-deleted.\n- Returns 409 `VERSION_CONFLICT` if `expected_version` does not match the database value.\n\nExamples:\n $ wspc event rm evt_xxx\n").argument("<id>", "id").option("--expected-version <value>", "Optional optimistic lock. Omit to let the server use the current version; pass only to fail with 409 `VERSION_CONFLICT` if someone else has mutated the event since you last read.").action(async (id, opts) => {
|
|
2723
2751
|
const client2 = await loadSdkClient();
|
|
2724
2752
|
const result = await eventDelete({
|
|
2725
2753
|
client: client2._rawClient,
|
|
@@ -2743,7 +2771,7 @@ var eventDeleteCommand = new Command18("rm").description("Soft-delete a calendar
|
|
|
2743
2771
|
|
|
2744
2772
|
// src/generated/cli/event/show.ts
|
|
2745
2773
|
import { Command as Command19 } from "commander";
|
|
2746
|
-
var eventGetCommand = new Command19("show").description("Get a calendar event by id").argument("<id>", "id").option("--include-deleted <value>", "When `true`, return the row even if soft-deleted. Default `false` (returns 404).").action(async (id, opts) => {
|
|
2774
|
+
var eventGetCommand = new Command19("show").description("Get a calendar event by id").addHelpText("after", "\n### Overview\nFetch a single calendar event by its unique ID, returning the complete record including all attendees.\n\n### When to Use\nDisplay a detailed view of an event, or read the latest database state (capturing `version`) prior to executing an optimistic-locked PATCH update.\n\n### Constraints\n- **Deleted Events**: Soft-deleted events return 404 `NOT_FOUND` by default. You must explicitly pass `include_deleted=true` in the query parameters to retrieve a soft-deleted row.\n- **ICS Format**: To download the RFC 5545 iCalendar text representation of this event, use `GET /calendar/events/{id}.ics` instead.\n\n### Troubleshooting\n- Returns 404 `NOT_FOUND` if the event does not exist, is soft-deleted (without `include_deleted=true`), or is owned by another user.\n\nExamples:\n $ wspc event show evt_xxx\n").argument("<id>", "id").option("--include-deleted <value>", "When `true`, return the row even if soft-deleted. Default `false` (returns 404).").action(async (id, opts) => {
|
|
2747
2775
|
const client2 = await loadSdkClient();
|
|
2748
2776
|
const result = await eventGet({
|
|
2749
2777
|
client: client2._rawClient,
|
|
@@ -2767,7 +2795,7 @@ var eventGetCommand = new Command19("show").description("Get a calendar event by
|
|
|
2767
2795
|
|
|
2768
2796
|
// src/generated/cli/event/set.ts
|
|
2769
2797
|
import { Command as Command20 } from "commander";
|
|
2770
|
-
var eventUpdateCommand = new Command20("set").description("Update a calendar event").argument("<id>", "id").option("--expected-version <value>", "Optional optimistic lock. Omit to let the server use the current version; pass only to fail the call if someone else has mutated the event since you last read. On mismatch the server returns 409 `VERSION_CONFLICT` and includes the current and sent versions in the message.").option("--title <value>", "New event title. Omit to leave unchanged.").option("--description <value>", "New description. Markdown formatted (CommonMark + GFM tables, strikethrough, task lists). Pass an empty string to clear; omit to leave unchanged.").option("--start <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("--end <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("-l, --location <value>", "New location. Pass an empty string to clear; omit to leave unchanged.").option("-u, --url <value>", "New meeting link. Pass an empty string to clear; omit to leave unchanged.").option("--status <value>", "Lifecycle status. `confirmed`: the event will happen (default). `tentative`: organizer has not finalized; still visible in lists. `cancelled`: the event was called off but the record is kept so attendees can be notified and history audited; distinct from soft-delete (DELETE `/calendar/events/{id}`) which hides the event from default list responses.").option("--attendee <value>", "If provided, REPLACES the attendee list (after case-insensitive email dedupe, up to 50). Added attendees receive a fresh invitation, kept attendees receive an update email, removed attendees receive a cancellation.", (val, memo) => {
|
|
2798
|
+
var eventUpdateCommand = new Command20("set").description("Update a calendar event").addHelpText("after", '\n### Overview\nPartially update fields of an existing calendar event. All properties in the request body are optional.\n\n### When to Use\nReschedule an event, update its location or notes, cancel the meeting (retaining the record but notifying participants), or replace/update the attendee list.\n\n### Constraints\n- **Optimistic Locking**: Pass `expected_version` to fail with `VERSION_CONFLICT` if another mutation occurred concurrently since you last read. Omit to let the server force the update.\n- **Field Clearing**: Pass an empty string `""` for `description`, `location`, or `url` to clear those fields in the database.\n- **Attendee replacement**: Providing the `attendees` property fully REPLACES the existing participant list. The server automatically diffs participants and asynchronously sends invitations (for newly added), updates (for kept), or cancellations (for removed) via Cloudflare `waitUntil`.\n- **Validation Rules**: Mismatched start/end formats or chronological order violations will fail the request.\n- **Attendee Limit**: A maximum of 50 unique attendees is allowed.\n\n### Troubleshooting\n- Returns 404 `NOT_FOUND` if the event does not exist or is soft-deleted.\n- Returns 409 `VERSION_CONFLICT` if `expected_version` is provided but stale.\n- Returns 400 `VALIDATION_ERROR` if `start` and `end` kinds do not match, or if `end <= start`.\n- Returns 400 `ATTENDEE_LIMIT_EXCEEDED` if unique attendees exceed 50.\n\nExamples:\n $ wspc event set evt_xxx --start "tomorrow 1pm" --end "tomorrow 2pm"\n $ wspc event set evt_xxx --status cancelled\n').argument("<id>", "id").option("--expected-version <value>", "Optional optimistic lock. Omit to let the server use the current version; pass only to fail the call if someone else has mutated the event since you last read. On mismatch the server returns 409 `VERSION_CONFLICT` and includes the current and sent versions in the message.").option("--title <value>", "New event title. Omit to leave unchanged.").option("--description <value>", "New description. Markdown formatted (CommonMark + GFM tables, strikethrough, task lists). Pass an empty string to clear; omit to leave unchanged.").option("--start <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("--end <value>", "Accepts ISO 8601 datetime with offset (e.g. `2026-06-01T12:30:00+08:00`) for timed events, or ISO date-only (e.g. `2026-06-01`) for all-day. The `wspc` CLI additionally accepts natural-language phrases (`tomorrow 12:30pm`, `next Monday 9am`) and resolves them to ISO before sending; the server itself only accepts ISO. All-day uses RFC 5545 exclusive end: a one-day event on 6/1 is `start=2026-06-01, end=2026-06-02`; both endpoints must be the same type.").option("-l, --location <value>", "New location. Pass an empty string to clear; omit to leave unchanged.").option("-u, --url <value>", "New meeting link. Pass an empty string to clear; omit to leave unchanged.").option("--status <value>", "Lifecycle status. `confirmed`: the event will happen (default). `tentative`: organizer has not finalized; still visible in lists. `cancelled`: the event was called off but the record is kept so attendees can be notified and history audited; distinct from soft-delete (DELETE `/calendar/events/{id}`) which hides the event from default list responses.").option("--attendee <value>", "If provided, REPLACES the attendee list (after case-insensitive email dedupe, up to 50). Added attendees receive a fresh invitation, kept attendees receive an update email, removed attendees receive a cancellation.", (val, memo) => {
|
|
2771
2799
|
memo.push(val);
|
|
2772
2800
|
return memo;
|
|
2773
2801
|
}, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (id, opts) => {
|
|
@@ -2821,7 +2849,7 @@ var eventUpdateCommand = new Command20("set").description("Update a calendar eve
|
|
|
2821
2849
|
|
|
2822
2850
|
// src/generated/cli/event/ics.ts
|
|
2823
2851
|
import { Command as Command21 } from "commander";
|
|
2824
|
-
var eventIcsDownloadCommand = new Command21("ics").description("Download event as `.ics`").argument("<id>", "id").action(async (id, opts) => {
|
|
2852
|
+
var eventIcsDownloadCommand = new Command21("ics").description("Download event as `.ics`").addHelpText("after", "\n### Overview\nReturn a single event rendered as an RFC 5545 `.ics` file suitable for import into major calendar clients.\n\n### When to Use\nExpose a 'Save to my calendar' link in email notifications, show a download button in a UI, or programmatically forward raw iCalendar text to third parties.\n\n### Constraints\n- **Router Match**: The path parameter `filename` must be exactly `<event_id>.ics`. The `.ics` suffix is strictly required for the router to match this endpoint ahead of the JSON detail endpoint.\n- **Response Payload**: The response is plain text containing the iCalendar specification, NOT JSON. The `Content-Type` is set to `text/calendar; charset=utf-8` with `Content-Disposition: inline; filename=\"<event_id>.ics\"`.\n- **Authentication**: Standard authentication is required (Bearer API key or OAuth access token), as this endpoint is secure.\n\n### Troubleshooting\n- Returns 404 `NOT_FOUND` if the event does not exist, is soft-deleted, or is owned by another user.\n\nExamples:\n $ wspc event ics evt_xxx > event.ics\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2825
2853
|
const client2 = await loadSdkClient();
|
|
2826
2854
|
const result = await eventIcsDownload({
|
|
2827
2855
|
client: client2._rawClient,
|
|
@@ -2842,7 +2870,7 @@ var eventIcsDownloadCommand = new Command21("ics").description("Download event a
|
|
|
2842
2870
|
|
|
2843
2871
|
// src/generated/cli/event/restore.ts
|
|
2844
2872
|
import { Command as Command22 } from "commander";
|
|
2845
|
-
var eventRestoreCommand = new Command22("restore").description("Restore a soft-deleted event").argument("<id>", "id").option("--expected-version <value>", "Optional optimistic lock. Omit to let the server use the current version; pass only to fail with 409 `VERSION_CONFLICT` if someone else has mutated the event since you last read.").action(async (id, opts) => {
|
|
2873
|
+
var eventRestoreCommand = new Command22("restore").description("Restore a soft-deleted event").addHelpText("after", "\n### Overview\nRestore a previously soft-deleted calendar event, making it active and visible in default list queries.\n\n### When to Use\nRecover an event that was accidentally soft-deleted.\n\n### Constraints\n- **Optimistic Locking**: Supports optional optimistic locking via `expected_version` in the request body.\n- **Side Effects**: When restoring an event with attendees, all participants will asynchronously receive a new invitation email containing an `.ics` REQUEST attachment via Cloudflare `waitUntil`.\n- **State Integrity**: You cannot restore a live (non-deleted) event. Restoring a live event is treated as an error.\n\n### Troubleshooting\n- Returns 404 `NOT_FOUND` if the event does not exist, or is NOT currently soft-deleted.\n- Returns 409 `VERSION_CONFLICT` if `expected_version` does not match the database value.\n").argument("<id>", "id").option("--expected-version <value>", "Optional optimistic lock. Omit to let the server use the current version; pass only to fail with 409 `VERSION_CONFLICT` if someone else has mutated the event since you last read.").action(async (id, opts) => {
|
|
2846
2874
|
const client2 = await loadSdkClient();
|
|
2847
2875
|
const result = await eventRestore({
|
|
2848
2876
|
client: client2._rawClient,
|
|
@@ -2866,7 +2894,7 @@ var eventRestoreCommand = new Command22("restore").description("Restore a soft-d
|
|
|
2866
2894
|
|
|
2867
2895
|
// src/generated/cli/drive/library/add.ts
|
|
2868
2896
|
import { Command as Command23 } from "commander";
|
|
2869
|
-
var driveLibraryCreateCommand = new Command23("add").description("Create a drive library").argument("<name>", "name").action(async (name, opts) => {
|
|
2897
|
+
var driveLibraryCreateCommand = new Command23("add").description("Create a drive library").addHelpText("after", "\nCreate an organization-scoped Drive / Library container.\n").argument("<name>", "name").action(async (name, opts) => {
|
|
2870
2898
|
const client2 = await loadSdkClient();
|
|
2871
2899
|
const result = await driveLibraryCreate({
|
|
2872
2900
|
client: client2._rawClient,
|
|
@@ -2887,7 +2915,7 @@ var driveLibraryCreateCommand = new Command23("add").description("Create a drive
|
|
|
2887
2915
|
|
|
2888
2916
|
// src/generated/cli/drive/library/ls.ts
|
|
2889
2917
|
import { Command as Command24 } from "commander";
|
|
2890
|
-
var driveLibraryListCommand = new Command24("ls").description("List drive libraries").option("--limit <value>", "limit").option("--cursor <value>", "cursor").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
|
|
2918
|
+
var driveLibraryListCommand = new Command24("ls").description("List drive libraries").addHelpText("after", "\nList libraries in the caller organization with cursor pagination.\n").option("--limit <value>", "limit").option("--cursor <value>", "cursor").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
|
|
2891
2919
|
const client2 = await loadSdkClient();
|
|
2892
2920
|
const result = await driveLibraryList({
|
|
2893
2921
|
client: client2._rawClient,
|
|
@@ -2910,7 +2938,7 @@ var driveLibraryListCommand = new Command24("ls").description("List drive librar
|
|
|
2910
2938
|
|
|
2911
2939
|
// src/generated/cli/drive/file/rm.ts
|
|
2912
2940
|
import { Command as Command25 } from "commander";
|
|
2913
|
-
var driveFileDeleteCommand = new Command25("rm").description("Delete a drive file").argument("<id>", "id").argument("<path>", "path").option("--expected-entry-version <value>", "expected_entry_version").action(async (id, path, opts) => {
|
|
2941
|
+
var driveFileDeleteCommand = new Command25("rm").description("Delete a drive file").addHelpText("after", "\nTombstone an active file using optimistic entry version locking.\n").argument("<id>", "id").argument("<path>", "path").option("--expected-entry-version <value>", "expected_entry_version").action(async (id, path, opts) => {
|
|
2914
2942
|
const client2 = await loadSdkClient();
|
|
2915
2943
|
const result = await driveFileDelete({
|
|
2916
2944
|
client: client2._rawClient,
|
|
@@ -2935,7 +2963,7 @@ var driveFileDeleteCommand = new Command25("rm").description("Delete a drive fil
|
|
|
2935
2963
|
|
|
2936
2964
|
// src/generated/cli/drive/library/rm.ts
|
|
2937
2965
|
import { Command as Command26 } from "commander";
|
|
2938
|
-
var driveLibraryDeleteCommand = new Command26("rm").description("Delete a drive library").argument("<id>", "id").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
|
|
2966
|
+
var driveLibraryDeleteCommand = new Command26("rm").description("Delete a drive library").addHelpText("after", "\nSoft-delete an empty library using optimistic version locking.\n").argument("<id>", "id").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
|
|
2939
2967
|
const client2 = await loadSdkClient();
|
|
2940
2968
|
const result = await driveLibraryDelete({
|
|
2941
2969
|
client: client2._rawClient,
|
|
@@ -2959,7 +2987,7 @@ var driveLibraryDeleteCommand = new Command26("rm").description("Delete a drive
|
|
|
2959
2987
|
|
|
2960
2988
|
// src/generated/cli/drive/library/show.ts
|
|
2961
2989
|
import { Command as Command27 } from "commander";
|
|
2962
|
-
var driveLibraryGetCommand = new Command27("show").description("Get a drive library").argument("<id>", "id").action(async (id, opts) => {
|
|
2990
|
+
var driveLibraryGetCommand = new Command27("show").description("Get a drive library").addHelpText("after", "\nFetch one active library by id. Cross-org and soft-deleted rows are hidden.\n").argument("<id>", "id").action(async (id, opts) => {
|
|
2963
2991
|
const client2 = await loadSdkClient();
|
|
2964
2992
|
const result = await driveLibraryGet({
|
|
2965
2993
|
client: client2._rawClient,
|
|
@@ -2980,7 +3008,7 @@ var driveLibraryGetCommand = new Command27("show").description("Get a drive libr
|
|
|
2980
3008
|
|
|
2981
3009
|
// src/generated/cli/drive/library/update.ts
|
|
2982
3010
|
import { Command as Command28 } from "commander";
|
|
2983
|
-
var driveLibraryUpdateCommand = new Command28("update").description("Update a drive library").argument("<id>", "id").option("--name <value>", "name").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
|
|
3011
|
+
var driveLibraryUpdateCommand = new Command28("update").description("Update a drive library").addHelpText("after", "\nRename a library using optimistic version locking.\n").argument("<id>", "id").option("--name <value>", "name").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
|
|
2984
3012
|
const client2 = await loadSdkClient();
|
|
2985
3013
|
const result = await driveLibraryUpdate({
|
|
2986
3014
|
client: client2._rawClient,
|
|
@@ -3005,7 +3033,7 @@ var driveLibraryUpdateCommand = new Command28("update").description("Update a dr
|
|
|
3005
3033
|
|
|
3006
3034
|
// src/generated/cli/drive/file/history.ts
|
|
3007
3035
|
import { Command as Command29 } from "commander";
|
|
3008
|
-
var driveFileHistoryCommand = new Command29("history").description("Get drive file version history").argument("<id>", "id").option("--path <value>", "path").action(async (id, opts) => {
|
|
3036
|
+
var driveFileHistoryCommand = new Command29("history").description("Get drive file version history").addHelpText("after", "\nList stored versions of a file, newest first.\n").argument("<id>", "id").option("--path <value>", "path").action(async (id, opts) => {
|
|
3009
3037
|
const client2 = await loadSdkClient();
|
|
3010
3038
|
const result = await driveFileHistory({
|
|
3011
3039
|
client: client2._rawClient,
|
|
@@ -3029,7 +3057,7 @@ var driveFileHistoryCommand = new Command29("history").description("Get drive fi
|
|
|
3029
3057
|
|
|
3030
3058
|
// src/generated/cli/drive/manifest/get.ts
|
|
3031
3059
|
import { Command as Command30 } from "commander";
|
|
3032
|
-
var driveManifestGetCommand = new Command30("get").description("Get a drive library manifest").argument("<id>", "id").option("--limit <value>", "limit").option("--cursor <value>", "cursor").option("--include-deleted <value>", "include_deleted").option("--path-prefix <value>", "path_prefix").option("--since-cursor <value>", "since_cursor").action(async (id, opts) => {
|
|
3060
|
+
var driveManifestGetCommand = new Command30("get").description("Get a drive library manifest").addHelpText("after", "\nList file entries for sync using path/id cursor pagination.\n").argument("<id>", "id").option("--limit <value>", "limit").option("--cursor <value>", "cursor").option("--include-deleted <value>", "include_deleted").option("--path-prefix <value>", "path_prefix").option("--since-cursor <value>", "since_cursor").action(async (id, opts) => {
|
|
3033
3061
|
const client2 = await loadSdkClient();
|
|
3034
3062
|
const result = await driveManifestGet({
|
|
3035
3063
|
client: client2._rawClient,
|
|
@@ -3057,7 +3085,7 @@ var driveManifestGetCommand = new Command30("get").description("Get a drive libr
|
|
|
3057
3085
|
|
|
3058
3086
|
// src/generated/cli/drive/file/restore.ts
|
|
3059
3087
|
import { Command as Command31 } from "commander";
|
|
3060
|
-
var driveFileRestoreCommand = new Command31("restore").description("Restore a drive file version").argument("<id>", "id").option("--path <value>", "path").option("--version-id <value>", "version_id").action(async (id, opts) => {
|
|
3088
|
+
var driveFileRestoreCommand = new Command31("restore").description("Restore a drive file version").addHelpText("after", "\nPromote a previous file version to be the current content.\n").argument("<id>", "id").option("--path <value>", "path").option("--version-id <value>", "version_id").action(async (id, opts) => {
|
|
3061
3089
|
const client2 = await loadSdkClient();
|
|
3062
3090
|
const result = await driveFileRestore({
|
|
3063
3091
|
client: client2._rawClient,
|
|
@@ -3082,7 +3110,7 @@ var driveFileRestoreCommand = new Command31("restore").description("Restore a dr
|
|
|
3082
3110
|
|
|
3083
3111
|
// src/generated/cli/drive/search.ts
|
|
3084
3112
|
import { Command as Command32 } from "commander";
|
|
3085
|
-
var driveSearchCommand = new Command32("search").description("Search drive library text").argument("<id>", "id").option("--query <value>", "query").option("--limit <value>", "limit").action(async (id, opts) => {
|
|
3113
|
+
var driveSearchCommand = new Command32("search").description("Search drive library text").addHelpText("after", "\nFull-text search over indexed text files in a library (FTS5).\n").argument("<id>", "id").option("--query <value>", "query").option("--limit <value>", "limit").action(async (id, opts) => {
|
|
3086
3114
|
const client2 = await loadSdkClient();
|
|
3087
3115
|
const result = await driveSearch({
|
|
3088
3116
|
client: client2._rawClient,
|
|
@@ -3107,7 +3135,7 @@ var driveSearchCommand = new Command32("search").description("Search drive libra
|
|
|
3107
3135
|
|
|
3108
3136
|
// src/generated/cli/alias/add.ts
|
|
3109
3137
|
import { Command as Command33 } from "commander";
|
|
3110
|
-
var emailAliasCreateCommand = new Command33("add").description("Create a receiving alias").argument("<email>", "email").action(async (email, opts) => {
|
|
3138
|
+
var emailAliasCreateCommand = new Command33("add").description("Create a receiving alias").addHelpText("after", "\n### Overview\nReserves and provisions a new passwordless/disposable receiving email alias address under the configured WSPC domain or a fully verified organization custom domain. All inbound emails received on this alias will be forwarded into the caller's inbox.\n\n### When to Use\n- Use this endpoint to spin up a fresh, dedicated email address (e.g., `alice-shop@wspc.app`) for specific websites, newsletters, or contexts to prevent spam or categorize incoming mail.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **Alias Formatting**: The local part must be between 5 and 32 characters, start with an alphanumeric character, and only contain letters, numbers, dots, underscores, and hyphens.\n- **Custom Domains**: If the address uses a non-platform host, that domain must be registered to the caller's organization and have `status = verified`, `sending_status = verified`, and `receiving_status = verified`.\n- **Limit Check**: Each user is allowed a maximum of 10 active email aliases. Soft-deleted aliases do not count against this quota limit.\n\n### Troubleshooting\n- **401 Unauthorized**: Bearer token is missing, invalid, or expired.\n- **400 Bad Request / INVALID_CHARSET / RESERVED**: The alias local part contains invalid characters, is too short/long, or matches a reserved keyword.\n- **400 Bad Request / ALIAS_DOMAIN_NOT_FOUND**: The custom domain is not registered to the caller's organization.\n- **400 Bad Request / UNVERIFIED_DOMAIN**: The custom domain exists but is not verified yet.\n- **400 Bad Request / ALIAS_DOMAIN_NOT_READY**: The custom domain exists but has not completed sending or receiving verification.\n- **409 Conflict / ALIAS_CONFLICT**: An alias with the exact requested email address already exists globally (whether active or soft-deleted by any user).\n- **429 Too Many Requests / ALIAS_LIMIT_EXCEEDED**: The user has reached the active alias cap limit of 10. A previously deleted alias must be cleaned up or wait for quota availability.\n").argument("<email>", "email").action(async (email, opts) => {
|
|
3111
3139
|
const client2 = await loadSdkClient();
|
|
3112
3140
|
const result = await emailAliasCreate({
|
|
3113
3141
|
client: client2._rawClient,
|
|
@@ -3128,7 +3156,7 @@ var emailAliasCreateCommand = new Command33("add").description("Create a receivi
|
|
|
3128
3156
|
|
|
3129
3157
|
// src/generated/cli/alias/ls.ts
|
|
3130
3158
|
import { Command as Command34 } from "commander";
|
|
3131
|
-
var emailAliasListCommand = new Command34("ls").description("List the caller's aliases").option("--include-deleted", "include_deleted").action(async (opts) => {
|
|
3159
|
+
var emailAliasListCommand = new Command34("ls").description("List the caller's aliases").addHelpText("after", "\n### Overview\nRetrieves a list of all email receiving aliases owned by the authenticated user.\n\n### When to Use\n- Use this endpoint to render an alias directory in user profiles or to provide a selection list of verified sender aliases in an email compose interface.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- By default, only active receiving aliases are returned. Pass `include_deleted=true` in the query to also fetch soft-deleted aliases (which have `deleted_at` timestamps set).\n\n### Troubleshooting\n- **401 Unauthorized**: Active token is missing, expired, or invalid.\n").option("--include-deleted", "include_deleted").action(async (opts) => {
|
|
3132
3160
|
const client2 = await loadSdkClient();
|
|
3133
3161
|
const result = await emailAliasList({
|
|
3134
3162
|
client: client2._rawClient,
|
|
@@ -3149,7 +3177,7 @@ var emailAliasListCommand = new Command34("ls").description("List the caller's a
|
|
|
3149
3177
|
|
|
3150
3178
|
// src/generated/cli/domain/add.ts
|
|
3151
3179
|
import { Command as Command35 } from "commander";
|
|
3152
|
-
var emailDomainCreateCommand = new Command35("add").description("Register a custom email domain").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3180
|
+
var emailDomainCreateCommand = new Command35("add").description("Register a custom email domain").addHelpText("after", "\n### Overview\nRegisters a new organization-owned custom email domain with the upstream provider and caches the returned DNS verification records in D1.\n\n### When to Use\n- Use this endpoint when onboarding a new custom email domain such as `mail.example.com`.\n- The response contains the DNS records the organization must publish before the domain can be verified.\n- This route registers the domain and returns DNS records. Custom-domain aliases require `status`, `sending_status`, and `receiving_status` to all be `verified`.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Domain ownership is globally unique across the platform. Once any organization has reserved a domain, another org cannot register it.\n- This route requires custom domain provider credentials in production because it performs a live provider registration call.\n\n### Troubleshooting\n- **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The hostname is malformed or belongs to the platform (`wspc.app` or its subdomains).\n- **409 Conflict / DOMAIN_CONFLICT**: The domain is already registered by some organization.\n- **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: The upstream provider request failed, timed out, or returned an unexpected shape.\n").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3153
3181
|
const client2 = await loadSdkClient();
|
|
3154
3182
|
const result = await emailDomainCreate({
|
|
3155
3183
|
client: client2._rawClient,
|
|
@@ -3170,7 +3198,7 @@ var emailDomainCreateCommand = new Command35("add").description("Register a cust
|
|
|
3170
3198
|
|
|
3171
3199
|
// src/generated/cli/domain/ls.ts
|
|
3172
3200
|
import { Command as Command36 } from "commander";
|
|
3173
|
-
var emailDomainListCommand = new Command36("ls").description("List cached custom domains").action(async (opts) => {
|
|
3201
|
+
var emailDomainListCommand = new Command36("ls").description("List cached custom domains").addHelpText("after", "\n### Overview\nReturns the caller organization's cached custom email domains from D1. This route does not call the upstream provider.\n\n### When to Use\n- Use this to render an admin view of all registered domains and their latest known verification state.\n- Use it to inspect DNS records that were previously fetched during create or verify operations.\n- The cached state includes DNS ownership, sending readiness, and receiving readiness used by custom-domain alias creation.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Results are scoped to the caller organization and sorted newest-first by creation time.\n").action(async (opts) => {
|
|
3174
3202
|
const client2 = await loadSdkClient();
|
|
3175
3203
|
const result = await emailDomainList({
|
|
3176
3204
|
client: client2._rawClient
|
|
@@ -3188,7 +3216,7 @@ var emailDomainListCommand = new Command36("ls").description("List cached custom
|
|
|
3188
3216
|
|
|
3189
3217
|
// src/generated/cli/alias/rm.ts
|
|
3190
3218
|
import { Command as Command37 } from "commander";
|
|
3191
|
-
var emailAliasDeleteCommand = new Command37("rm").description("Soft-delete an alias").argument("<email>", "email").action(async (email, opts) => {
|
|
3219
|
+
var emailAliasDeleteCommand = new Command37("rm").description("Soft-delete an alias").addHelpText("after", "\n### Overview\nSoft-deletes a specific active email receiving alias owned by the caller. Once soft-deleted, the alias stops accepting and forwarding any new inbound emails.\n\n### When to Use\n- Use this endpoint when decommissioning a disposable alias address that is no longer needed or is receiving excessive spam.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **Data Retention**: Soft-deletion is immediate. Inbound mail forwarding stops, but historical emails previously received on this alias remain fully readable in the inbox.\n- **Restoration**: The alias remains globally reserved and cannot be created fresh by anyone; use `POST /email/aliases/{email}/restore` to reactivate.\n- **Path Parameter**: The `@` character in the `{email}` path parameter must be URL-encoded as `%40`.\n\n### Troubleshooting\n- **401 Unauthorized**: Missing or invalid token.\n- **404 Not Found**: No active alias with this exact address was found for the authenticated user, or the alias is already deleted.\n").argument("<email>", "email").action(async (email, opts) => {
|
|
3192
3220
|
const client2 = await loadSdkClient();
|
|
3193
3221
|
const result = await emailAliasDelete({
|
|
3194
3222
|
client: client2._rawClient,
|
|
@@ -3209,7 +3237,7 @@ var emailAliasDeleteCommand = new Command37("rm").description("Soft-delete an al
|
|
|
3209
3237
|
|
|
3210
3238
|
// src/generated/cli/email/rm.ts
|
|
3211
3239
|
import { Command as Command38 } from "commander";
|
|
3212
|
-
var emailDeleteCommand = new Command38("rm").description("Soft-delete inbound emails").argument("<id...>", "id").action(async (id, opts) => {
|
|
3240
|
+
var emailDeleteCommand = new Command38("rm").description("Soft-delete inbound emails").addHelpText("after", "\n### Overview\nSoft-deletes a batch of inbound emails, moving them to the trash. Soft-deleted emails are immediately excluded from default inbox lists.\n\n### When to Use\n- Use this endpoint to trash one or more email messages from a user's inbox view.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Accepts 1 to 100 email IDs per call.\n- Deletion is fully reversible: soft-deleted rows persist in the database and can be undeleted using the restore endpoint.\n- **Data Cleanup**: Out-of-band background processes eventually purge associated raw MIME source payloads and attachment bytes from R2; deletion does not immediately free storage.\n\n### Troubleshooting\n- **401 Unauthorized**: Invalid Bearer token.\n- **400 Bad Request**: The request body is malformed or exceeds the maximum limit of 100 IDs.\n").argument("<id...>", "id").action(async (id, opts) => {
|
|
3213
3241
|
const idRaw = id;
|
|
3214
3242
|
const ids = idRaw.length > 0 ? idRaw : void 0;
|
|
3215
3243
|
const client2 = await loadSdkClient();
|
|
@@ -3232,7 +3260,7 @@ var emailDeleteCommand = new Command38("rm").description("Soft-delete inbound em
|
|
|
3232
3260
|
|
|
3233
3261
|
// src/generated/cli/domain/rm.ts
|
|
3234
3262
|
import { Command as Command39 } from "commander";
|
|
3235
|
-
var emailDomainDeleteCommand = new Command39("rm").description("Delete a custom email domain").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3263
|
+
var emailDomainDeleteCommand = new Command39("rm").description("Delete a custom email domain").addHelpText("after", "\n### Overview\nDeletes one active custom email domain for the caller organization. The worker first confirms no active aliases use the domain, deletes the upstream provider resource, then soft-deletes the cached D1 row.\n\n### When to Use\n- Use this when an organization no longer wants WSPC to manage a custom email domain.\n- Delete is only allowed when no active aliases use the domain.\n- Deleted domains are hidden from active list/get/verify/delete surfaces and cannot be self-restored in this version.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- This route requires custom domain provider credentials in production because it performs a live provider delete call.\n- Provider identifiers and provider raw errors are never returned to the client.\n\n### Troubleshooting\n- **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n- **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist, belongs to another organization, or was already deleted.\n- **409 Conflict / DOMAIN_IN_USE**: Active aliases still use this domain.\n- **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: Provider delete failed, timed out, or credentials are missing.\n").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3236
3264
|
const client2 = await loadSdkClient();
|
|
3237
3265
|
const result = await emailDomainDelete({
|
|
3238
3266
|
client: client2._rawClient,
|
|
@@ -3253,7 +3281,7 @@ var emailDomainDeleteCommand = new Command39("rm").description("Delete a custom
|
|
|
3253
3281
|
|
|
3254
3282
|
// src/generated/cli/domain/show.ts
|
|
3255
3283
|
import { Command as Command40 } from "commander";
|
|
3256
|
-
var emailDomainGetCommand = new Command40("show").description("Get one cached custom domain").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3284
|
+
var emailDomainGetCommand = new Command40("show").description("Get one cached custom domain").addHelpText("after", "\n### Overview\nReturns the caller organization's cached state for one custom email domain. This is a pure D1 read and never calls the upstream provider.\n\n### When to Use\n- Use this to inspect the latest cached DNS records or verification status for a single domain.\n- This cached view includes ownership, sending readiness, and receiving readiness state for custom-domain alias decisions.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- The `{domain}` path parameter is normalized and validated server-side before lookup.\n\n### Troubleshooting\n- **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n- **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist or belongs to another organization.\n").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3257
3285
|
const client2 = await loadSdkClient();
|
|
3258
3286
|
const result = await emailDomainGet({
|
|
3259
3287
|
client: client2._rawClient,
|
|
@@ -3274,7 +3302,7 @@ var emailDomainGetCommand = new Command40("show").description("Get one cached cu
|
|
|
3274
3302
|
|
|
3275
3303
|
// src/generated/cli/email/show.ts
|
|
3276
3304
|
import { Command as Command41 } from "commander";
|
|
3277
|
-
var emailGetCommand = new Command41("show").description("Get an inbound email by id").argument("<id>", "id").option("--include-html <value>", "When `true`, fetch the HTML body from R2 and include it as `html_body` in the response. Costs an extra R2 read; omit if you only need text.").option("--include-deleted <value>", "When `true`, allow fetching a soft-deleted email. Defaults to `false` (returns 404 for soft-deleted rows).").action(async (id, opts) => {
|
|
3305
|
+
var emailGetCommand = new Command41("show").description("Get an inbound email by id").addHelpText("after", "\n### Overview\nFetches the metadata and plain-text body of a single inbound email by its unique ID. It also returns metadata for all associated attachments and optionally resolves the rendered HTML content.\n\n### When to Use\n- Use this endpoint to display the complete detail view of an email message.\n- Use it to extract attachment files or read complex HTML layouts.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **R2 HTML Read**: The HTML body is stored in Object Storage (R2). To fetch it, explicitly pass `include_html=true` (this incurs an extra R2 read charge; leave unset if only plain text is needed).\n- Returns a 404 error if the email has been soft-deleted, unless `include_deleted=true` is set.\n\n### Troubleshooting\n- **401 Unauthorized**: Missing or expired token.\n- **404 Not Found**: The specified email ID does not exist, belongs to another user, or has been soft-deleted (without `include_deleted=true`).\n").argument("<id>", "id").option("--include-html <value>", "When `true`, fetch the HTML body from R2 and include it as `html_body` in the response. Costs an extra R2 read; omit if you only need text.").option("--include-deleted <value>", "When `true`, allow fetching a soft-deleted email. Defaults to `false` (returns 404 for soft-deleted rows).").action(async (id, opts) => {
|
|
3278
3306
|
const client2 = await loadSdkClient();
|
|
3279
3307
|
const result = await emailGet({
|
|
3280
3308
|
client: client2._rawClient,
|
|
@@ -3299,7 +3327,7 @@ var emailGetCommand = new Command41("show").description("Get an inbound email by
|
|
|
3299
3327
|
|
|
3300
3328
|
// src/generated/cli/email/ls.ts
|
|
3301
3329
|
import { Command as Command42 } from "commander";
|
|
3302
|
-
var emailListCommand = new Command42("ls").description("List inbound emails").option("--limit <value>", "Max items to return (clamped to 1-100). Defaults to 20 server-side.").option("--alias-email <value>", "If set, only return emails received on this full alias email address.").option("--unread-only <value>", "When `true`, only return emails with `is_read=false`.").option("--since <value>", "Unix epoch milliseconds \u2014 only return emails with `received_at >= since`. Useful for incremental sync.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").option("--include-deleted", "include_deleted").action(async (opts) => {
|
|
3330
|
+
var emailListCommand = new Command42("ls").description("List inbound emails").addHelpText("after", "\n### Overview\nRetrieves a paginated directory list of all inbound emails received by the user's active aliases, sorted in descending order of ingestion time (newest first).\n\n### When to Use\n- Use this endpoint to render mailbox dashboards or inbox streams.\n- Use query parameters to perform incremental syncs (via `since` timestamp) or to filter incoming mail by read state or target alias email.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **Pagination**: Supports cursor-based pagination. Pass the returned `next_cursor` value back as the `cursor` query parameter to list subsequent pages. The `limit` is capped between 1 and 100, defaulting to 20.\n- By default, soft-deleted emails are hidden. Pass `include_deleted=true` to retrieve them.\n\n### Troubleshooting\n- **401 Unauthorized**: Missing, invalid, or expired Bearer token.\n- **400 Bad Request**: Malformed pagination cursor or invalid query parameters (e.g., non-integer limit).\n").option("--limit <value>", "Max items to return (clamped to 1-100). Defaults to 20 server-side.").option("--alias-email <value>", "If set, only return emails received on this full alias email address.").option("--unread-only <value>", "When `true`, only return emails with `is_read=false`.").option("--since <value>", "Unix epoch milliseconds \u2014 only return emails with `received_at >= since`. Useful for incremental sync.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").option("--include-deleted", "include_deleted").action(async (opts) => {
|
|
3303
3331
|
const client2 = await loadSdkClient();
|
|
3304
3332
|
const result = await emailList({
|
|
3305
3333
|
client: client2._rawClient,
|
|
@@ -3325,7 +3353,7 @@ var emailListCommand = new Command42("ls").description("List inbound emails").op
|
|
|
3325
3353
|
|
|
3326
3354
|
// src/generated/cli/email/read.ts
|
|
3327
3355
|
import { Command as Command43 } from "commander";
|
|
3328
|
-
var emailMarkReadCommand = new Command43("read").description("Mark inbound emails as read").argument("<id...>", "id").action(async (id, opts) => {
|
|
3356
|
+
var emailMarkReadCommand = new Command43("read").description("Mark inbound emails as read").addHelpText("after", "\n### Overview\nMarks a batch of inbound emails as read. This batch operation is fully idempotent.\n\n### When to Use\n- Use this endpoint when a user opens an email detail view or performs a bulk mark-read action in an inbox dashboard.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Accepts 1 to 100 email IDs in a single call.\n- **Idempotency**: Already-read IDs are silently processed without generating errors but do not count toward the returned `marked` value. Missing, unauthorized, or soft-deleted IDs will be logged in `not_found`.\n\n### Troubleshooting\n- **401 Unauthorized**: Invalid or missing Bearer token.\n- **400 Bad Request**: The request body is malformed or exceeds the maximum limit of 100 IDs.\n").argument("<id...>", "id").action(async (id, opts) => {
|
|
3329
3357
|
const idRaw = id;
|
|
3330
3358
|
const ids = idRaw.length > 0 ? idRaw : void 0;
|
|
3331
3359
|
const client2 = await loadSdkClient();
|
|
@@ -3348,7 +3376,7 @@ var emailMarkReadCommand = new Command43("read").description("Mark inbound email
|
|
|
3348
3376
|
|
|
3349
3377
|
// src/generated/cli/email/unread.ts
|
|
3350
3378
|
import { Command as Command44 } from "commander";
|
|
3351
|
-
var emailMarkUnreadCommand = new Command44("unread").description("Mark inbound emails as unread").argument("<id...>", "id").action(async (id, opts) => {
|
|
3379
|
+
var emailMarkUnreadCommand = new Command44("unread").description("Mark inbound emails as unread").addHelpText("after", "\n### Overview\nResets a batch of inbound emails back to an unread state.\n\n### When to Use\n- Use this endpoint to undo an accidental read marking or to mark messages for later review.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Accepts 1 to 100 email IDs per call. Already-unread IDs are silently ignored but do not contribute to `marked`.\n\n### Troubleshooting\n- **401 Unauthorized**: Invalid Bearer token.\n- **400 Bad Request**: Malformed body or ID batch size limit exceeded.\n").argument("<id...>", "id").action(async (id, opts) => {
|
|
3352
3380
|
const idRaw = id;
|
|
3353
3381
|
const ids = idRaw.length > 0 ? idRaw : void 0;
|
|
3354
3382
|
const client2 = await loadSdkClient();
|
|
@@ -3371,7 +3399,7 @@ var emailMarkUnreadCommand = new Command44("unread").description("Mark inbound e
|
|
|
3371
3399
|
|
|
3372
3400
|
// src/generated/cli/alias/restore.ts
|
|
3373
3401
|
import { Command as Command45 } from "commander";
|
|
3374
|
-
var emailAliasRestoreCommand = new Command45("restore").description("Restore a soft-deleted alias").argument("<email>", "email").action(async (email, opts) => {
|
|
3402
|
+
var emailAliasRestoreCommand = new Command45("restore").description("Restore a soft-deleted alias").addHelpText("after", "\n### Overview\nReactivates a previously soft-deleted email receiving alias, immediately resuming mail forwarding to the user's inbox.\n\n### When to Use\n- Use this endpoint to re-enable a temporarily disabled alias or to recover one that was deleted by mistake.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- **Quota Check**: Reactivating an alias increases the active alias count towards the user's maximum quota of 10 active aliases. If the limit is exceeded, a `429 ALIAS_LIMIT_EXCEEDED` error is returned.\n- **Path Parameter**: The `@` character in the path parameter must be URL-encoded as `%40`.\n\n### Troubleshooting\n- **401 Unauthorized**: Missing or invalid token.\n- **404 Not Found**: No soft-deleted alias with this exact address was found for the authenticated user.\n- **429 Too Many Requests / ALIAS_LIMIT_EXCEEDED**: Reactivating this alias would exceed the per-user limit of 10 active aliases.\n").argument("<email>", "email").action(async (email, opts) => {
|
|
3375
3403
|
const client2 = await loadSdkClient();
|
|
3376
3404
|
const result = await emailAliasRestore({
|
|
3377
3405
|
client: client2._rawClient,
|
|
@@ -3392,7 +3420,7 @@ var emailAliasRestoreCommand = new Command45("restore").description("Restore a s
|
|
|
3392
3420
|
|
|
3393
3421
|
// src/generated/cli/email/restore.ts
|
|
3394
3422
|
import { Command as Command46 } from "commander";
|
|
3395
|
-
var emailRestoreCommand = new Command46("restore").description("Restore soft-deleted inbound emails").argument("<id...>", "id").action(async (id, opts) => {
|
|
3423
|
+
var emailRestoreCommand = new Command46("restore").description("Restore soft-deleted inbound emails").addHelpText("after", "\n### Overview\nRestores a batch of soft-deleted inbound emails from the trash, making them reappear in standard inbox lists.\n\n### When to Use\n- Use this endpoint to recover email messages that were trashed by mistake.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- Accepts 1 to 100 email IDs. Already-active IDs are silently ignored.\n\n### Troubleshooting\n- **401 Unauthorized**: Invalid token.\n- **400 Bad Request**: Malformed request or batch limit exceeded.\n").argument("<id...>", "id").action(async (id, opts) => {
|
|
3396
3424
|
const idRaw = id;
|
|
3397
3425
|
const ids = idRaw.length > 0 ? idRaw : void 0;
|
|
3398
3426
|
const client2 = await loadSdkClient();
|
|
@@ -3415,7 +3443,7 @@ var emailRestoreCommand = new Command46("restore").description("Restore soft-del
|
|
|
3415
3443
|
|
|
3416
3444
|
// src/generated/cli/domain/verify.ts
|
|
3417
3445
|
import { Command as Command47 } from "commander";
|
|
3418
|
-
var emailDomainVerifyCommand = new Command47("verify").description("Verify a custom domain with the provider").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3446
|
+
var emailDomainVerifyCommand = new Command47("verify").description("Verify a custom domain with the provider").addHelpText("after", "\n### Overview\nTriggers an upstream provider verification attempt for one custom email domain, refreshes the cached DNS records/status in D1, and returns the updated row.\nThis route refreshes DNS registration and verification state. Custom-domain aliases require `status`, `sending_status`, and `receiving_status` to all be `verified`.\n\n### When to Use\n- Use this after publishing the required DNS records, or whenever you want to refresh cached provider state explicitly.\n- If the provider verify call returns incomplete DNS records, the worker performs a follow-up provider read before responding.\n\n### Constraints\n- Requires a valid Bearer token in the `Authorization` header.\n- This route requires custom domain provider credentials in production because it performs live provider calls.\n- Verification is asynchronous provider work; a successful response may still report `status: pending`.\n- `status: verified` plus `sending_status: verified` enables custom-domain outbound send for active aliases; `receiving_status: verified` is also required before new custom-domain aliases can be created.\n\n### Troubleshooting\n- **400 Bad Request / DOMAIN_INVALID / DOMAIN_RESERVED**: The path hostname is malformed or reserved.\n- **404 Not Found / DOMAIN_NOT_FOUND**: The domain does not exist or belongs to another organization.\n- **502 Bad Gateway / DOMAIN_PROVIDER_ERROR**: Provider verification failed, timed out, or credentials are missing.\n").argument("<domain>", "domain").action(async (domain, opts) => {
|
|
3419
3447
|
const client2 = await loadSdkClient();
|
|
3420
3448
|
const result = await emailDomainVerify({
|
|
3421
3449
|
client: client2._rawClient,
|
|
@@ -3436,7 +3464,7 @@ var emailDomainVerifyCommand = new Command47("verify").description("Verify a cus
|
|
|
3436
3464
|
|
|
3437
3465
|
// src/generated/cli/push/config/rm.ts
|
|
3438
3466
|
import { Command as Command48 } from "commander";
|
|
3439
|
-
var pushConfigDeleteCommand = new Command48("rm").description("Remove a push transport").argument("<transport>", "transport").action(async (transport, opts) => {
|
|
3467
|
+
var pushConfigDeleteCommand = new Command48("rm").description("Remove a push transport").addHelpText("after", "\n### Overview\nDelete the configured push transport row, immediately halting push event dispatching for the caller.\n\n### When to Use\nWhen a user disconnects their notification channel, turns off push preferences, or resets their transport target.\n\n### Constraints\n- **Idempotency**: Deleting a transport that has not been registered (or was already deleted) is handled as a no-op, returning 204 `No Content`.\n- **Side Effects**: Hard-deletes the `(user_id, transport)` configuration record and completely purges all associated test history (`last_test_at` and `last_test_status`).\n- **Transport Support**: The path parameter must be a recognized transport identifier.\n\n### Troubleshooting\n- Returns 400 `UNKNOWN_TRANSPORT` if the transport parameter contains an unrecognized transport identifier.\n").argument("<transport>", "transport").action(async (transport, opts) => {
|
|
3440
3468
|
const client2 = await loadSdkClient();
|
|
3441
3469
|
const result = await pushConfigDelete({
|
|
3442
3470
|
client: client2._rawClient,
|
|
@@ -3457,7 +3485,7 @@ var pushConfigDeleteCommand = new Command48("rm").description("Remove a push tra
|
|
|
3457
3485
|
|
|
3458
3486
|
// src/generated/cli/push/config/set.ts
|
|
3459
3487
|
import { Command as Command49 } from "commander";
|
|
3460
|
-
var pushConfigSetCommand = new Command49("set").description("Register or update a push transport").option("--transport <value>", "Transport discriminator. `telegram` is the only supported value today \u2014 push delivers via a Telegram bot DM. Future transports (web push, iOS/Android, generic webhook) will be added as additional discriminator values.").option("--target-bot-username <value>", "Telegram bot username (with leading `@`, 5\u201332 alphanumeric/underscore characters). This is the bot the user has already started a chat with \u2014 wspc DMs notifications to it via the Telegram Bot API.").action(async (opts) => {
|
|
3488
|
+
var pushConfigSetCommand = new Command49("set").description("Register or update a push transport").addHelpText("after", "\n### Overview\nUpsert a notification transport configuration for the authenticated user. After registration, wspc can dispatch notifications to the user when registered product events fire.\n\n### When to Use\nFirst-time onboarding push configuration setup, or whenever the user updates their transport target details (e.g., pointing notifications to a new Telegram bot username).\n\n### Constraints\n- **Supported Transports**: Currently only `transport: telegram` is supported.\n- **Target Validation**: `target_bot_username` must be a valid Telegram bot name starting with `@` followed by 5\u201332 alphanumeric/underscore characters (`^@[A-Za-z0-9_]{5,32}$`).\n- **Uniqueness**: Up to one registration row is saved per `(user_id, transport)`. Upserting replaces any existing target config, updating `updated_at` while retaining `created_at`.\n- **No Side-effect Messages**: Registering a transport does **not** send a test notification; clients should separately trigger `POST /push/test`.\n\n### Troubleshooting\n- Returns 400 `INVALID_CONFIG` if payload structure is invalid or `target_bot_username` validation fails.\n").option("--transport <value>", "Transport discriminator. `telegram` is the only supported value today \u2014 push delivers via a Telegram bot DM. Future transports (web push, iOS/Android, generic webhook) will be added as additional discriminator values.").option("--target-bot-username <value>", "Telegram bot username (with leading `@`, 5\u201332 alphanumeric/underscore characters). This is the bot the user has already started a chat with \u2014 wspc DMs notifications to it via the Telegram Bot API.").action(async (opts) => {
|
|
3461
3489
|
const client2 = await loadSdkClient();
|
|
3462
3490
|
const result = await pushConfigSet({
|
|
3463
3491
|
client: client2._rawClient,
|
|
@@ -3481,7 +3509,7 @@ var pushConfigSetCommand = new Command49("set").description("Register or update
|
|
|
3481
3509
|
|
|
3482
3510
|
// src/generated/cli/push/config/show.ts
|
|
3483
3511
|
import { Command as Command50 } from "commander";
|
|
3484
|
-
var pushConfigGetCommand = new Command50("show").description("List the caller's push transports").action(async (opts) => {
|
|
3512
|
+
var pushConfigGetCommand = new Command50("show").description("List the caller's push transports").addHelpText("after", "\n### Overview\nRetrieve all active push transport configurations registered for the authenticated user.\n\n### When to Use\nRender settings page, determine if push notifications are enabled before prompting the user, or fetch historical health check results (`last_test_at` and `last_test_status`).\n\n### Constraints\n- **List Limitations**: Currently returns at most one active registration row (`telegram`).\n- **Data Security**: Response payload contains sensitive data (e.g. `target_bot_username`). Callers must handle these values as user secret-equivalent and prevent leakage.\n\n### Troubleshooting\n- Standard 401 Unauthorized or 403 Forbidden checks if authentication credentials are missing or invalid.\n").action(async (opts) => {
|
|
3485
3513
|
const client2 = await loadSdkClient();
|
|
3486
3514
|
const result = await pushConfigGet({
|
|
3487
3515
|
client: client2._rawClient
|
|
@@ -3499,7 +3527,7 @@ var pushConfigGetCommand = new Command50("show").description("List the caller's
|
|
|
3499
3527
|
|
|
3500
3528
|
// src/generated/cli/push/test.ts
|
|
3501
3529
|
import { Command as Command51 } from "commander";
|
|
3502
|
-
var pushTestCommand = new Command51("test").description("Send a test push notification").option("--transport <value>", "Which transport to send the test message through. Must match a transport the caller has already registered via `POST /push/config`; today only `telegram` is supported.").action(async (opts) => {
|
|
3530
|
+
var pushTestCommand = new Command51("test").description("Send a test push notification").addHelpText("after", "\n### Overview\nSynchronously dispatch a static test message via the requested transport target to verify delivery health.\n\n### When to Use\nImmediately after executing `POST /push/config` to verify connection legitimacy, or when troubleshooting missing notification claims.\n\n### Constraints\n- **Target Requirement**: You must have already successfully registered the targeted transport configuration.\n- **Side Effects**: Sends a single probe message to the upstream provider (e.g. Telegram Bot API). Test details are persisted to the configuration row under `last_test_at` and `last_test_status`.\n- **No Audit Footprint**: This operation is treated strictly as an integration probe and will not generate a product audit log footprint.\n\n### Troubleshooting\n- **Upstream Error Handling**: This endpoint returns an HTTP `200 OK` status even if the upstream dispatch fails. Callers must inspect `ok: false` and review `status` and `detail` in the response JSON to verify connection health.\n- Returns 404 `NO_CONFIG` if the user has not registered configuration details for the requested transport.\n").option("--transport <value>", "Which transport to send the test message through. Must match a transport the caller has already registered via `POST /push/config`; today only `telegram` is supported.").action(async (opts) => {
|
|
3503
3531
|
const client2 = await loadSdkClient();
|
|
3504
3532
|
const result = await pushTest({
|
|
3505
3533
|
client: client2._rawClient,
|
|
@@ -3523,7 +3551,7 @@ var pushTestCommand = new Command51("test").description("Send a test push notifi
|
|
|
3523
3551
|
|
|
3524
3552
|
// src/generated/cli/todo/comment/add.ts
|
|
3525
3553
|
import { Command as Command52 } from "commander";
|
|
3526
|
-
var todoCommentCreateCommand = new Command52("add").description("Add a comment to a todo").argument("<id>", "id").argument("<content>", "content").action(async (id, content, opts) => {
|
|
3554
|
+
var todoCommentCreateCommand = new Command52("add").description("Add a comment to a todo").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nAttach a free-text comment to a todo. Use this to record progress updates, notes, or remarks as a task moves along.\n\n### \u{1F4A1} Key Features & Constraints\n* **Free text**: Comments are plain text up to 10000 characters; there is no separate "progress" vs "remark" type.\n* **Authorship**: The author is recorded as the calling user (`user_id`).\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo does not exist or is soft-deleted.\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if content is empty or exceeds 10000 characters.\n\nExamples:\n $ wspc todo comment add tod_01HW3K "Verified on staging"\n').argument("<id>", "id").argument("<content>", "content").action(async (id, content, opts) => {
|
|
3527
3555
|
const client2 = await loadSdkClient();
|
|
3528
3556
|
const result = await todoCommentCreate({
|
|
3529
3557
|
client: client2._rawClient,
|
|
@@ -3547,7 +3575,7 @@ var todoCommentCreateCommand = new Command52("add").description("Add a comment t
|
|
|
3547
3575
|
|
|
3548
3576
|
// src/generated/cli/todo/comment/ls.ts
|
|
3549
3577
|
import { Command as Command53 } from "commander";
|
|
3550
|
-
var todoCommentListCommand = new Command53("ls").description("List comments on a todo").argument("<id>", "id").option("--order <value>", "order").option("--include-deleted <value>", "include_deleted").option("--limit <value>", "Max comments to return. Clamped to [1, 200]. Default 50 server-side.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").action(async (id, opts) => {
|
|
3578
|
+
var todoCommentListCommand = new Command53("ls").description("List comments on a todo").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nList the comments attached to a todo, oldest-first by default.\n\n### \u{1F4A1} Key Features & Constraints\n* **Ordering**: Defaults to chronological (`asc`). Pass `order=desc` for newest-first.\n* **Soft-deleted**: Hidden by default; pass `include_deleted=true` to include them.\n* **Pagination**: Use `limit` (max 200, default 50) and `cursor` (the `next_cursor` from a previous response) to page through results. When `next_cursor` is absent in the response, you are on the last page. Returns `{ comments, next_cursor? }`. Changing `order` invalidates a cursor.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo does not exist or is soft-deleted.\n* **`VALIDATION_ERROR`**: Thrown if a cursor was produced with a different `order` than the current request.\n\nExamples:\n $ wspc todo comment ls tod_01HW3K\n").argument("<id>", "id").option("--order <value>", "order").option("--include-deleted <value>", "include_deleted").option("--limit <value>", "Max comments to return. Clamped to [1, 200]. Default 50 server-side.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").action(async (id, opts) => {
|
|
3551
3579
|
const client2 = await loadSdkClient();
|
|
3552
3580
|
const result = await todoCommentList({
|
|
3553
3581
|
client: client2._rawClient,
|
|
@@ -3574,7 +3602,7 @@ var todoCommentListCommand = new Command53("ls").description("List comments on a
|
|
|
3574
3602
|
|
|
3575
3603
|
// src/generated/cli/todo/project/add.ts
|
|
3576
3604
|
import { Command as Command54 } from "commander";
|
|
3577
|
-
var projectCreateCommand = new Command54("add").description("Create a project").argument("<name>", "name").option("--default-todo-type-id <value>", "default_todo_type_id").action(async (name, opts) => {
|
|
3605
|
+
var projectCreateCommand = new Command54("add").description("Create a project").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nEstablish a new isolated project workspace.\n\n### \u{1F50D} When to Use\n* Use this to set up a new domain, team project, or separate workspace area to isolate tasks, custom types, and recurrence rules.\n\n### \u{1F4A1} Key Features & Constraints\n* **Project Partitioning**: Projects act as strict boundaries. Custom todo types and recurrence rules created under this project are strictly confined to it.\n* **Name Uniqueness**: Project names are free-form and do not have to be unique.\n* **Default Type Inheritance**: Omit `default_todo_type_id` to automatically inherit the Default Project\'s default task type.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing, if name is empty, or if name length constraints are violated.\n\nExamples:\n $ wspc todo project add "Personal"\n').argument("<name>", "name").option("--default-todo-type-id <value>", "default_todo_type_id").action(async (name, opts) => {
|
|
3578
3606
|
const client2 = await loadSdkClient();
|
|
3579
3607
|
const result = await projectCreate({
|
|
3580
3608
|
client: client2._rawClient,
|
|
@@ -3596,7 +3624,7 @@ var projectCreateCommand = new Command54("add").description("Create a project").
|
|
|
3596
3624
|
|
|
3597
3625
|
// src/generated/cli/todo/project/ls.ts
|
|
3598
3626
|
import { Command as Command55 } from "commander";
|
|
3599
|
-
var projectListCommand = new Command55("ls").description("List projects").option("--include-deleted <value>", "Set to `true` to include soft-deleted projects in the response.").action(async (opts) => {
|
|
3627
|
+
var projectListCommand = new Command55("ls").description("List projects").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nList all project workspaces available to the authenticated organization or user.\n\n### \u{1F50D} When to Use\n* Use this to populate project switcher dropdown menus, load side navigation views, or find valid project IDs before listing other scoped resources.\n\n### \u{1F4A1} Key Features & Constraints\n* **Archived Visibility**: Soft-deleted projects are omitted from default listings. Pass `include_deleted=true` to include them for auditing or recovery dashboards.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`AUTH_REQUIRED` (HTTP 401)**: Thrown if the caller is not authenticated.\n\nExamples:\n $ wspc todo project ls\n").option("--include-deleted <value>", "Set to `true` to include soft-deleted projects in the response.").action(async (opts) => {
|
|
3600
3628
|
const client2 = await loadSdkClient();
|
|
3601
3629
|
const result = await projectList({
|
|
3602
3630
|
client: client2._rawClient,
|
|
@@ -3617,7 +3645,7 @@ var projectListCommand = new Command55("ls").description("List projects").option
|
|
|
3617
3645
|
|
|
3618
3646
|
// src/generated/cli/todo/rule/add.ts
|
|
3619
3647
|
import { Command as Command56 } from "commander";
|
|
3620
|
-
var recurrenceRuleCreateCommand = new Command56("add").description("Create a recurring todo rule").argument("<title>", "title").option("--rrule <value>", "rrule").option("--dtstart <value>", "dtstart").option("--description <value>", "description").option("--parent-id <value>", "parent_id").option("-p, --project <value>", "Project for the recurrence rule, its template todo, and all materialized instances. Must be an active project in the caller's organization.").option("-t, --type <value>", "type_id").action(async (title, opts) => {
|
|
3648
|
+
var recurrenceRuleCreateCommand = new Command56("add").description("Create a recurring todo rule").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nCreate a recurrence rule that materializes upcoming todo instances on a repeating schedule.\n\n### \u{1F50D} When to Use\n* Use this to set up recurring work like a weekly Standup, monthly reporting, or cyclical maintenance. The server automatically materializes upcoming todo instances on a 14-day rolling horizon.\n\n### \u{1F4A1} Key Features & Constraints\n* **RFC-5545 Conformity**: The `rrule` parameter must be a valid RFC-5545 schedule string (e.g., `FREQ=WEEKLY;BYDAY=MO`) and must **not** include the `DTSTART` or `TZID` directive.\n* **Anchor Date**: `dtstart` specifies the local calendar starting date (`YYYY-MM-DD`) where the schedule rule is anchored.\n* **Nesting Constraints**: Recurrence rules can only be bound to root-level tasks. Child tasks (subtasks) cannot have recurrence rules. Setting a child task as a parent will trigger `PARENT_IS_CHILD`.\n* **Instance Independence**: Once materialized, each todo instance is fully independent with its own `status` and `due_at`.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`RRULE_INVALID` (HTTP 400)**: Thrown if the `rrule` schedule string is broken or contains illegal `DTSTART` directives.\n* **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the specified `parent_id` points to a child task.\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if date format is invalid or required fields are missing.\n\nExamples:\n $ wspc todo rule add "Weekly review" --rrule "FREQ=WEEKLY;BYDAY=MO" --dtstart 2026-05-18 --project prj_xxx\n $ wspc todo rule add "Weekly review" --rrule "FREQ=WEEKLY;BYDAY=MO" --dtstart 2026-05-18 --project prj_xxx --type typ_xxx\n').argument("<title>", "title").option("--rrule <value>", "rrule").option("--dtstart <value>", "dtstart").option("--description <value>", "description").option("--parent-id <value>", "parent_id").option("-p, --project <value>", "Project for the recurrence rule, its template todo, and all materialized instances. Must be an active project in the caller's organization.").option("-t, --type <value>", "type_id").action(async (title, opts) => {
|
|
3621
3649
|
const client2 = await loadSdkClient();
|
|
3622
3650
|
const result = await recurrenceRuleCreate({
|
|
3623
3651
|
client: client2._rawClient,
|
|
@@ -3644,7 +3672,7 @@ var recurrenceRuleCreateCommand = new Command56("add").description("Create a rec
|
|
|
3644
3672
|
|
|
3645
3673
|
// src/generated/cli/todo/rule/ls.ts
|
|
3646
3674
|
import { Command as Command57 } from "commander";
|
|
3647
|
-
var recurrenceRuleListCommand = new Command57("ls").description("List recurring todo rules").option("--project-id <value>", "Project id filter. Required. Unknown, cross-organization, or soft-deleted project ids return NOT_FOUND.").option("--user-id <value>", "user_id").action(async (opts) => {
|
|
3675
|
+
var recurrenceRuleListCommand = new Command57("ls").description("List recurring todo rules").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nReturn all active recurrence rules within a specific project owned by the caller.\n\n### \u{1F50D} When to Use\n* Use this to render rule management panels, list scheduled automation templates, or inspect active rules.\n\n### \u{1F4A1} Key Features & Constraints\n* **Project Scope**: The `project_id` query parameter is strictly required.\n* **Exclusion**: Soft-deleted/archived rules are excluded from the response by default.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` query filter is omitted.\n\nExamples:\n $ wspc todo rule ls\n").option("--project-id <value>", "Project id filter. Required. Unknown, cross-organization, or soft-deleted project ids return NOT_FOUND.").option("--user-id <value>", "user_id").action(async (opts) => {
|
|
3648
3676
|
const client2 = await loadSdkClient();
|
|
3649
3677
|
const result = await recurrenceRuleList({
|
|
3650
3678
|
client: client2._rawClient,
|
|
@@ -3680,7 +3708,7 @@ function parseJsonField(raw, flag) {
|
|
|
3680
3708
|
}
|
|
3681
3709
|
|
|
3682
3710
|
// src/generated/cli/todo/add.ts
|
|
3683
|
-
var todoCreateCommand = new Command58("add").description("Create a todo").argument("<title>", "title").option("-p, --project <value>", "Project id to assign this todo to. It must be an active project in the caller's organization.").option("--description <value>", "Free-form details about the todo. Fully supports GFM Markdown (tables, strikethrough, task lists). Stored verbatim; client applications are responsible for rendering. Optional. Passing `null` is strictly rejected.").option("--parent-id <value>", "Parent todo ID (`tod_<ULID>`) to attach this todo as a child under another todo. Omit or pass `null` to create a root-level todo. Nesting is limited to one level; attempting to set a child todo as a parent will trigger `PARENT_IS_CHILD`. To make a subtask appear on every occurrence of a recurring rule, set this to that rule's template todo id (the template id returned when the rule is created); the server re-materializes future occurrences so each carries the subtask.").option("--status <value>", "Initial status of the todo. Omit to default to `open`. Allowed values: `open`, `in_progress`, `done`, `cancelled`.").option("--due-at <value>", 'Optional calendar due date in ISO date-only format (`YYYY-MM-DD`). Stored without timezone offsets to represent the same local calendar day globally. Pass `""` or omit the field to skip setting a due date. Passing `null` is strictly rejected.').option("--idempotency-key <value>", "idempotency_key").option("--type-id <value>", "Type id this todo belongs to. Omit to use the project's default type. When project_id is also supplied, the type must belong to the same project. New server-generated type ids use typ_<ULID>; legacy ids remain accepted.").option("--custom-fields <value>", "Custom field values keyed by the field's immutable `key` (not the human `label`). Each value must match the declared field type: string fields require string values, and string_array fields require string arrays. Providing a key that is not declared on the resolved todo type is strictly rejected with `UNDECLARED_FIELD`. Missing required fields that lack a default value are rejected with `FIELD_REQUIRED`. Defaults declared on the type are auto-applied at create time.").action(async (title, opts) => {
|
|
3711
|
+
var todoCreateCommand = new Command58("add").description("Create a todo").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nCreate a new todo item under a specified project. This can either be a standalone root-level todo or a nested subtask attached to an existing root todo.\n\n### \u{1F50D} When to Use\n* Use this to capture a fresh work item, document an ongoing task, or break a larger root todo into subtasks by creating child todos under it.\n\n### \u{1F4A1} Key Features & Constraints\n* **One-Level Nesting Limit**: WSPC supports a maximum of one level of task nesting (Root \u2794 Child). A root-level todo can have children, but a child todo cannot have further subtasks. Setting a child todo as a parent will fail and trigger a `PARENT_IS_CHILD` error.\n* **Description Handling**: Passing a non-empty string stores the description; passing `""` explicitly stores an empty string. Passing `null` is strictly rejected.\n* **Due Date Format**: Accepts an ISO-8601 date-only format (`YYYY-MM-DD`). Pass `""` or omit the field to skip setting a due date.\n* **Project Binding**: Every todo must belong to a valid active project (`project_id`).\n\n### \u{1F4A1} Best Practices & Guidelines\n* **Descriptive Descriptions**: Always provide a detailed description explaining the task\'s context, goal, or definition of done. Avoid leaving it empty.\n* **Task Breakdown**: For complex items, split the task into 2-3 logical subtasks (by passing a parent todo ID in `parent_id`). Remember WSPC supports only one level of nesting (Root -> Child).\n* **Integration with Drive**: If a task requires storing large text blocks, research logs, checklists, or files, do not overload the description. Use the Drive feature to store a markdown file (e.g., `research/notes.md`) and place a clean reference link in the description, such as `[Notes](drive://<library>/<path>)`.\n* **Structured Properties (Custom Fields)**: Avoid putting structured meta-attributes (like priority, severity, story points, tags) directly in the description. Instead, use custom todo types (`todo_type`). Create a custom type schema first, then assign it with `type_id` and pass values via `custom_fields`.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing, if `due_at` violates the `YYYY-MM-DD` format, or if `title` exceeds 500 characters.\n* **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the target `parent_id` refers to a todo that is itself already a child todo.\n* **`WOULD_CREATE_CYCLE` (HTTP 400)**: Thrown if `parent_id` points to the todo\'s own ID.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the specified `project_id` or `parent_id` does not exist or has been soft-deleted.\n\nExamples:\n $ wspc todo add "Buy milk"\n $ wspc todo add "Buy milk" --project prj_xxx\n $ wspc todo add "Fix styling issue" --type-id typ_xxx --custom-fields \'{"severity":"high","tags":["ui"]}\'\n').argument("<title>", "title").option("-p, --project <value>", "Project id to assign this todo to. It must be an active project in the caller's organization.").option("--description <value>", "Free-form details about the todo. Fully supports GFM Markdown (tables, strikethrough, task lists). Stored verbatim; client applications are responsible for rendering. Optional. Passing `null` is strictly rejected.").option("--parent-id <value>", "Parent todo ID (`tod_<ULID>`) to attach this todo as a child under another todo. Omit or pass `null` to create a root-level todo. Nesting is limited to one level; attempting to set a child todo as a parent will trigger `PARENT_IS_CHILD`. To make a subtask appear on every occurrence of a recurring rule, set this to that rule's template todo id (the template id returned when the rule is created); the server re-materializes future occurrences so each carries the subtask.").option("--status <value>", "Initial status of the todo. Omit to default to `open`. Allowed values: `open`, `in_progress`, `done`, `cancelled`.").option("--due-at <value>", 'Optional calendar due date in ISO date-only format (`YYYY-MM-DD`). Stored without timezone offsets to represent the same local calendar day globally. Pass `""` or omit the field to skip setting a due date. Passing `null` is strictly rejected.').option("--idempotency-key <value>", "idempotency_key").option("--type-id <value>", "Type id this todo belongs to. Omit to use the project's default type. When project_id is also supplied, the type must belong to the same project. New server-generated type ids use typ_<ULID>; legacy ids remain accepted.").option("--custom-fields <value>", "Custom field values keyed by the field's immutable `key` (not the human `label`). Each value must match the declared field type: string fields require string values, and string_array fields require string arrays. Providing a key that is not declared on the resolved todo type is strictly rejected with `UNDECLARED_FIELD`. Missing required fields that lack a default value are rejected with `FIELD_REQUIRED`. Defaults declared on the type are auto-applied at create time.").action(async (title, opts) => {
|
|
3684
3712
|
const client2 = await loadSdkClient();
|
|
3685
3713
|
const result = await todoCreate({
|
|
3686
3714
|
client: client2._rawClient,
|
|
@@ -3709,7 +3737,7 @@ var todoCreateCommand = new Command58("add").description("Create a todo").argume
|
|
|
3709
3737
|
|
|
3710
3738
|
// src/generated/cli/todo/ls.ts
|
|
3711
3739
|
import { Command as Command59 } from "commander";
|
|
3712
|
-
var todoListCommand = new Command59("ls").description("List todos with filters").option("-p, --project <value>", "Filter by project. Required. Unknown, cross-organization, or soft-deleted project ids return NOT_FOUND.").option("--user-id <value>", "user_id").option("--parent-id <value>", "parent_id").option("-s, --status <value>", "status").option("--include-deleted", "include_deleted").option("--include-templates <value>", "include_templates").option("--due-after <value>", "due_after").option("--due-before <value>", "due_before").option("--type-id <value>", "type_id").option("--sort-by <value>", "sort_by").option("--order <value>", "order").option("--include-orphan-fields <value>", "include_orphan_fields").option("--limit <value>", "Max todos to return. Clamped to [1, 200]. Default 50 server-side.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").action(async (opts) => {
|
|
3740
|
+
var todoListCommand = new Command59("ls").description("List todos with filters").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nReturn the caller's active or archived todos, with comprehensive options to filter by project, parent task, status, due-date window, and template visibility.\n\n### \u{1F50D} When to Use\n* Use this to render the main todo board dashboard, query items due in a specific timeframe (using `due_after` and `due_before`), or lazy-load subtasks for an expanded parent todo by passing its ID.\n\n### \u{1F4A1} Key Features & Constraints\n* **Required Parameter**: The `project_id` query parameter is strictly required and must match an active project.\n* **Parent Tasks**: Omitting `parent_id` lists root-level todos by default. Pass a todo id to list direct children of that specific task.\n* **Multi-Status Filters**: Multi-value `status` query is supported by repeating the parameter, e.g., `?status=open&status=in_progress`.\n* **Due-Date Windowing**: The `due_after` filter is inclusive, while `due_before` is exclusive, forming a half-open window `[due_after, due_before)`. Both parameters exclude todos with no due date.\n* **Template & Soft-Delete Visibility**: Soft-deleted todos are hidden unless `include_deleted=true`. Template todos backing recurrence rules are hidden unless `include_templates=true`.\n* **Custom-Field Filters (`cf.<key>=<value>`)**: Repeatable dynamic-prefix query parameters whose name follows the `cf.<key>` pattern (e.g. `?cf.priority=high&cf.team=eng`). Each pair is ANDed; for `string_array` custom fields the match is positive when the array contains the value. Keys must be declared on the project's todo type schema. Because the prefix is dynamic, these parameters cannot be expressed in the JSON Schema below \u2014 clients must construct them from the URL query string directly.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` is missing, or if query parameters fail schema validation.\n\nExamples:\n $ wspc todo ls\n $ wspc todo ls --status open\n $ wspc todo ls --project prj_xxx\n").option("-p, --project <value>", "Filter by project. Required. Unknown, cross-organization, or soft-deleted project ids return NOT_FOUND.").option("--user-id <value>", "user_id").option("--parent-id <value>", "parent_id").option("-s, --status <value>", "status").option("--include-deleted", "include_deleted").option("--include-templates <value>", "include_templates").option("--due-after <value>", "due_after").option("--due-before <value>", "due_before").option("--type-id <value>", "type_id").option("--sort-by <value>", "sort_by").option("--order <value>", "order").option("--include-orphan-fields <value>", "include_orphan_fields").option("--limit <value>", "Max todos to return. Clamped to [1, 200]. Default 50 server-side.").option("--cursor <value>", "Opaque pagination cursor returned in `next_cursor` of a previous response.").action(async (opts) => {
|
|
3713
3741
|
const client2 = await loadSdkClient();
|
|
3714
3742
|
const result = await todoList({
|
|
3715
3743
|
client: client2._rawClient,
|
|
@@ -3741,9 +3769,33 @@ var todoListCommand = new Command59("ls").description("List todos with filters")
|
|
|
3741
3769
|
render({ kind: "todo_list", display: { "shape": "list", "columns": ["id", "status", "title", "due_at"], "format": { "id": "id-short", "status": "status-badge", "title": "truncate", "due_at": "relative-time" }, "emptyMessage": "no todos" } }, result.data);
|
|
3742
3770
|
});
|
|
3743
3771
|
|
|
3744
|
-
// src/generated/cli/todo/type/
|
|
3772
|
+
// src/generated/cli/todo/type/add.ts
|
|
3745
3773
|
import { Command as Command60 } from "commander";
|
|
3746
|
-
var
|
|
3774
|
+
var todoTypeCreateCommand = new Command60("add").description("Create a todo type").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nCreate a new custom todo type. This allows you to define specialized category schemas (e.g. "Bug Report") and configure custom field constraints.\n\n### \u{1F50D} When to Use\n* Use this to set up customized task behaviors (e.g. tracking choices, additional metadata, or enforcing hidden fields) tailored to a project.\n\n### \u{1F4A1} Key Features & Constraints\n* **Automatic Seeding**: The first project initialization will lazily seed a `Default Project` and a `Default` todo type if they do not already exist.\n* **Metadata Schema**: Custom field keys mapped here are evaluated during task creation/update.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if required fields are missing or schema constraints are violated.\n\nExamples:\n $ wspc todo type add "Bug Report"\n $ wspc todo type add "Bug Report" --project prj_xxx\n $ wspc todo type add "Sprint Task" --custom-fields \'[{"key":"story_points","label":"Story Points","type":"string"}]\'\n').argument("<label>", "label").option("-p, --project <value>", "Project this type belongs to. Required. It must be an active project in the caller's organization.").option("--hide-core-fields <value>", "hide_core_fields").option("--custom-fields <value>", "custom_fields").action(async (label, opts) => {
|
|
3775
|
+
const client2 = await loadSdkClient();
|
|
3776
|
+
const result = await todoTypeCreate({
|
|
3777
|
+
client: client2._rawClient,
|
|
3778
|
+
body: {
|
|
3779
|
+
label,
|
|
3780
|
+
project_id: opts.project,
|
|
3781
|
+
hide_core_fields: parseJsonField(opts.hideCoreFields, "hide-core-fields"),
|
|
3782
|
+
custom_fields: parseJsonField(opts.customFields, "custom-fields")
|
|
3783
|
+
}
|
|
3784
|
+
});
|
|
3785
|
+
if (result.error || !result.response?.ok) {
|
|
3786
|
+
process.stderr.write(
|
|
3787
|
+
`HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
|
|
3788
|
+
`
|
|
3789
|
+
);
|
|
3790
|
+
process.exitCode = 1;
|
|
3791
|
+
return;
|
|
3792
|
+
}
|
|
3793
|
+
render({ kind: "todo_type_create", display: void 0 }, result.data);
|
|
3794
|
+
});
|
|
3795
|
+
|
|
3796
|
+
// src/generated/cli/todo/type/ls.ts
|
|
3797
|
+
import { Command as Command61 } from "commander";
|
|
3798
|
+
var todoTypeListCommand = new Command61("ls").description("List todo types").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nList custom todo types defined within a project.\n\n### \u{1F50D} When to Use\n* Use this to populate task type selection dropdown elements or load category metadata for dynamic custom forms.\n\n### \u{1F4A1} Key Features & Constraints\n* **Required Parameter**: The `project_id` filter is strictly required and must match an active project.\n* **Exclusion**: Soft-deleted types are excluded by default. Pass `include_deleted=true` to surface archived rows for a recovery UI.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if `project_id` query parameter is omitted.\n\nExamples:\n $ wspc todo type ls\n").option("--project-id <value>", "Project id filter. Required. Unknown, cross-organization, or soft-deleted project ids return NOT_FOUND.").option("--user-id <value>", "user_id").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
|
|
3747
3799
|
const client2 = await loadSdkClient();
|
|
3748
3800
|
const result = await todoTypeList({
|
|
3749
3801
|
client: client2._rawClient,
|
|
@@ -3765,8 +3817,8 @@ var todoTypeListCommand = new Command60("ls").description("List todo types").opt
|
|
|
3765
3817
|
});
|
|
3766
3818
|
|
|
3767
3819
|
// src/generated/cli/todo/comment/rm.ts
|
|
3768
|
-
import { Command as
|
|
3769
|
-
var todoCommentDeleteCommand = new
|
|
3820
|
+
import { Command as Command62 } from "commander";
|
|
3821
|
+
var todoCommentDeleteCommand = new Command62("rm").description("Soft-delete a comment").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nSoft-delete a comment.\n\n### \u{1F4A1} Key Features & Constraints\n* **Soft delete**: The comment is hidden from default listings but retained; there is no restore endpoint.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`COMMENT_NOT_FOUND` (HTTP 404)**: Thrown if the comment id is unknown, already deleted, or not in the caller's organization.\n\nExamples:\n $ wspc todo comment rm tdc_01HW3K\n").argument("<id>", "id").action(async (id, opts) => {
|
|
3770
3822
|
const client2 = await loadSdkClient();
|
|
3771
3823
|
const result = await todoCommentDelete({
|
|
3772
3824
|
client: client2._rawClient,
|
|
@@ -3786,8 +3838,8 @@ var todoCommentDeleteCommand = new Command61("rm").description("Soft-delete a co
|
|
|
3786
3838
|
});
|
|
3787
3839
|
|
|
3788
3840
|
// src/generated/cli/todo/comment/edit.ts
|
|
3789
|
-
import { Command as
|
|
3790
|
-
var todoCommentUpdateCommand = new
|
|
3841
|
+
import { Command as Command63 } from "commander";
|
|
3842
|
+
var todoCommentUpdateCommand = new Command63("edit").description("Edit a comment").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nEdit the body of an existing comment.\n\n### \u{1F4A1} Key Features & Constraints\n* **Last write wins**: There is no optimistic-lock version on comments; the latest edit replaces the content.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`COMMENT_NOT_FOUND` (HTTP 404)**: Thrown if the comment id is unknown, soft-deleted, or not in the caller\'s organization.\n* **`VALIDATION_ERROR` (HTTP 400)**: Thrown if content is empty or exceeds 10000 characters.\n\nExamples:\n $ wspc todo comment edit tdc_01HW3K "Edited note"\n').argument("<id>", "id").argument("<content>", "content").action(async (id, content, opts) => {
|
|
3791
3843
|
const client2 = await loadSdkClient();
|
|
3792
3844
|
const result = await todoCommentUpdate({
|
|
3793
3845
|
client: client2._rawClient,
|
|
@@ -3810,8 +3862,8 @@ var todoCommentUpdateCommand = new Command62("edit").description("Edit a comment
|
|
|
3810
3862
|
});
|
|
3811
3863
|
|
|
3812
3864
|
// src/generated/cli/todo/project/rm.ts
|
|
3813
|
-
import { Command as
|
|
3814
|
-
var projectDeleteCommand = new
|
|
3865
|
+
import { Command as Command64 } from "commander";
|
|
3866
|
+
var projectDeleteCommand = new Command64("rm").description("Soft-delete a project").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nSoft-delete/archive a project workspace.\n\n### \u{1F50D} When to Use\n* Use this to archive a completed project and hide it from default listings without losing historical metrics.\n\n### \u{1F4A1} Key Features & Constraints\n* **Cascading Effects**: Deleting a project automatically soft-deletes the project record and cascades to soft-delete all todos created under it.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the project ID does not exist or has already been archived.\n\nExamples:\n $ wspc todo project rm prj_01HW3K\n").argument("<id>", "id").action(async (id, opts) => {
|
|
3815
3867
|
const client2 = await loadSdkClient();
|
|
3816
3868
|
const result = await projectDelete({
|
|
3817
3869
|
client: client2._rawClient,
|
|
@@ -3831,8 +3883,8 @@ var projectDeleteCommand = new Command63("rm").description("Soft-delete a projec
|
|
|
3831
3883
|
});
|
|
3832
3884
|
|
|
3833
3885
|
// src/generated/cli/todo/rule/rm.ts
|
|
3834
|
-
import { Command as
|
|
3835
|
-
var recurrenceRuleDeleteCommand = new
|
|
3886
|
+
import { Command as Command65 } from "commander";
|
|
3887
|
+
var recurrenceRuleDeleteCommand = new Command65("rm").description("Delete a recurring todo rule").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nSoft-delete/delete a recurrence rule to immediately halt future task materialization.\n\n### \u{1F50D} When to Use\n* Use this to permanently end an ongoing cyclical schedule automation (e.g., when a weekly standby rotation is retired).\n\n### \u{1F4A1} Key Features & Constraints\n* **Historic Preservation**: Deleting a rule stops the rolling schedule generations, but **does not** delete or alter todo tasks that have already been materialized. They remain on the user's list.\n* **Optimistic Locking**: Supports optional `expected_version` checks.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` mismatches the database.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target rule ID does not exist.\n\nExamples:\n $ wspc todo rule rm tdr_xxx\n $ wspc todo rule rm tdr_xxx --expected-version 3\n").argument("<id>", "id").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
|
|
3836
3888
|
const client2 = await loadSdkClient();
|
|
3837
3889
|
const result = await recurrenceRuleDelete({
|
|
3838
3890
|
client: client2._rawClient,
|
|
@@ -3855,8 +3907,8 @@ var recurrenceRuleDeleteCommand = new Command64("rm").description("Delete a recu
|
|
|
3855
3907
|
});
|
|
3856
3908
|
|
|
3857
3909
|
// src/generated/cli/todo/rule/show.ts
|
|
3858
|
-
import { Command as
|
|
3859
|
-
var recurrenceRuleGetCommand = new
|
|
3910
|
+
import { Command as Command66 } from "commander";
|
|
3911
|
+
var recurrenceRuleGetCommand = new Command66("show").description("Get a recurring todo rule").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nFetch a single recurrence rule along with its template todo snapshot and the count of materialized instances.\n\n### \u{1F50D} When to Use\n* Use this to inspect rule details before editing, preview the task template that future occurrences will copy, or check the current materialization metrics.\n\n### \u{1F4A1} Key Features & Constraints\n* **Snapshot Integrity**: The returned template represents a schema template snapshot \u2014 modifying the rule (PATCH) only alters future occurrences; already-materialized tasks are never mutated retroactively.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the specified rule ID does not exist.\n\nExamples:\n $ wspc todo rule show tdr_xxx\n").argument("<id>", "id").action(async (id, opts) => {
|
|
3860
3912
|
const client2 = await loadSdkClient();
|
|
3861
3913
|
const result = await recurrenceRuleGet({
|
|
3862
3914
|
client: client2._rawClient,
|
|
@@ -3876,8 +3928,8 @@ var recurrenceRuleGetCommand = new Command65("show").description("Get a recurrin
|
|
|
3876
3928
|
});
|
|
3877
3929
|
|
|
3878
3930
|
// src/generated/cli/todo/rm.ts
|
|
3879
|
-
import { Command as
|
|
3880
|
-
var todoDeleteCommand = new
|
|
3931
|
+
import { Command as Command67 } from "commander";
|
|
3932
|
+
var todoDeleteCommand = new Command67("rm").description("Soft-delete a todo").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nSoft-delete a todo item so that it no longer appears in active list queries. The record remains in the database and can be recovered later.\n\n### \u{1F50D} When to Use\n* Use this to hide an item from your active listings without permanently losing the history or metrics.\n\n### \u{1F4A1} Key Features & Constraints\n* **Cascading Delete (`cascade`)**: If the target todo has active child subtasks:\n - If `cascade: false` (default), the deletion will fail and throw a `HAS_CHILDREN` error to prevent accidental orphaned tasks.\n - If `cascade: true`, the target todo and all its nested child subtasks will be soft-deleted together.\n* **Optimistic Locking**: You may optionally pass `expected_version` to ensure the todo has not been modified since you last read it.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`HAS_CHILDREN` (HTTP 400)**: Thrown if you attempt to delete a parent todo that has active subtasks without explicitly setting `cascade: true`.\n* **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` is provided and mismatches the database.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo `id` does not exist or has already been soft-deleted.\n\nExamples:\n $ wspc todo rm tod_xxx\n").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--cascade <value>", "cascade").action(async (id, opts) => {
|
|
3881
3933
|
const client2 = await loadSdkClient();
|
|
3882
3934
|
const result = await todoDelete({
|
|
3883
3935
|
client: client2._rawClient,
|
|
@@ -3901,8 +3953,8 @@ var todoDeleteCommand = new Command66("rm").description("Soft-delete a todo").ar
|
|
|
3901
3953
|
});
|
|
3902
3954
|
|
|
3903
3955
|
// src/generated/cli/todo/show.ts
|
|
3904
|
-
import { Command as
|
|
3905
|
-
var todoGetCommand = new
|
|
3956
|
+
import { Command as Command68 } from "commander";
|
|
3957
|
+
var todoGetCommand = new Command68("show").description("Get a todo by id").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nFetch the full details of a single todo item by its unique identifier.\n\n### \u{1F50D} When to Use\n* Use this to confirm the current state of a task, inspect nested field values, or retrieve its current `version` before issuing an optimistic update (PATCH).\n\n### \u{1F4A1} Key Features & Constraints\n* **Soft-Deleted Recovery**: A soft-deleted todo will return an HTTP 404 unless the query parameter `?include_deleted=true` is explicitly supplied.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the specified todo `id` does not exist, or has been soft-deleted and the request did not supply `include_deleted=true`.\n\nExamples:\n $ wspc todo show tod_xxx\n").argument("<id>", "id").option("--include-deleted <value>", "include_deleted").option("--include-orphan-fields <value>", "include_orphan_fields").action(async (id, opts) => {
|
|
3906
3958
|
const client2 = await loadSdkClient();
|
|
3907
3959
|
const result = await todoGet({
|
|
3908
3960
|
client: client2._rawClient,
|
|
@@ -3927,8 +3979,8 @@ var todoGetCommand = new Command67("show").description("Get a todo by id").argum
|
|
|
3927
3979
|
});
|
|
3928
3980
|
|
|
3929
3981
|
// src/generated/cli/todo/update.ts
|
|
3930
|
-
import { Command as
|
|
3931
|
-
var todoUpdateCommand = new
|
|
3982
|
+
import { Command as Command69 } from "commander";
|
|
3983
|
+
var todoUpdateCommand = new Command69("update").description("Update a todo").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nUpdate one or more fields of an existing todo item, such as its title, status, parent todo, due date, or description.\n\n### \u{1F50D} When to Use\n* Use this to log progress by changing the status (e.g., to `in_progress` or `done`), reschedule due dates, edit title/description, or reassign/move a task by changing its `parent_id`.\n\n### \u{1F4A1} Key Features & Constraints\n* **Optimistic Locking (`expected_version`)**: An optional integer representing the version you expect to update. If provided, the server matches it with the current database version. If they match, the update succeeds and increments the version; if they mismatch, a `VERSION_CONFLICT` error is thrown. Omit this field to skip version checking (Last-Write-Wins behavior).\n* **Parent Re-assignment**: Set `parent_id: null` to move a child todo back to the root level.\n* **Status Transitions**: Transitioning the `status` to `done` automatically emits a `captureTodoCompleted` analytics event.\n* **Clearing Fields**: To clear an existing description or due date, explicitly pass `""`. Passing `null` is rejected.\n\n### \u{1F4A1} Best Practices & Guidelines\n* **Enriched Context**: Keep the description updated with definition of done, relevant progress notes, or resolution summaries.\n* **Keep Descriptions Clean**: Delegate heavy logs/documents to a Markdown file on Drive, and put a markdown link inside the description.\n* **Structured Properties**: Use custom fields (`custom_fields`) matching the todo\'s type to record properties like tags, priority, or severity.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` does not match the current database row version.\n* **`PARENT_IS_CHILD` (HTTP 400)**: Thrown if the new `parent_id` refers to a todo that is itself already a child todo.\n* **`WOULD_CREATE_CYCLE` (HTTP 400)**: Thrown if the update attempts to make a parent todo a child of its own descendant.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the todo `id` or the new `parent_id` does not exist or has been soft-deleted.\n\nExamples:\n $ wspc todo update tod_xxx --status done\n $ wspc todo update tod_xxx --title "New title"\n $ wspc todo update tod_xxx --custom-fields \'{"severity":"critical"}\'\n').argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--title <value>", "New title. Omit to leave the existing title unchanged. Must be non-empty when supplied.").option("--description <value>", 'New description. Markdown formatted (CommonMark + GFM tables, strikethrough, task lists). Pass empty string `""` explicitly to clear an existing description, or omit to leave unchanged. Passing `null` is strictly rejected.').option("--parent-id <value>", "Re-parent the todo. Pass a valid parent ID to attach under another todo, pass `null` to move it back to the root level, or omit to leave unchanged. Nesting is limited to one level; attempting to set a child todo as a parent will trigger `PARENT_IS_CHILD`.").option("--status <value>", "New status of the todo. Allowed transitions: `open` \u2794 `in_progress` \u2794 `done`. `cancelled` represents a terminal state. Transitioning to `done` automatically emits a `captureTodoCompleted` analytics event. Omit to leave the existing status unchanged.").option("--due-at <value>", 'Update calendar due date in ISO date-only format (`YYYY-MM-DD`). Pass `""` explicitly to clear an existing due date, or omit to leave it unchanged. Passing `null` is strictly rejected.').option("--type-id <value>", "Re-assign this todo to a different active type. The new type must belong to the todo's same project; otherwise the request fails with TYPE_PROJECT_MISMATCH. New server-generated type ids use typ_<ULID>; legacy ids remain accepted.").option("--custom-fields <value>", "PATCH semantics: only the keys present in this map change. Pass `null` for a key (e.g. `custom_fields: { priority: null }`) to explicitly delete that custom field value. Array values are replaced wholesale with no element-level diff. Providing a key that is not declared on the effective todo type is rejected with `UNDECLARED_FIELD`.").option("--user-id <value>", "Reassign the owner (assignee) user ID of this todo. Target user must belong to the same organization.").action(async (id, opts) => {
|
|
3932
3984
|
const client2 = await loadSdkClient();
|
|
3933
3985
|
const result = await todoUpdate({
|
|
3934
3986
|
client: client2._rawClient,
|
|
@@ -3958,9 +4010,57 @@ var todoUpdateCommand = new Command68("update").description("Update a todo").arg
|
|
|
3958
4010
|
render({ kind: "todo_update", display: { "shape": "object", "format": { "id": "id-short", "user_id": "id-short", "project_id": "id-short", "parent_id": "id-short", "type_id": "id-short", "status": "status-badge", "due_at": "relative-time", "created_at": "relative-time", "updated_at": "relative-time", "deleted_at": "relative-time" } } }, result.data);
|
|
3959
4011
|
});
|
|
3960
4012
|
|
|
4013
|
+
// src/generated/cli/todo/type/rm.ts
|
|
4014
|
+
import { Command as Command70 } from "commander";
|
|
4015
|
+
var todoTypeDeleteCommand = new Command70("rm").description("Soft-delete a todo type").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nSoft-delete/archive a custom todo type.\n\n### \u{1F50D} When to Use\n* Use this to retire a custom task category workspace that is no longer needed.\n\n### \u{1F4A1} Key Features & Constraints\n* **Default Type Protection**: The current active default type of a project cannot be deleted. You must assign another type as default first; otherwise the call fails with `CANNOT_DELETE_DEFAULT_TYPE`.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`CANNOT_DELETE_DEFAULT_TYPE` (HTTP 409)**: Thrown if the target todo type is currently the project's default type.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n\nExamples:\n $ wspc todo type rm typ_xxx\n").argument("<id>", "id").action(async (id, opts) => {
|
|
4016
|
+
const client2 = await loadSdkClient();
|
|
4017
|
+
const result = await todoTypeDelete({
|
|
4018
|
+
client: client2._rawClient,
|
|
4019
|
+
path: {
|
|
4020
|
+
id
|
|
4021
|
+
}
|
|
4022
|
+
});
|
|
4023
|
+
if (result.error || !result.response?.ok) {
|
|
4024
|
+
process.stderr.write(
|
|
4025
|
+
`HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
|
|
4026
|
+
`
|
|
4027
|
+
);
|
|
4028
|
+
process.exitCode = 1;
|
|
4029
|
+
return;
|
|
4030
|
+
}
|
|
4031
|
+
render({ kind: "todo_type_delete", display: void 0 }, result.data);
|
|
4032
|
+
});
|
|
4033
|
+
|
|
4034
|
+
// src/generated/cli/todo/type/set.ts
|
|
4035
|
+
import { Command as Command71 } from "commander";
|
|
4036
|
+
var todoTypeUpdateCommand = new Command71("set").description("Update a todo type").addHelpText("after", '\n### \u{1F3AF} Overview & Purpose\nUpdate a custom todo type\'s label, core field overrides, or custom field schema definitions.\n\n### \u{1F50D} When to Use\n* Use this to rename a task category category, hide native todo attributes, or adjust custom data schemas.\n\n### \u{1F4A1} Key Features & Constraints\n* **Type Modification Constraints**: Changing the data `type` of an existing custom field key (e.g. converting a string field to a boolean field) is strictly rejected with `CANNOT_CHANGE_FIELD_TYPE`. To migrate, remove the key and re-add it under a brand new name.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`CANNOT_CHANGE_FIELD_TYPE` (HTTP 422)**: Thrown if you attempt to modify the declared data type of an existing custom field key.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n\nExamples:\n $ wspc todo type set typ_xxx --label "Feature Request"\n $ wspc todo type set typ_xxx --custom-fields \'[{"key":"severity","label":"Severity","type":"string"}]\'\n').argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--label <value>", "label").option("--hide-core-fields <value>", "hide_core_fields").option("--custom-fields <value>", "custom_fields").action(async (id, opts) => {
|
|
4037
|
+
const client2 = await loadSdkClient();
|
|
4038
|
+
const result = await todoTypeUpdate({
|
|
4039
|
+
client: client2._rawClient,
|
|
4040
|
+
path: {
|
|
4041
|
+
id
|
|
4042
|
+
},
|
|
4043
|
+
body: {
|
|
4044
|
+
expected_version: opts.expectedVersion,
|
|
4045
|
+
label: opts.label,
|
|
4046
|
+
hide_core_fields: parseJsonField(opts.hideCoreFields, "hide-core-fields"),
|
|
4047
|
+
custom_fields: parseJsonField(opts.customFields, "custom-fields")
|
|
4048
|
+
}
|
|
4049
|
+
});
|
|
4050
|
+
if (result.error || !result.response?.ok) {
|
|
4051
|
+
process.stderr.write(
|
|
4052
|
+
`HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
|
|
4053
|
+
`
|
|
4054
|
+
);
|
|
4055
|
+
process.exitCode = 1;
|
|
4056
|
+
return;
|
|
4057
|
+
}
|
|
4058
|
+
render({ kind: "todo_type_update", display: void 0 }, result.data);
|
|
4059
|
+
});
|
|
4060
|
+
|
|
3961
4061
|
// src/generated/cli/todo/restore.ts
|
|
3962
|
-
import { Command as
|
|
3963
|
-
var todoRestoreCommand = new
|
|
4062
|
+
import { Command as Command72 } from "commander";
|
|
4063
|
+
var todoRestoreCommand = new Command72("restore").description("Restore a soft-deleted todo").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nReverse a previous soft-delete. The todo (and optionally its descendants) is recovered back to the active list.\n\n### \u{1F50D} When to Use\n* Use this to recover a task deleted by mistake, or pull a task out of the trash to continue active work.\n\n### \u{1F4A1} Key Features & Constraints\n* **Orphan Warning**: If the restored todo's parent is still in the trash, the call succeeds but returns `parent_in_trash_warning: true`, signaling that the restored todo is currently orphaned from a visible ancestor.\n* **Cascading Restore (`cascade`)**: If `cascade: true` is provided, all descendants still in the trash are also restored. Otherwise, descendants are left in the trash, and their count is reported back in `descendants_in_trash_count`.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`VERSION_CONFLICT` (HTTP 409)**: Thrown if `expected_version` is supplied and mismatches the database.\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target todo `id` does not exist or has already been permanently purged.\n\nExamples:\n $ wspc todo restore tod_xxx\n $ wspc todo restore tod_xxx --cascade\n").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--cascade <value>", "cascade").action(async (id, opts) => {
|
|
3964
4064
|
const client2 = await loadSdkClient();
|
|
3965
4065
|
const result = await todoRestore({
|
|
3966
4066
|
client: client2._rawClient,
|
|
@@ -3983,6 +4083,27 @@ var todoRestoreCommand = new Command69("restore").description("Restore a soft-de
|
|
|
3983
4083
|
render({ kind: "todo_restore", display: { "shape": "object", "format": { "id": "id-short", "user_id": "id-short", "project_id": "id-short", "parent_id": "id-short", "type_id": "id-short", "status": "status-badge", "due_at": "relative-time", "created_at": "relative-time", "updated_at": "relative-time", "deleted_at": "relative-time" } } }, result.data);
|
|
3984
4084
|
});
|
|
3985
4085
|
|
|
4086
|
+
// src/generated/cli/todo/type/restore.ts
|
|
4087
|
+
import { Command as Command73 } from "commander";
|
|
4088
|
+
var todoTypeRestoreCommand = new Command73("restore").description("Restore a soft-deleted todo type").addHelpText("after", "\n### \u{1F3AF} Overview & Purpose\nRestore a previously archived/soft-deleted custom todo type.\n\n### \u{1F50D} When to Use\n* Use this to bring a retired task category back into active status.\n\n### \u{1F4A1} Key Features & Constraints\n* **Task Re-Attachment**: Restoring a type clears its `deleted_at` timestamp. Todo items previously assigned to this type immediately become active and validated under this recovered category schema.\n\n### \u26A0\uFE0F Common Errors & Troubleshooting\n* **`NOT_FOUND` (HTTP 404)**: Thrown if the target ID does not exist.\n\nExamples:\n $ wspc todo type restore typ_xxx\n").argument("<id>", "id").action(async (id, opts) => {
|
|
4089
|
+
const client2 = await loadSdkClient();
|
|
4090
|
+
const result = await todoTypeRestore({
|
|
4091
|
+
client: client2._rawClient,
|
|
4092
|
+
path: {
|
|
4093
|
+
id
|
|
4094
|
+
}
|
|
4095
|
+
});
|
|
4096
|
+
if (result.error || !result.response?.ok) {
|
|
4097
|
+
process.stderr.write(
|
|
4098
|
+
`HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
|
|
4099
|
+
`
|
|
4100
|
+
);
|
|
4101
|
+
process.exitCode = 1;
|
|
4102
|
+
return;
|
|
4103
|
+
}
|
|
4104
|
+
render({ kind: "todo_type_restore", display: void 0 }, result.data);
|
|
4105
|
+
});
|
|
4106
|
+
|
|
3986
4107
|
// src/generated/cli/index.ts
|
|
3987
4108
|
function registerGeneratedCommands(root) {
|
|
3988
4109
|
const root_invite = root.command("invite").description("invite commands");
|
|
@@ -4069,7 +4190,11 @@ function registerGeneratedCommands(root) {
|
|
|
4069
4190
|
root_todo.addCommand(todoCreateCommand);
|
|
4070
4191
|
root_todo.addCommand(todoListCommand);
|
|
4071
4192
|
const root_todo_type = root_todo.command("type").description("type commands");
|
|
4193
|
+
root_todo_type.addCommand(todoTypeCreateCommand);
|
|
4072
4194
|
root_todo_type.addCommand(todoTypeListCommand);
|
|
4195
|
+
root_todo_type.addCommand(todoTypeDeleteCommand);
|
|
4196
|
+
root_todo_type.addCommand(todoTypeUpdateCommand);
|
|
4197
|
+
root_todo_type.addCommand(todoTypeRestoreCommand);
|
|
4073
4198
|
root_todo.addCommand(todoDeleteCommand);
|
|
4074
4199
|
root_todo.addCommand(todoGetCommand);
|
|
4075
4200
|
root_todo.addCommand(todoUpdateCommand);
|
|
@@ -4077,7 +4202,7 @@ function registerGeneratedCommands(root) {
|
|
|
4077
4202
|
}
|
|
4078
4203
|
|
|
4079
4204
|
// src/handwritten/commands/login.ts
|
|
4080
|
-
import { Command as
|
|
4205
|
+
import { Command as Command74 } from "commander";
|
|
4081
4206
|
|
|
4082
4207
|
// src/handwritten/auth/device-flow.ts
|
|
4083
4208
|
var DEFAULT_SLEEP = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -4319,7 +4444,7 @@ function resolveLoginTarget(opts, env) {
|
|
|
4319
4444
|
function wantsJson(opts, env) {
|
|
4320
4445
|
return opts.json === true || env.WSPC_OUTPUT === "json";
|
|
4321
4446
|
}
|
|
4322
|
-
var loginCommand = new
|
|
4447
|
+
var loginCommand = new Command74("login").description("Log in via OAuth device flow (default) or API key").option("--api-key <key>", "Log in with a wspc API key (escape hatch)").option("--api-base <url>", "Target API base URL (default: production)").option("--env <name>", "Config env name to store credentials under").option("--json", "Emit machine-readable events to stdout").action(async (opts) => {
|
|
4323
4448
|
const store = new ConfigStore();
|
|
4324
4449
|
const { baseUrl, envName } = resolveLoginTarget(opts, process.env);
|
|
4325
4450
|
const output = wantsJson(opts, process.env) ? { write: () => {
|
|
@@ -4338,7 +4463,7 @@ var loginCommand = new Command70("login").description("Log in via OAuth device f
|
|
|
4338
4463
|
});
|
|
4339
4464
|
|
|
4340
4465
|
// src/handwritten/commands/logout.ts
|
|
4341
|
-
import { Command as
|
|
4466
|
+
import { Command as Command75 } from "commander";
|
|
4342
4467
|
|
|
4343
4468
|
// src/handwritten/auth/logout.ts
|
|
4344
4469
|
async function runLogout(opts) {
|
|
@@ -4371,7 +4496,7 @@ async function runLogout(opts) {
|
|
|
4371
4496
|
}
|
|
4372
4497
|
|
|
4373
4498
|
// src/handwritten/commands/logout.ts
|
|
4374
|
-
var logoutCommand = new
|
|
4499
|
+
var logoutCommand = new Command75("logout").description("Log out an account (default: the active account in the current env)").argument("[email]", "Email of the account to log out").option("--all", "Log out every account in the current env").action(async (email, opts) => {
|
|
4375
4500
|
const res = await runLogout({ store: new ConfigStore(), email, all: opts.all });
|
|
4376
4501
|
if (res.removed.length === 0) {
|
|
4377
4502
|
process.stdout.write("nothing to log out\n");
|
|
@@ -4384,7 +4509,7 @@ var logoutCommand = new Command71("logout").description("Log out an account (def
|
|
|
4384
4509
|
});
|
|
4385
4510
|
|
|
4386
4511
|
// src/handwritten/commands/whoami.ts
|
|
4387
|
-
import { Command as
|
|
4512
|
+
import { Command as Command76 } from "commander";
|
|
4388
4513
|
var ENV_DISPLAY = {
|
|
4389
4514
|
shape: "object",
|
|
4390
4515
|
fields: ["name", "api_base", "account", "actor", "agent_label"]
|
|
@@ -4415,7 +4540,7 @@ async function backfillActiveEmail(store, envName, email, userId) {
|
|
|
4415
4540
|
rekeyLegacyAccount(cfg, envName, email, userId);
|
|
4416
4541
|
});
|
|
4417
4542
|
}
|
|
4418
|
-
var whoamiCommand = new
|
|
4543
|
+
var whoamiCommand = new Command76("whoami").description("Show the active env, signed-in account, and organization").action(async () => {
|
|
4419
4544
|
const store = new ConfigStore();
|
|
4420
4545
|
const config = await store.read();
|
|
4421
4546
|
let resolved;
|
|
@@ -4468,8 +4593,8 @@ function printLoggedOut() {
|
|
|
4468
4593
|
}
|
|
4469
4594
|
|
|
4470
4595
|
// src/handwritten/commands/config.ts
|
|
4471
|
-
import { Command as
|
|
4472
|
-
var configCommand = new
|
|
4596
|
+
import { Command as Command77 } from "commander";
|
|
4597
|
+
var configCommand = new Command77("config").description("Manage wspc local config");
|
|
4473
4598
|
registerRenderer("config_show", (data) => {
|
|
4474
4599
|
const d = data;
|
|
4475
4600
|
if (d.envs.length === 0) {
|
|
@@ -4540,7 +4665,7 @@ configCommand.command("use <env>").description("Switch current_env").action(asyn
|
|
|
4540
4665
|
});
|
|
4541
4666
|
|
|
4542
4667
|
// src/handwritten/commands/account.ts
|
|
4543
|
-
import { Command as
|
|
4668
|
+
import { Command as Command78 } from "commander";
|
|
4544
4669
|
async function listAccounts(store) {
|
|
4545
4670
|
const c = await store.read();
|
|
4546
4671
|
const envName = c.current_env;
|
|
@@ -4581,7 +4706,7 @@ registerRenderer("account_ls", (data) => {
|
|
|
4581
4706
|
]);
|
|
4582
4707
|
process.stdout.write(table(headers, body));
|
|
4583
4708
|
});
|
|
4584
|
-
var accountCommand = new
|
|
4709
|
+
var accountCommand = new Command78("account").description("Manage logged-in accounts");
|
|
4585
4710
|
accountCommand.command("ls").description("List accounts in the current env (active marked with \u2713)").action(async () => {
|
|
4586
4711
|
const accounts = await listAccounts(new ConfigStore());
|
|
4587
4712
|
render({ kind: "account_ls" }, { accounts });
|
|
@@ -4593,7 +4718,7 @@ accountCommand.command("switch <email>").description("Set the active account for
|
|
|
4593
4718
|
});
|
|
4594
4719
|
|
|
4595
4720
|
// src/handwritten/commands/tour.ts
|
|
4596
|
-
import { Command as
|
|
4721
|
+
import { Command as Command79 } from "commander";
|
|
4597
4722
|
var GUIDE_URL_DEFAULT = "https://mcp.wspc.ai/guide";
|
|
4598
4723
|
function resolveGuideUrl(env = process.env) {
|
|
4599
4724
|
const override = env.WSPC_GUIDE_URL?.trim();
|
|
@@ -4605,14 +4730,14 @@ async function fetchGuide(url, fetchImpl = fetch) {
|
|
|
4605
4730
|
return await res.text();
|
|
4606
4731
|
}
|
|
4607
4732
|
var TOUR_HINT = "This is the wspc guided tour for your AI agent \u2014 ask your agent to run `wspc tour` and follow it.\n";
|
|
4608
|
-
var tourCommand = new
|
|
4733
|
+
var tourCommand = new Command79("tour").description("Print the wspc guided-tour script for your AI agent to read and follow").action(async () => {
|
|
4609
4734
|
const text = await fetchGuide(resolveGuideUrl());
|
|
4610
4735
|
if (process.stdout.isTTY) process.stderr.write(TOUR_HINT);
|
|
4611
4736
|
process.stdout.write(text.endsWith("\n") ? text : text + "\n");
|
|
4612
4737
|
});
|
|
4613
4738
|
|
|
4614
4739
|
// src/handwritten/commands/todo-done.ts
|
|
4615
|
-
import { Command as
|
|
4740
|
+
import { Command as Command80 } from "commander";
|
|
4616
4741
|
var TODO_UPDATE_DISPLAY = {
|
|
4617
4742
|
shape: "object",
|
|
4618
4743
|
format: {
|
|
@@ -4630,7 +4755,7 @@ var TODO_UPDATE_DISPLAY = {
|
|
|
4630
4755
|
deleted_at: "relative-time"
|
|
4631
4756
|
}
|
|
4632
4757
|
};
|
|
4633
|
-
var todoDoneCommand = new
|
|
4758
|
+
var todoDoneCommand = new Command80("done").description("Mark a todo done (sugar for `update <id> --status done`)").argument("<id>", "Todo id").action(async (id) => {
|
|
4634
4759
|
const client2 = await loadSdkClient();
|
|
4635
4760
|
const result = await todoUpdate({
|
|
4636
4761
|
client: client2._rawClient,
|
|
@@ -4649,7 +4774,7 @@ var todoDoneCommand = new Command76("done").description("Mark a todo done (sugar
|
|
|
4649
4774
|
});
|
|
4650
4775
|
|
|
4651
4776
|
// src/handwritten/commands/email/send.ts
|
|
4652
|
-
import { Command as
|
|
4777
|
+
import { Command as Command81 } from "commander";
|
|
4653
4778
|
import { randomUUID } from "crypto";
|
|
4654
4779
|
import { readFile, stat } from "fs/promises";
|
|
4655
4780
|
import { basename } from "path";
|
|
@@ -4708,7 +4833,7 @@ async function resolveAttachment(input) {
|
|
|
4708
4833
|
`--attach ${input}: neither a readable file nor a valid <prefix>_<ulid>:<idx> reference.`
|
|
4709
4834
|
);
|
|
4710
4835
|
}
|
|
4711
|
-
var sendCommand = new
|
|
4836
|
+
var sendCommand = new Command81("send").description("Send an outbound email").requiredOption("--from <alias-email>", "alias email to send from").option("--to <addr...>", "recipient address (repeatable)", []).option("--subject <text>", "subject").option("--text <body>", "plain-text body").option("--text-file <path>", "read text body from file").option("--reply <id>", "inbound email id to reply to").option("--attach <path-or-ref...>", "attachment (file path or eml_xxx:idx)", []).option("--idempotency-key <key>", "idempotency key (auto-generated if omitted)").action(async (opts) => {
|
|
4712
4837
|
const isReply = Boolean(opts.reply);
|
|
4713
4838
|
const to = opts.to;
|
|
4714
4839
|
const attachInputs = opts.attach;
|
|
@@ -4797,7 +4922,7 @@ var sendCommand = new Command77("send").description("Send an outbound email").re
|
|
|
4797
4922
|
});
|
|
4798
4923
|
|
|
4799
4924
|
// src/handwritten/commands/email/attachment.ts
|
|
4800
|
-
import { Command as
|
|
4925
|
+
import { Command as Command82 } from "commander";
|
|
4801
4926
|
import { createWriteStream } from "fs";
|
|
4802
4927
|
import { Readable } from "stream";
|
|
4803
4928
|
import { pipeline } from "stream/promises";
|
|
@@ -4815,7 +4940,7 @@ function parseContentDispositionFilename(header) {
|
|
|
4815
4940
|
}
|
|
4816
4941
|
|
|
4817
4942
|
// src/handwritten/commands/email/attachment.ts
|
|
4818
|
-
var attachmentCommand = new
|
|
4943
|
+
var attachmentCommand = new Command82("attachment").description("Download an inbound email attachment by index").argument("<email-id>").argument("<idx>").option("--output <path>", "output file path").option("--include-deleted", "allow downloads from soft-deleted parent emails").action(async (emailId, idxArg, opts) => {
|
|
4819
4944
|
const idx = Number(idxArg);
|
|
4820
4945
|
if (!Number.isInteger(idx) || idx < 0) {
|
|
4821
4946
|
process.stderr.write(`<idx> must be a non-negative integer (got "${idxArg}")
|
|
@@ -4847,7 +4972,7 @@ var attachmentCommand = new Command78("attachment").description("Download an inb
|
|
|
4847
4972
|
});
|
|
4848
4973
|
|
|
4849
4974
|
// src/handwritten/commands/drive/bind.ts
|
|
4850
|
-
import { Command as
|
|
4975
|
+
import { Command as Command83 } from "commander";
|
|
4851
4976
|
import { stat as stat3 } from "fs/promises";
|
|
4852
4977
|
import { resolve } from "path";
|
|
4853
4978
|
|
|
@@ -5175,7 +5300,7 @@ async function assertExistingDirectory(path) {
|
|
|
5175
5300
|
}
|
|
5176
5301
|
}
|
|
5177
5302
|
function driveBindCommand() {
|
|
5178
|
-
return new
|
|
5303
|
+
return new Command83("bind").description("Bind a local folder to an existing Drive library").requiredOption("--library <id>", "existing Drive library id").argument("[path]", "local folder path", ".").action(async (path, opts) => {
|
|
5179
5304
|
const root = resolve(path);
|
|
5180
5305
|
await assertExistingDirectory(root);
|
|
5181
5306
|
const api = await createDriveApi();
|
|
@@ -5193,7 +5318,7 @@ function driveBindCommand() {
|
|
|
5193
5318
|
}
|
|
5194
5319
|
|
|
5195
5320
|
// src/handwritten/commands/drive/sync.ts
|
|
5196
|
-
import { Command as
|
|
5321
|
+
import { Command as Command84 } from "commander";
|
|
5197
5322
|
import { mkdir as mkdir3, readFile as readFile4, rm as rm3, writeFile as writeFile3 } from "fs/promises";
|
|
5198
5323
|
import { basename as basename3, dirname as dirname2, join as join6, posix as pathPosix3, resolve as resolve3 } from "path";
|
|
5199
5324
|
import { createHash as createHash3, randomUUID as randomUUID4 } from "crypto";
|
|
@@ -6108,7 +6233,7 @@ function decisionFields(path, action, entry, local, remote) {
|
|
|
6108
6233
|
};
|
|
6109
6234
|
}
|
|
6110
6235
|
function driveSyncCommand(api) {
|
|
6111
|
-
const sync = new
|
|
6236
|
+
const sync = new Command84("sync").description("Drive sync commands");
|
|
6112
6237
|
sync.command("once").description("Run one Drive sync pass").argument("[path]", "local folder path", ".").action(async (path) => {
|
|
6113
6238
|
const summary = await runDriveSyncOnce(resolve3(path), api);
|
|
6114
6239
|
render({ kind: "drive_sync_once", display: { shape: "object" } }, summary);
|
|
@@ -6667,7 +6792,7 @@ function containsVersionConflict(value) {
|
|
|
6667
6792
|
}
|
|
6668
6793
|
|
|
6669
6794
|
// src/handwritten/commands/drive/watch.ts
|
|
6670
|
-
import { Command as
|
|
6795
|
+
import { Command as Command85 } from "commander";
|
|
6671
6796
|
import chokidar from "chokidar";
|
|
6672
6797
|
import { watch as fsWatch } from "fs";
|
|
6673
6798
|
import { basename as basename4, relative as relative2, resolve as resolve4 } from "path";
|
|
@@ -7174,7 +7299,7 @@ async function runDriveWatch(root, options = {}) {
|
|
|
7174
7299
|
}
|
|
7175
7300
|
}
|
|
7176
7301
|
function driveWatchCommand(options = {}) {
|
|
7177
|
-
return new
|
|
7302
|
+
return new Command85("watch").description("Watch a bound Drive folder and sync local changes").argument("[path]", "local folder path", ".").option("--debug", "append debug NDJSON events to <folder>/.wspc-drive/debug.log").action(async (path, flags) => {
|
|
7178
7303
|
const debug = options.debug ?? (flags.debug === true || process.env.WSPC_DRIVE_DEBUG === "1");
|
|
7179
7304
|
await runDriveWatch(resolve4(path), { ...options, debug });
|
|
7180
7305
|
});
|
|
@@ -7260,7 +7385,7 @@ function waitForStopSignal(onRegistered) {
|
|
|
7260
7385
|
function mountDriveCommands(program) {
|
|
7261
7386
|
let drive = program.commands.find((c) => c.name() === "drive");
|
|
7262
7387
|
if (!drive) {
|
|
7263
|
-
drive = new
|
|
7388
|
+
drive = new Command86("drive").description("Drive commands");
|
|
7264
7389
|
program.addCommand(drive);
|
|
7265
7390
|
}
|
|
7266
7391
|
if (!drive.commands.some((c) => c.name() === "bind")) {
|
|
@@ -7286,7 +7411,7 @@ function isCliEntrypoint(argv = process.argv, metaUrl = import.meta.url) {
|
|
|
7286
7411
|
}
|
|
7287
7412
|
}
|
|
7288
7413
|
function buildProgram() {
|
|
7289
|
-
const program = new
|
|
7414
|
+
const program = new Command86().name("wspc").description("Official CLI for wspc.ai").version(`wspc ${VERSION} (spec ${SPEC_SHA}, fetched ${SPEC_FETCHED_AT})`).option("--json", "Output raw JSON (machine-readable)").option("--account <email>", "Run as a specific account (overrides the active account)").hook("preAction", (_thisCommand, actionCommand) => {
|
|
7290
7415
|
const globals = actionCommand.optsWithGlobals();
|
|
7291
7416
|
if (globals.json) process.env.WSPC_OUTPUT = "json";
|
|
7292
7417
|
if (globals.account) process.env.WSPC_ACCOUNT = String(globals.account);
|