@wspc/cli 0.0.6 → 0.0.8

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 CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command43 } from "commander";
4
+ import { Command as Command55 } from "commander";
5
5
 
6
- // src/generated/cli/keys/create.ts
6
+ // src/generated/cli/invite/accept.ts
7
7
  import { Command } from "commander";
8
8
 
9
9
  // src/generated/sdk/core/bodySerializer.gen.ts
@@ -795,6 +795,11 @@ var createClient = (config = {}) => {
795
795
  var client = createClient(createConfig({ baseUrl: "https://api.wspc.ai" }));
796
796
 
797
797
  // src/generated/sdk/sdk.gen.ts
798
+ var inviteAccept = (options) => (options.client ?? client).post({
799
+ security: [{ scheme: "bearer", type: "http" }],
800
+ url: "/auth/invites/{id}/accept",
801
+ ...options
802
+ });
798
803
  var keyList = (options) => (options?.client ?? client).get({
799
804
  security: [{ scheme: "bearer", type: "http" }],
800
805
  url: "/auth/keys",
@@ -809,6 +814,20 @@ var keyCreate = (options) => (options.client ?? client).post({
809
814
  ...options.headers
810
815
  }
811
816
  });
817
+ var orgInvitesList = (options) => (options?.client ?? client).get({
818
+ security: [{ scheme: "bearer", type: "http" }],
819
+ url: "/auth/me/org/invites",
820
+ ...options
821
+ });
822
+ var orgInviteCreate = (options) => (options?.client ?? client).post({
823
+ security: [{ scheme: "bearer", type: "http" }],
824
+ url: "/auth/me/org/invites",
825
+ ...options,
826
+ headers: {
827
+ "Content-Type": "application/json",
828
+ ...options?.headers
829
+ }
830
+ });
812
831
  var orgGet = (options) => (options?.client ?? client).get({
813
832
  security: [{ scheme: "bearer", type: "http" }],
814
833
  url: "/auth/me/org",
@@ -823,16 +842,31 @@ var orgUpdate = (options) => (options?.client ?? client).patch({
823
842
  ...options?.headers
824
843
  }
825
844
  });
845
+ var inviteGet = (options) => (options.client ?? client).get({
846
+ security: [{ scheme: "bearer", type: "http" }],
847
+ url: "/auth/invites/{id}",
848
+ ...options
849
+ });
826
850
  var authMe = (options) => (options?.client ?? client).get({
827
851
  security: [{ scheme: "bearer", type: "http" }],
828
852
  url: "/auth/me",
829
853
  ...options
830
854
  });
855
+ var invitesList = (options) => (options?.client ?? client).get({
856
+ security: [{ scheme: "bearer", type: "http" }],
857
+ url: "/auth/invites",
858
+ ...options
859
+ });
831
860
  var orgMembersList = (options) => (options?.client ?? client).get({
832
861
  security: [{ scheme: "bearer", type: "http" }],
833
862
  url: "/auth/me/org/members",
834
863
  ...options
835
864
  });
865
+ var inviteReject = (options) => (options.client ?? client).post({
866
+ security: [{ scheme: "bearer", type: "http" }],
867
+ url: "/auth/invites/{id}/reject",
868
+ ...options
869
+ });
836
870
  var keyRevoke = (options) => (options.client ?? client).delete({
837
871
  security: [{ scheme: "bearer", type: "http" }],
838
872
  url: "/auth/keys/{id}",
@@ -847,6 +881,11 @@ var keyUpdate = (options) => (options.client ?? client).patch({
847
881
  ...options.headers
848
882
  }
849
883
  });
884
+ var orgInviteRevoke = (options) => (options.client ?? client).delete({
885
+ security: [{ scheme: "bearer", type: "http" }],
886
+ url: "/auth/me/org/invites/{id}",
887
+ ...options
888
+ });
850
889
  var eventList = (options) => (options?.client ?? client).get({
851
890
  security: [{ scheme: "bearer", type: "http" }],
852
891
  url: "/calendar/events",
@@ -982,6 +1021,20 @@ var pushTest = (options) => (options.client ?? client).post({
982
1021
  ...options.headers
983
1022
  }
984
1023
  });
1024
+ var todoCommentList = (options) => (options.client ?? client).get({
1025
+ security: [{ scheme: "bearer", type: "http" }],
1026
+ url: "/todo/items/{id}/comments",
1027
+ ...options
1028
+ });
1029
+ var todoCommentCreate = (options) => (options.client ?? client).post({
1030
+ security: [{ scheme: "bearer", type: "http" }],
1031
+ url: "/todo/items/{id}/comments",
1032
+ ...options,
1033
+ headers: {
1034
+ "Content-Type": "application/json",
1035
+ ...options.headers
1036
+ }
1037
+ });
985
1038
  var projectList = (options) => (options?.client ?? client).get({
986
1039
  security: [{ scheme: "bearer", type: "http" }],
987
1040
  url: "/todo/projects",
@@ -1020,6 +1073,20 @@ var todoTypeList = (options) => (options.client ?? client).get({
1020
1073
  url: "/todo/types",
1021
1074
  ...options
1022
1075
  });
1076
+ var todoCommentDelete = (options) => (options.client ?? client).delete({
1077
+ security: [{ scheme: "bearer", type: "http" }],
1078
+ url: "/todo/comments/{id}",
1079
+ ...options
1080
+ });
1081
+ var todoCommentUpdate = (options) => (options.client ?? client).patch({
1082
+ security: [{ scheme: "bearer", type: "http" }],
1083
+ url: "/todo/comments/{id}",
1084
+ ...options,
1085
+ headers: {
1086
+ "Content-Type": "application/json",
1087
+ ...options.headers
1088
+ }
1089
+ });
1023
1090
  var todoDelete = (options) => (options.client ?? client).delete({
1024
1091
  security: [{ scheme: "bearer", type: "http" }],
1025
1092
  url: "/todo/items/{id}",
@@ -1048,7 +1115,62 @@ var todoUpdate = (options) => (options.client ?? client).patch({
1048
1115
  import { promises as fs } from "fs";
1049
1116
  import { homedir } from "os";
1050
1117
  import { join } from "path";
1118
+ var LEGACY_ACCOUNT_KEY = "(default)";
1051
1119
  var DEFAULT_DIR = join(homedir(), ".wspc");
1120
+ var V1_CRED_KEYS = [
1121
+ "refresh_token",
1122
+ "access_token",
1123
+ "access_token_expires_at",
1124
+ "api_key",
1125
+ "actor",
1126
+ "agent_label"
1127
+ ];
1128
+ function migrateEnv(raw) {
1129
+ const api_base = typeof raw.api_base === "string" ? raw.api_base : "";
1130
+ const env = { api_base, accounts: {} };
1131
+ if (typeof raw.client_id === "string") env.client_id = raw.client_id;
1132
+ if (raw.accounts && typeof raw.accounts === "object") {
1133
+ env.accounts = raw.accounts;
1134
+ if (typeof raw.current_account === "string") env.current_account = raw.current_account;
1135
+ return env;
1136
+ }
1137
+ const hasCreds = V1_CRED_KEYS.some((k) => raw[k] !== void 0);
1138
+ if (hasCreds) {
1139
+ const creds = { email: LEGACY_ACCOUNT_KEY };
1140
+ for (const k of V1_CRED_KEYS) {
1141
+ if (raw[k] !== void 0) creds[k] = raw[k];
1142
+ }
1143
+ env.accounts[LEGACY_ACCOUNT_KEY] = creds;
1144
+ env.current_account = LEGACY_ACCOUNT_KEY;
1145
+ }
1146
+ return env;
1147
+ }
1148
+ function normalize(parsed) {
1149
+ if (typeof parsed !== "object" || parsed === null) return { envs: {} };
1150
+ const obj = parsed;
1151
+ if (typeof obj.envs !== "object" || obj.envs === null) return { envs: {} };
1152
+ const envs = {};
1153
+ for (const [name, rawEnv] of Object.entries(obj.envs)) {
1154
+ if (typeof rawEnv === "object" && rawEnv !== null) {
1155
+ envs[name] = migrateEnv(rawEnv);
1156
+ }
1157
+ }
1158
+ const out = { schema_version: 2, envs };
1159
+ if (typeof obj.current_env === "string") out.current_env = obj.current_env;
1160
+ return out;
1161
+ }
1162
+ function rekeyLegacyAccount(config, envName, email, userId) {
1163
+ if (email === LEGACY_ACCOUNT_KEY) return false;
1164
+ const env = config.envs[envName];
1165
+ const legacy = env?.accounts?.[LEGACY_ACCOUNT_KEY];
1166
+ if (!env || !legacy) return false;
1167
+ delete env.accounts[LEGACY_ACCOUNT_KEY];
1168
+ if (!env.accounts[email]) {
1169
+ env.accounts[email] = { ...legacy, email, ...userId ? { user_id: userId } : {} };
1170
+ }
1171
+ if (env.current_account === LEGACY_ACCOUNT_KEY) env.current_account = email;
1172
+ return true;
1173
+ }
1052
1174
  var ConfigStore = class {
1053
1175
  configDir;
1054
1176
  configFile;
@@ -1059,11 +1181,7 @@ var ConfigStore = class {
1059
1181
  async read() {
1060
1182
  try {
1061
1183
  const buf = await fs.readFile(this.configFile, "utf8");
1062
- const parsed = JSON.parse(buf);
1063
- if (typeof parsed !== "object" || parsed === null || typeof parsed.envs !== "object") {
1064
- return { envs: {} };
1065
- }
1066
- return parsed;
1184
+ return normalize(JSON.parse(buf));
1067
1185
  } catch (e) {
1068
1186
  if (e.code === "ENOENT") return { envs: {} };
1069
1187
  throw e;
@@ -1088,9 +1206,9 @@ var ConfigStore = class {
1088
1206
  };
1089
1207
 
1090
1208
  // src/version.ts
1091
- var VERSION = "0.0.6";
1092
- var SPEC_SHA = "7418fe42";
1093
- var SPEC_FETCHED_AT = "2026-06-02T09:58:13.195Z";
1209
+ var VERSION = "0.0.8";
1210
+ var SPEC_SHA = "9735a255";
1211
+ var SPEC_FETCHED_AT = "2026-06-08T08:32:23.241Z";
1094
1212
  var API_BASE = "https://api.wspc.ai";
1095
1213
 
1096
1214
  // src/index.ts
@@ -1154,45 +1272,78 @@ function createAuthInterceptor(mode) {
1154
1272
  };
1155
1273
  }
1156
1274
 
1157
- // src/handwritten/auth/load-sdk-client.ts
1158
- async function loadSdkClient(opts = {}) {
1159
- const store = opts.store ?? new ConfigStore();
1160
- const current = await store.currentEnv();
1161
- if (!current) {
1162
- throw new Error("not logged in: run `wspc login` first");
1163
- }
1164
- const env = current.config;
1165
- if (!env.api_key && !(env.access_token && env.refresh_token)) {
1166
- throw new Error("not logged in: run `wspc login` first");
1167
- }
1168
- let interceptor;
1169
- if (env.api_key) {
1170
- interceptor = createAuthInterceptor({ apiKey: env.api_key });
1171
- } else {
1172
- if (!env.client_id) {
1275
+ // src/handwritten/auth/resolve-account.ts
1276
+ var NOT_LOGGED_IN = "not logged in: run `wspc login` first";
1277
+ function resolveAccount(config, opts = {}) {
1278
+ const envName = config.current_env;
1279
+ if (!envName || !config.envs[envName]) throw new Error(NOT_LOGGED_IN);
1280
+ const env = config.envs[envName];
1281
+ const accounts = env.accounts ?? {};
1282
+ const emails = Object.keys(accounts);
1283
+ let email;
1284
+ const override = opts.accountOverride;
1285
+ if (override) {
1286
+ if (!accounts[override]) {
1173
1287
  throw new Error(
1174
- "config has OAuth tokens but no client_id \u2014 run `wspc logout && wspc login` to re-register"
1288
+ `no account '${override}' in env '${envName}'. Run \`wspc account ls\` or \`wspc login\`.`
1175
1289
  );
1176
1290
  }
1177
- interceptor = createAuthInterceptor({
1178
- accessToken: env.access_token,
1179
- refreshToken: env.refresh_token,
1180
- baseUrl: env.api_base,
1181
- clientId: env.client_id,
1182
- onTokenRefresh: async ({ accessToken, refreshToken, expiresAt }) => {
1183
- const cfg = await store.read();
1184
- const e = cfg.envs[current.name];
1185
- if (!e) return;
1186
- e.access_token = accessToken;
1187
- e.refresh_token = refreshToken;
1188
- e.access_token_expires_at = expiresAt;
1189
- await store.write(cfg);
1190
- }
1191
- });
1291
+ email = override;
1292
+ } else if (env.current_account && accounts[env.current_account]) {
1293
+ email = env.current_account;
1294
+ } else if (emails.length === 1) {
1295
+ email = emails[0];
1296
+ } else if (emails.length === 0) {
1297
+ throw new Error(NOT_LOGGED_IN);
1298
+ } else {
1299
+ throw new Error(
1300
+ `multiple accounts in env '${envName}'; specify --account <email> or run \`wspc account switch <email>\`.`
1301
+ );
1302
+ }
1303
+ if (email === void 0) throw new Error(NOT_LOGGED_IN);
1304
+ const creds = accounts[email];
1305
+ if (!creds) throw new Error(NOT_LOGGED_IN);
1306
+ if (!creds.api_key && !(creds.access_token && creds.refresh_token)) {
1307
+ throw new Error(NOT_LOGGED_IN);
1308
+ }
1309
+ return { envName, apiBase: env.api_base, clientId: env.client_id, email, creds };
1310
+ }
1311
+
1312
+ // src/handwritten/auth/load-sdk-client.ts
1313
+ function buildInterceptor(store, resolved) {
1314
+ const { envName, apiBase, clientId, email, creds } = resolved;
1315
+ if (creds.api_key) {
1316
+ return createAuthInterceptor({ apiKey: creds.api_key });
1192
1317
  }
1318
+ if (!clientId) {
1319
+ throw new Error(
1320
+ "config has OAuth tokens but no client_id \u2014 run `wspc logout && wspc login` to re-register"
1321
+ );
1322
+ }
1323
+ return createAuthInterceptor({
1324
+ accessToken: creds.access_token,
1325
+ refreshToken: creds.refresh_token,
1326
+ baseUrl: apiBase,
1327
+ clientId,
1328
+ onTokenRefresh: async ({ accessToken, refreshToken, expiresAt }) => {
1329
+ const cfg = await store.read();
1330
+ const a = cfg.envs[envName]?.accounts?.[email];
1331
+ if (!a) return;
1332
+ a.access_token = accessToken;
1333
+ a.refresh_token = refreshToken;
1334
+ a.access_token_expires_at = expiresAt;
1335
+ await store.write(cfg);
1336
+ }
1337
+ });
1338
+ }
1339
+ async function loadSdkClient(opts = {}) {
1340
+ const store = opts.store ?? new ConfigStore();
1341
+ const config = await store.read();
1342
+ const resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
1343
+ const interceptor = buildInterceptor(store, resolved);
1193
1344
  const rawClient = createClient(
1194
1345
  createConfig({
1195
- baseUrl: env.api_base,
1346
+ baseUrl: resolved.apiBase,
1196
1347
  fetch: ((input, init) => interceptor.execute(new Request(input, init)))
1197
1348
  })
1198
1349
  );
@@ -1200,39 +1351,11 @@ async function loadSdkClient(opts = {}) {
1200
1351
  }
1201
1352
  async function loadAuthedFetch(opts = {}) {
1202
1353
  const store = opts.store ?? new ConfigStore();
1203
- const current = await store.currentEnv();
1204
- if (!current) throw new Error("not logged in: run `wspc login` first");
1205
- const env = current.config;
1206
- if (!env.api_key && !(env.access_token && env.refresh_token)) {
1207
- throw new Error("not logged in: run `wspc login` first");
1208
- }
1209
- let interceptor;
1210
- if (env.api_key) {
1211
- interceptor = createAuthInterceptor({ apiKey: env.api_key });
1212
- } else {
1213
- if (!env.client_id) {
1214
- throw new Error(
1215
- "config has OAuth tokens but no client_id \u2014 run `wspc logout && wspc login` to re-register"
1216
- );
1217
- }
1218
- interceptor = createAuthInterceptor({
1219
- accessToken: env.access_token,
1220
- refreshToken: env.refresh_token,
1221
- baseUrl: env.api_base,
1222
- clientId: env.client_id,
1223
- onTokenRefresh: async ({ accessToken, refreshToken, expiresAt }) => {
1224
- const cfg = await store.read();
1225
- const e = cfg.envs[current.name];
1226
- if (!e) return;
1227
- e.access_token = accessToken;
1228
- e.refresh_token = refreshToken;
1229
- e.access_token_expires_at = expiresAt;
1230
- await store.write(cfg);
1231
- }
1232
- });
1233
- }
1354
+ const config = await store.read();
1355
+ const resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
1356
+ const interceptor = buildInterceptor(store, resolved);
1234
1357
  const authedFetch = (input, init) => interceptor.execute(new Request(input, init));
1235
- return { fetch: authedFetch, baseUrl: env.api_base };
1358
+ return { fetch: authedFetch, baseUrl: resolved.apiBase };
1236
1359
  }
1237
1360
 
1238
1361
  // src/handwritten/output/primitives.ts
@@ -1617,8 +1740,29 @@ function formatCell(value, fmt, colorMap) {
1617
1740
  }
1618
1741
  }
1619
1742
 
1743
+ // src/generated/cli/invite/accept.ts
1744
+ var inviteAcceptCommand = new Command("accept").description("Accept an invite and switch into the inviting organization").argument("<id>", "id").action(async (id, opts) => {
1745
+ const client2 = await loadSdkClient();
1746
+ const result = await inviteAccept({
1747
+ client: client2._rawClient,
1748
+ path: {
1749
+ id
1750
+ }
1751
+ });
1752
+ if (result.error || !result.response?.ok) {
1753
+ process.stderr.write(
1754
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1755
+ `
1756
+ );
1757
+ process.exitCode = 1;
1758
+ return;
1759
+ }
1760
+ render({ kind: "invite_accept", display: { "shape": "object", "fields": ["id", "name", "created_at", "updated_at"] } }, result.data);
1761
+ });
1762
+
1620
1763
  // src/generated/cli/keys/create.ts
1621
- var keyCreateCommand = new Command("create").description("Create a new API key (full value returned once)").option("--label <value>", "label").action(async (opts) => {
1764
+ import { Command as Command2 } from "commander";
1765
+ var keyCreateCommand = new Command2("create").description("Create a new API key (full value returned once)").option("--label <value>", "label").action(async (opts) => {
1622
1766
  const client2 = await loadSdkClient();
1623
1767
  const result = await keyCreate({
1624
1768
  client: client2._rawClient,
@@ -1638,8 +1782,8 @@ var keyCreateCommand = new Command("create").description("Create a new API key (
1638
1782
  });
1639
1783
 
1640
1784
  // src/generated/cli/keys/ls.ts
1641
- import { Command as Command2 } from "commander";
1642
- var keyListCommand = new Command2("ls").description("List active API keys").action(async (opts) => {
1785
+ import { Command as Command3 } from "commander";
1786
+ var keyListCommand = new Command3("ls").description("List active API keys").action(async (opts) => {
1643
1787
  const client2 = await loadSdkClient();
1644
1788
  const result = await keyList({
1645
1789
  client: client2._rawClient
@@ -1655,9 +1799,48 @@ var keyListCommand = new Command2("ls").description("List active API keys").acti
1655
1799
  render({ kind: "key_list", display: { "shape": "list", "dataPath": "keys", "columns": ["id", "label", "last_4", "created_at", "last_used_at"], "format": { "id": "id-short", "created_at": "relative-time", "last_used_at": "relative-time" }, "emptyMessage": "(no API keys)" } }, result.data);
1656
1800
  });
1657
1801
 
1802
+ // src/generated/cli/org/invite.ts
1803
+ import { Command as Command4 } from "commander";
1804
+ var orgInviteCreateCommand = new Command4("invite").description("Invite an email to join the caller's organization").option("--email <value>", "email").action(async (opts) => {
1805
+ const client2 = await loadSdkClient();
1806
+ const result = await orgInviteCreate({
1807
+ client: client2._rawClient,
1808
+ body: {
1809
+ email: opts.email
1810
+ }
1811
+ });
1812
+ if (result.error || !result.response?.ok) {
1813
+ process.stderr.write(
1814
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1815
+ `
1816
+ );
1817
+ process.exitCode = 1;
1818
+ return;
1819
+ }
1820
+ render({ kind: "org_invite_create", display: { "shape": "object", "fields": ["id", "email", "state", "expires_at", "invite_url"] } }, result.data);
1821
+ });
1822
+
1823
+ // src/generated/cli/org/invites.ts
1824
+ import { Command as Command5 } from "commander";
1825
+ var orgInvitesListCommand = new Command5("invites").description("List invites issued by the caller's organization").action(async (opts) => {
1826
+ const client2 = await loadSdkClient();
1827
+ const result = await orgInvitesList({
1828
+ client: client2._rawClient
1829
+ });
1830
+ if (result.error || !result.response?.ok) {
1831
+ process.stderr.write(
1832
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1833
+ `
1834
+ );
1835
+ process.exitCode = 1;
1836
+ return;
1837
+ }
1838
+ render({ kind: "org_invites_list", display: { "shape": "list", "dataPath": "invites", "columns": ["id", "email", "state", "expires_at"], "format": { "id": "id-short", "expires_at": "relative-time" } } }, result.data);
1839
+ });
1840
+
1658
1841
  // src/generated/cli/org/show.ts
1659
- import { Command as Command3 } from "commander";
1660
- var orgGetCommand = new Command3("show").description("Get the authenticated user's organization").action(async (opts) => {
1842
+ import { Command as Command6 } from "commander";
1843
+ var orgGetCommand = new Command6("show").description("Get the authenticated user's organization").action(async (opts) => {
1661
1844
  const client2 = await loadSdkClient();
1662
1845
  const result = await orgGet({
1663
1846
  client: client2._rawClient
@@ -1674,8 +1857,8 @@ var orgGetCommand = new Command3("show").description("Get the authenticated user
1674
1857
  });
1675
1858
 
1676
1859
  // src/generated/cli/org/rename.ts
1677
- import { Command as Command4 } from "commander";
1678
- var orgUpdateCommand = new Command4("rename").description("Update the authenticated user's organization").option("--name <value>", "name").action(async (opts) => {
1860
+ import { Command as Command7 } from "commander";
1861
+ var orgUpdateCommand = new Command7("rename").description("Update the authenticated user's organization").option("--name <value>", "name").action(async (opts) => {
1679
1862
  const client2 = await loadSdkClient();
1680
1863
  const result = await orgUpdate({
1681
1864
  client: client2._rawClient,
@@ -1694,9 +1877,30 @@ var orgUpdateCommand = new Command4("rename").description("Update the authentica
1694
1877
  render({ kind: "org_update", display: { "shape": "object", "fields": ["id", "name", "created_at", "updated_at"], "format": { "id": "id-short", "name": "truncate", "created_at": "relative-time", "updated_at": "relative-time" } } }, result.data);
1695
1878
  });
1696
1879
 
1880
+ // src/generated/cli/invite/show.ts
1881
+ import { Command as Command8 } from "commander";
1882
+ var inviteGetCommand = new Command8("show").description("Get a single invite addressed to the caller").argument("<id>", "id").action(async (id, opts) => {
1883
+ const client2 = await loadSdkClient();
1884
+ const result = await inviteGet({
1885
+ client: client2._rawClient,
1886
+ path: {
1887
+ id
1888
+ }
1889
+ });
1890
+ if (result.error || !result.response?.ok) {
1891
+ process.stderr.write(
1892
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1893
+ `
1894
+ );
1895
+ process.exitCode = 1;
1896
+ return;
1897
+ }
1898
+ render({ kind: "invite_get", display: void 0 }, result.data);
1899
+ });
1900
+
1697
1901
  // src/generated/cli/auth/me.ts
1698
- import { Command as Command5 } from "commander";
1699
- var authMeCommand = new Command5("me").description("Fetch the user identified by the bearer token").action(async (opts) => {
1902
+ import { Command as Command9 } from "commander";
1903
+ var authMeCommand = new Command9("me").description("Fetch the user identified by the bearer token").action(async (opts) => {
1700
1904
  const client2 = await loadSdkClient();
1701
1905
  const result = await authMe({
1702
1906
  client: client2._rawClient
@@ -1712,9 +1916,27 @@ var authMeCommand = new Command5("me").description("Fetch the user identified by
1712
1916
  render({ kind: "auth_me", display: { "shape": "object", "fields": ["user_id", "email", "display_name", "api_key_id"], "format": { "user_id": "id-short", "api_key_id": "id-short" } } }, result.data);
1713
1917
  });
1714
1918
 
1919
+ // src/generated/cli/invites.ts
1920
+ import { Command as Command10 } from "commander";
1921
+ var invitesListCommand = new Command10("invites").description("List invites addressed to the authenticated user's email").action(async (opts) => {
1922
+ const client2 = await loadSdkClient();
1923
+ const result = await invitesList({
1924
+ client: client2._rawClient
1925
+ });
1926
+ if (result.error || !result.response?.ok) {
1927
+ process.stderr.write(
1928
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1929
+ `
1930
+ );
1931
+ process.exitCode = 1;
1932
+ return;
1933
+ }
1934
+ render({ kind: "invites_list", display: { "shape": "list", "dataPath": "invites", "columns": ["id", "org_name", "inviter_email", "state", "expires_at"], "format": { "id": "id-short", "expires_at": "relative-time" } } }, result.data);
1935
+ });
1936
+
1715
1937
  // src/generated/cli/org/members.ts
1716
- import { Command as Command6 } from "commander";
1717
- var orgMembersListCommand = new Command6("members").description("List members of the authenticated user's organization").option("--cursor <value>", "cursor").option("--limit <value>", "limit").action(async (opts) => {
1938
+ import { Command as Command11 } from "commander";
1939
+ var orgMembersListCommand = new Command11("members").description("List members of the authenticated user's organization").option("--cursor <value>", "cursor").option("--limit <value>", "limit").action(async (opts) => {
1718
1940
  const client2 = await loadSdkClient();
1719
1941
  const result = await orgMembersList({
1720
1942
  client: client2._rawClient,
@@ -1734,9 +1956,30 @@ var orgMembersListCommand = new Command6("members").description("List members of
1734
1956
  render({ kind: "org_members_list", display: { "shape": "list", "dataPath": "members", "columns": ["user_id", "email", "display_name", "joined_at"], "format": { "user_id": "id-short", "joined_at": "relative-time" } } }, result.data);
1735
1957
  });
1736
1958
 
1959
+ // src/generated/cli/invite/reject.ts
1960
+ import { Command as Command12 } from "commander";
1961
+ var inviteRejectCommand = new Command12("reject").description("Reject an invite").argument("<id>", "id").action(async (id, opts) => {
1962
+ const client2 = await loadSdkClient();
1963
+ const result = await inviteReject({
1964
+ client: client2._rawClient,
1965
+ path: {
1966
+ id
1967
+ }
1968
+ });
1969
+ if (result.error || !result.response?.ok) {
1970
+ process.stderr.write(
1971
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1972
+ `
1973
+ );
1974
+ process.exitCode = 1;
1975
+ return;
1976
+ }
1977
+ render({ kind: "invite_reject", display: void 0 }, result.data);
1978
+ });
1979
+
1737
1980
  // src/generated/cli/keys/rm.ts
1738
- import { Command as Command7 } from "commander";
1739
- var keyRevokeCommand = new Command7("rm").description("Soft-revoke an API key").argument("<id>", "id").action(async (id, opts) => {
1981
+ import { Command as Command13 } from "commander";
1982
+ var keyRevokeCommand = new Command13("rm").description("Soft-revoke an API key").argument("<id>", "id").action(async (id, opts) => {
1740
1983
  const client2 = await loadSdkClient();
1741
1984
  const result = await keyRevoke({
1742
1985
  client: client2._rawClient,
@@ -1756,8 +1999,8 @@ var keyRevokeCommand = new Command7("rm").description("Soft-revoke an API key").
1756
1999
  });
1757
2000
 
1758
2001
  // src/generated/cli/keys/edit.ts
1759
- import { Command as Command8 } from "commander";
1760
- var keyUpdateCommand = new Command8("edit").description("Update an active API key's label").argument("<id>", "id").option("--label <value>", "label").action(async (id, opts) => {
2002
+ import { Command as Command14 } from "commander";
2003
+ var keyUpdateCommand = new Command14("edit").description("Update an active API key's label").argument("<id>", "id").option("--label <value>", "label").action(async (id, opts) => {
1761
2004
  const client2 = await loadSdkClient();
1762
2005
  const result = await keyUpdate({
1763
2006
  client: client2._rawClient,
@@ -1779,8 +2022,29 @@ var keyUpdateCommand = new Command8("edit").description("Update an active API ke
1779
2022
  render({ kind: "key_update", display: void 0 }, result.data);
1780
2023
  });
1781
2024
 
2025
+ // src/generated/cli/org/invite/revoke.ts
2026
+ import { Command as Command15 } from "commander";
2027
+ var orgInviteRevokeCommand = new Command15("revoke").description("Revoke a pending invite").argument("<id>", "id").action(async (id, opts) => {
2028
+ const client2 = await loadSdkClient();
2029
+ const result = await orgInviteRevoke({
2030
+ client: client2._rawClient,
2031
+ path: {
2032
+ id
2033
+ }
2034
+ });
2035
+ if (result.error || !result.response?.ok) {
2036
+ process.stderr.write(
2037
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
2038
+ `
2039
+ );
2040
+ process.exitCode = 1;
2041
+ return;
2042
+ }
2043
+ render({ kind: "org_invite_revoke", display: void 0 }, result.data);
2044
+ });
2045
+
1782
2046
  // src/generated/cli/event/add.ts
1783
- import { Command as Command9 } from "commander";
2047
+ import { Command as Command16 } from "commander";
1784
2048
 
1785
2049
  // src/handwritten/utils/parse-time.ts
1786
2050
  import * as chrono from "chrono-node";
@@ -1866,7 +2130,7 @@ function parseAttendee(input) {
1866
2130
  }
1867
2131
 
1868
2132
  // src/generated/cli/event/add.ts
1869
- var eventCreateCommand = new Command9("add").description("Schedule a calendar event").argument("<title>", "title").option("--description <value>", "description").option("--start <value>", "start").option("--end <value>", "end").option("-l, --location <value>", "location").option("-u, --url <value>", "url").option("--status <value>", "status").option("--attendee <value>", "attendee", (val, memo) => {
2133
+ var eventCreateCommand = new Command16("add").description("Schedule a calendar event").argument("<title>", "title").option("--description <value>", "description").option("--start <value>", "start").option("--end <value>", "end").option("-l, --location <value>", "location").option("-u, --url <value>", "url").option("--status <value>", "status").option("--attendee <value>", "attendee", (val, memo) => {
1870
2134
  memo.push(val);
1871
2135
  return memo;
1872
2136
  }, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (title, opts) => {
@@ -1915,8 +2179,8 @@ var eventCreateCommand = new Command9("add").description("Schedule a calendar ev
1915
2179
  });
1916
2180
 
1917
2181
  // src/generated/cli/event/ls.ts
1918
- import { Command as Command10 } from "commander";
1919
- var eventListCommand = new Command10("ls").description("List calendar events").option("--q <value>", "q").option("--from <value>", "from").option("--to <value>", "to").option("--end-from <value>", "end_from").option("--end-to <value>", "end_to").option("--cursor <value>", "cursor").option("--limit <value>", "limit").option("--include-deleted <value>", "include_deleted").option("--include-past <value>", "include_past").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (opts) => {
2182
+ import { Command as Command17 } from "commander";
2183
+ var eventListCommand = new Command17("ls").description("List calendar events").option("--q <value>", "q").option("--from <value>", "from").option("--to <value>", "to").option("--end-from <value>", "end_from").option("--end-to <value>", "end_to").option("--cursor <value>", "cursor").option("--limit <value>", "limit").option("--include-deleted <value>", "include_deleted").option("--include-past <value>", "include_past").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (opts) => {
1920
2184
  const zone = resolveTimezone(opts.tz);
1921
2185
  let fromValue;
1922
2186
  if (opts.from !== void 0) {
@@ -1953,8 +2217,8 @@ var eventListCommand = new Command10("ls").description("List calendar events").o
1953
2217
  });
1954
2218
 
1955
2219
  // src/generated/cli/event/rm.ts
1956
- import { Command as Command11 } from "commander";
1957
- var eventDeleteCommand = new Command11("rm").description("Soft-delete a calendar event").argument("<id>", "id").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
2220
+ import { Command as Command18 } from "commander";
2221
+ var eventDeleteCommand = new Command18("rm").description("Soft-delete a calendar event").argument("<id>", "id").option("--expected-version <value>", "expected_version").action(async (id, opts) => {
1958
2222
  const client2 = await loadSdkClient();
1959
2223
  const result = await eventDelete({
1960
2224
  client: client2._rawClient,
@@ -1977,8 +2241,8 @@ var eventDeleteCommand = new Command11("rm").description("Soft-delete a calendar
1977
2241
  });
1978
2242
 
1979
2243
  // src/generated/cli/event/show.ts
1980
- import { Command as Command12 } from "commander";
1981
- var eventGetCommand = new Command12("show").description("Get a calendar event by id").argument("<id>", "id").option("--include-deleted <value>", "include_deleted").action(async (id, opts) => {
2244
+ import { Command as Command19 } from "commander";
2245
+ var eventGetCommand = new Command19("show").description("Get a calendar event by id").argument("<id>", "id").option("--include-deleted <value>", "include_deleted").action(async (id, opts) => {
1982
2246
  const client2 = await loadSdkClient();
1983
2247
  const result = await eventGet({
1984
2248
  client: client2._rawClient,
@@ -2001,8 +2265,8 @@ var eventGetCommand = new Command12("show").description("Get a calendar event by
2001
2265
  });
2002
2266
 
2003
2267
  // src/generated/cli/event/set.ts
2004
- import { Command as Command13 } from "commander";
2005
- var eventUpdateCommand = new Command13("set").description("Update a calendar event").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--title <value>", "title").option("--description <value>", "description").option("--start <value>", "start").option("--end <value>", "end").option("-l, --location <value>", "location").option("-u, --url <value>", "url").option("--status <value>", "status").option("--attendee <value>", "attendee", (val, memo) => {
2268
+ import { Command as Command20 } from "commander";
2269
+ var eventUpdateCommand = new Command20("set").description("Update a calendar event").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--title <value>", "title").option("--description <value>", "description").option("--start <value>", "start").option("--end <value>", "end").option("-l, --location <value>", "location").option("-u, --url <value>", "url").option("--status <value>", "status").option("--attendee <value>", "attendee", (val, memo) => {
2006
2270
  memo.push(val);
2007
2271
  return memo;
2008
2272
  }, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (id, opts) => {
@@ -2055,8 +2319,8 @@ var eventUpdateCommand = new Command13("set").description("Update a calendar eve
2055
2319
  });
2056
2320
 
2057
2321
  // src/generated/cli/event/ics.ts
2058
- import { Command as Command14 } from "commander";
2059
- var eventIcsDownloadCommand = new Command14("ics").description("Download event as `.ics`").argument("<id>", "id").action(async (id, opts) => {
2322
+ import { Command as Command21 } from "commander";
2323
+ var eventIcsDownloadCommand = new Command21("ics").description("Download event as `.ics`").argument("<id>", "id").action(async (id, opts) => {
2060
2324
  const client2 = await loadSdkClient();
2061
2325
  const result = await eventIcsDownload({
2062
2326
  client: client2._rawClient,
@@ -2076,8 +2340,8 @@ var eventIcsDownloadCommand = new Command14("ics").description("Download event a
2076
2340
  });
2077
2341
 
2078
2342
  // src/generated/cli/alias/add.ts
2079
- import { Command as Command15 } from "commander";
2080
- var emailAliasCreateCommand = new Command15("add").description("Create a receiving alias").argument("<email>", "email").action(async (email, opts) => {
2343
+ import { Command as Command22 } from "commander";
2344
+ var emailAliasCreateCommand = new Command22("add").description("Create a receiving alias").argument("<email>", "email").action(async (email, opts) => {
2081
2345
  const client2 = await loadSdkClient();
2082
2346
  const result = await emailAliasCreate({
2083
2347
  client: client2._rawClient,
@@ -2097,8 +2361,8 @@ var emailAliasCreateCommand = new Command15("add").description("Create a receivi
2097
2361
  });
2098
2362
 
2099
2363
  // src/generated/cli/alias/ls.ts
2100
- import { Command as Command16 } from "commander";
2101
- var emailAliasListCommand = new Command16("ls").description("List the caller's aliases").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2364
+ import { Command as Command23 } from "commander";
2365
+ var emailAliasListCommand = new Command23("ls").description("List the caller's aliases").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2102
2366
  const client2 = await loadSdkClient();
2103
2367
  const result = await emailAliasList({
2104
2368
  client: client2._rawClient,
@@ -2118,8 +2382,8 @@ var emailAliasListCommand = new Command16("ls").description("List the caller's a
2118
2382
  });
2119
2383
 
2120
2384
  // src/generated/cli/alias/rm.ts
2121
- import { Command as Command17 } from "commander";
2122
- var emailAliasDeleteCommand = new Command17("rm").description("Soft-delete an alias").argument("<email>", "email").action(async (email, opts) => {
2385
+ import { Command as Command24 } from "commander";
2386
+ var emailAliasDeleteCommand = new Command24("rm").description("Soft-delete an alias").argument("<email>", "email").action(async (email, opts) => {
2123
2387
  const client2 = await loadSdkClient();
2124
2388
  const result = await emailAliasDelete({
2125
2389
  client: client2._rawClient,
@@ -2139,8 +2403,8 @@ var emailAliasDeleteCommand = new Command17("rm").description("Soft-delete an al
2139
2403
  });
2140
2404
 
2141
2405
  // src/generated/cli/email/rm.ts
2142
- import { Command as Command18 } from "commander";
2143
- var emailDeleteCommand = new Command18("rm").description("Soft-delete inbound emails").argument("<id...>", "id").action(async (id, opts) => {
2406
+ import { Command as Command25 } from "commander";
2407
+ var emailDeleteCommand = new Command25("rm").description("Soft-delete inbound emails").argument("<id...>", "id").action(async (id, opts) => {
2144
2408
  const idRaw = id;
2145
2409
  const ids = idRaw.length > 0 ? idRaw : void 0;
2146
2410
  const client2 = await loadSdkClient();
@@ -2162,8 +2426,8 @@ var emailDeleteCommand = new Command18("rm").description("Soft-delete inbound em
2162
2426
  });
2163
2427
 
2164
2428
  // src/generated/cli/email/show.ts
2165
- import { Command as Command19 } from "commander";
2166
- var emailGetCommand = new Command19("show").description("Get an inbound email by id").argument("<id>", "id").option("--include-html <value>", "include_html").option("--include-deleted <value>", "include_deleted").action(async (id, opts) => {
2429
+ import { Command as Command26 } from "commander";
2430
+ var emailGetCommand = new Command26("show").description("Get an inbound email by id").argument("<id>", "id").option("--include-html <value>", "include_html").option("--include-deleted <value>", "include_deleted").action(async (id, opts) => {
2167
2431
  const client2 = await loadSdkClient();
2168
2432
  const result = await emailGet({
2169
2433
  client: client2._rawClient,
@@ -2187,8 +2451,8 @@ var emailGetCommand = new Command19("show").description("Get an inbound email by
2187
2451
  });
2188
2452
 
2189
2453
  // src/generated/cli/email/ls.ts
2190
- import { Command as Command20 } from "commander";
2191
- var emailListCommand = new Command20("ls").description("List inbound emails").option("--limit <value>", "limit").option("--alias-email <value>", "alias_email").option("--unread-only <value>", "unread_only").option("--since <value>", "since").option("--cursor <value>", "cursor").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2454
+ import { Command as Command27 } from "commander";
2455
+ var emailListCommand = new Command27("ls").description("List inbound emails").option("--limit <value>", "limit").option("--alias-email <value>", "alias_email").option("--unread-only <value>", "unread_only").option("--since <value>", "since").option("--cursor <value>", "cursor").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2192
2456
  const client2 = await loadSdkClient();
2193
2457
  const result = await emailList({
2194
2458
  client: client2._rawClient,
@@ -2213,8 +2477,8 @@ var emailListCommand = new Command20("ls").description("List inbound emails").op
2213
2477
  });
2214
2478
 
2215
2479
  // src/generated/cli/email/read.ts
2216
- import { Command as Command21 } from "commander";
2217
- var emailMarkReadCommand = new Command21("read").description("Mark inbound emails as read").argument("<id...>", "id").action(async (id, opts) => {
2480
+ import { Command as Command28 } from "commander";
2481
+ var emailMarkReadCommand = new Command28("read").description("Mark inbound emails as read").argument("<id...>", "id").action(async (id, opts) => {
2218
2482
  const idRaw = id;
2219
2483
  const ids = idRaw.length > 0 ? idRaw : void 0;
2220
2484
  const client2 = await loadSdkClient();
@@ -2236,8 +2500,8 @@ var emailMarkReadCommand = new Command21("read").description("Mark inbound email
2236
2500
  });
2237
2501
 
2238
2502
  // src/generated/cli/email/unread.ts
2239
- import { Command as Command22 } from "commander";
2240
- var emailMarkUnreadCommand = new Command22("unread").description("Mark inbound emails as unread").argument("<id...>", "id").action(async (id, opts) => {
2503
+ import { Command as Command29 } from "commander";
2504
+ var emailMarkUnreadCommand = new Command29("unread").description("Mark inbound emails as unread").argument("<id...>", "id").action(async (id, opts) => {
2241
2505
  const idRaw = id;
2242
2506
  const ids = idRaw.length > 0 ? idRaw : void 0;
2243
2507
  const client2 = await loadSdkClient();
@@ -2259,8 +2523,8 @@ var emailMarkUnreadCommand = new Command22("unread").description("Mark inbound e
2259
2523
  });
2260
2524
 
2261
2525
  // src/generated/cli/push/config/rm.ts
2262
- import { Command as Command23 } from "commander";
2263
- var pushConfigDeleteCommand = new Command23("rm").description("Remove a push transport").argument("<transport>", "transport").action(async (transport, opts) => {
2526
+ import { Command as Command30 } from "commander";
2527
+ var pushConfigDeleteCommand = new Command30("rm").description("Remove a push transport").argument("<transport>", "transport").action(async (transport, opts) => {
2264
2528
  const client2 = await loadSdkClient();
2265
2529
  const result = await pushConfigDelete({
2266
2530
  client: client2._rawClient,
@@ -2280,8 +2544,8 @@ var pushConfigDeleteCommand = new Command23("rm").description("Remove a push tra
2280
2544
  });
2281
2545
 
2282
2546
  // src/generated/cli/push/config/set.ts
2283
- import { Command as Command24 } from "commander";
2284
- var pushConfigSetCommand = new Command24("set").description("Register or update a push transport").option("--transport <value>", "transport").option("--target-bot-username <value>", "target_bot_username").action(async (opts) => {
2547
+ import { Command as Command31 } from "commander";
2548
+ var pushConfigSetCommand = new Command31("set").description("Register or update a push transport").option("--transport <value>", "transport").option("--target-bot-username <value>", "target_bot_username").action(async (opts) => {
2285
2549
  const client2 = await loadSdkClient();
2286
2550
  const result = await pushConfigSet({
2287
2551
  client: client2._rawClient,
@@ -2304,8 +2568,8 @@ var pushConfigSetCommand = new Command24("set").description("Register or update
2304
2568
  });
2305
2569
 
2306
2570
  // src/generated/cli/push/config/show.ts
2307
- import { Command as Command25 } from "commander";
2308
- var pushConfigGetCommand = new Command25("show").description("List the caller's push transports").action(async (opts) => {
2571
+ import { Command as Command32 } from "commander";
2572
+ var pushConfigGetCommand = new Command32("show").description("List the caller's push transports").action(async (opts) => {
2309
2573
  const client2 = await loadSdkClient();
2310
2574
  const result = await pushConfigGet({
2311
2575
  client: client2._rawClient
@@ -2322,8 +2586,8 @@ var pushConfigGetCommand = new Command25("show").description("List the caller's
2322
2586
  });
2323
2587
 
2324
2588
  // src/generated/cli/push/test.ts
2325
- import { Command as Command26 } from "commander";
2326
- var pushTestCommand = new Command26("test").description("Send a test push notification").option("--transport <value>", "transport").action(async (opts) => {
2589
+ import { Command as Command33 } from "commander";
2590
+ var pushTestCommand = new Command33("test").description("Send a test push notification").option("--transport <value>", "transport").action(async (opts) => {
2327
2591
  const client2 = await loadSdkClient();
2328
2592
  const result = await pushTest({
2329
2593
  client: client2._rawClient,
@@ -2345,9 +2609,58 @@ var pushTestCommand = new Command26("test").description("Send a test push notifi
2345
2609
  }
2346
2610
  });
2347
2611
 
2612
+ // src/generated/cli/todo/comment/add.ts
2613
+ import { Command as Command34 } from "commander";
2614
+ var todoCommentCreateCommand = new Command34("add").description("Add a comment to a todo").argument("<id>", "id").argument("<content>", "content").action(async (id, content, opts) => {
2615
+ const client2 = await loadSdkClient();
2616
+ const result = await todoCommentCreate({
2617
+ client: client2._rawClient,
2618
+ path: {
2619
+ id
2620
+ },
2621
+ body: {
2622
+ content
2623
+ }
2624
+ });
2625
+ if (result.error || !result.response?.ok) {
2626
+ process.stderr.write(
2627
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
2628
+ `
2629
+ );
2630
+ process.exitCode = 1;
2631
+ return;
2632
+ }
2633
+ render({ kind: "todo_comment_create", display: { "shape": "object", "format": { "id": "id-short", "todo_id": "id-short", "user_id": "id-short", "content": "truncate", "created_at": "relative-time", "updated_at": "relative-time", "deleted_at": "relative-time" } } }, result.data);
2634
+ });
2635
+
2636
+ // src/generated/cli/todo/comment/ls.ts
2637
+ import { Command as Command35 } from "commander";
2638
+ var todoCommentListCommand = new Command35("ls").description("List comments on a todo").argument("<id>", "id").option("--order <value>", "order").option("--include-deleted <value>", "include_deleted").action(async (id, opts) => {
2639
+ const client2 = await loadSdkClient();
2640
+ const result = await todoCommentList({
2641
+ client: client2._rawClient,
2642
+ path: {
2643
+ id
2644
+ },
2645
+ query: {
2646
+ order: opts.order,
2647
+ include_deleted: opts.includeDeleted
2648
+ }
2649
+ });
2650
+ if (result.error || !result.response?.ok) {
2651
+ process.stderr.write(
2652
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
2653
+ `
2654
+ );
2655
+ process.exitCode = 1;
2656
+ return;
2657
+ }
2658
+ render({ kind: "todo_comment_list", display: { "shape": "list", "columns": ["id", "content", "created_at"], "format": { "id": "id-short", "content": "truncate", "created_at": "relative-time" }, "emptyMessage": "no comments" } }, result.data);
2659
+ });
2660
+
2348
2661
  // src/generated/cli/todo/project/add.ts
2349
- import { Command as Command27 } from "commander";
2350
- var projectCreateCommand = new Command27("add").description("Create a project").argument("<name>", "name").option("--default-todo-type-id <value>", "default_todo_type_id").action(async (name, opts) => {
2662
+ import { Command as Command36 } from "commander";
2663
+ var projectCreateCommand = new Command36("add").description("Create a project").argument("<name>", "name").option("--default-todo-type-id <value>", "default_todo_type_id").action(async (name, opts) => {
2351
2664
  const client2 = await loadSdkClient();
2352
2665
  const result = await projectCreate({
2353
2666
  client: client2._rawClient,
@@ -2368,8 +2681,8 @@ var projectCreateCommand = new Command27("add").description("Create a project").
2368
2681
  });
2369
2682
 
2370
2683
  // src/generated/cli/todo/project/ls.ts
2371
- import { Command as Command28 } from "commander";
2372
- var projectListCommand = new Command28("ls").description("List projects").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2684
+ import { Command as Command37 } from "commander";
2685
+ var projectListCommand = new Command37("ls").description("List projects").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2373
2686
  const client2 = await loadSdkClient();
2374
2687
  const result = await projectList({
2375
2688
  client: client2._rawClient,
@@ -2389,8 +2702,8 @@ var projectListCommand = new Command28("ls").description("List projects").option
2389
2702
  });
2390
2703
 
2391
2704
  // src/generated/cli/todo/rule/ls.ts
2392
- import { Command as Command29 } from "commander";
2393
- var recurrenceRuleListCommand = new Command29("ls").description("List recurring todo rules").option("--project-id <value>", "project_id").option("--user-id <value>", "user_id").action(async (opts) => {
2705
+ import { Command as Command38 } from "commander";
2706
+ var recurrenceRuleListCommand = new Command38("ls").description("List recurring todo rules").option("--project-id <value>", "project_id").option("--user-id <value>", "user_id").action(async (opts) => {
2394
2707
  const client2 = await loadSdkClient();
2395
2708
  const result = await recurrenceRuleList({
2396
2709
  client: client2._rawClient,
@@ -2411,8 +2724,8 @@ var recurrenceRuleListCommand = new Command29("ls").description("List recurring
2411
2724
  });
2412
2725
 
2413
2726
  // src/generated/cli/todo/add.ts
2414
- import { Command as Command30 } from "commander";
2415
- var todoCreateCommand = new Command30("add").description("Create a todo").argument("<title>", "title").option("-p, --project <value>", "project_id").option("--description <value>", "description").option("--parent-id <value>", "parent_id").option("--status <value>", "status").option("--due-at <value>", "due_at").option("--type-id <value>", "type_id").option("--custom-fields <value>", "custom_fields").action(async (title, opts) => {
2727
+ import { Command as Command39 } from "commander";
2728
+ var todoCreateCommand = new Command39("add").description("Create a todo").argument("<title>", "title").option("-p, --project <value>", "project_id").option("--description <value>", "description").option("--parent-id <value>", "parent_id").option("--status <value>", "status").option("--due-at <value>", "due_at").option("--type-id <value>", "type_id").option("--custom-fields <value>", "custom_fields").action(async (title, opts) => {
2416
2729
  const client2 = await loadSdkClient();
2417
2730
  const result = await todoCreate({
2418
2731
  client: client2._rawClient,
@@ -2439,8 +2752,8 @@ var todoCreateCommand = new Command30("add").description("Create a todo").argume
2439
2752
  });
2440
2753
 
2441
2754
  // src/generated/cli/todo/ls.ts
2442
- import { Command as Command31 } from "commander";
2443
- var todoListCommand = new Command31("ls").description("List todos with filters").option("-p, --project <value>", "project_id").option("--user-id <value>", "user_id").option("--parent-id <value>", "parent_id").option("-s, --status <value>", "status").option("--include-deleted <value>", "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").action(async (opts) => {
2755
+ import { Command as Command40 } from "commander";
2756
+ var todoListCommand = new Command40("ls").description("List todos with filters").option("-p, --project <value>", "project_id").option("--user-id <value>", "user_id").option("--parent-id <value>", "parent_id").option("-s, --status <value>", "status").option("--include-deleted <value>", "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").action(async (opts) => {
2444
2757
  const client2 = await loadSdkClient();
2445
2758
  const result = await todoList({
2446
2759
  client: client2._rawClient,
@@ -2471,8 +2784,8 @@ var todoListCommand = new Command31("ls").description("List todos with filters")
2471
2784
  });
2472
2785
 
2473
2786
  // src/generated/cli/todo/type/ls.ts
2474
- import { Command as Command32 } from "commander";
2475
- var todoTypeListCommand = new Command32("ls").description("List todo types").option("--project-id <value>", "project_id").option("--user-id <value>", "user_id").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2787
+ import { Command as Command41 } from "commander";
2788
+ var todoTypeListCommand = new Command41("ls").description("List todo types").option("--project-id <value>", "project_id").option("--user-id <value>", "user_id").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2476
2789
  const client2 = await loadSdkClient();
2477
2790
  const result = await todoTypeList({
2478
2791
  client: client2._rawClient,
@@ -2493,9 +2806,54 @@ var todoTypeListCommand = new Command32("ls").description("List todo types").opt
2493
2806
  render({ kind: "todo_type_list", display: { "shape": "list", "columns": ["id", "label"], "format": { "id": "id-short", "label": "truncate" }, "emptyMessage": "no todo types" } }, result.data);
2494
2807
  });
2495
2808
 
2809
+ // src/generated/cli/todo/comment/rm.ts
2810
+ import { Command as Command42 } from "commander";
2811
+ var todoCommentDeleteCommand = new Command42("rm").description("Soft-delete a comment").argument("<id>", "id").action(async (id, opts) => {
2812
+ const client2 = await loadSdkClient();
2813
+ const result = await todoCommentDelete({
2814
+ client: client2._rawClient,
2815
+ path: {
2816
+ id
2817
+ }
2818
+ });
2819
+ if (result.error || !result.response?.ok) {
2820
+ process.stderr.write(
2821
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
2822
+ `
2823
+ );
2824
+ process.exitCode = 1;
2825
+ return;
2826
+ }
2827
+ render({ kind: "todo_comment_delete", display: { "shape": "object", "format": { "id": "id-short", "todo_id": "id-short", "user_id": "id-short", "content": "truncate", "created_at": "relative-time", "updated_at": "relative-time", "deleted_at": "relative-time" } } }, result.data);
2828
+ });
2829
+
2830
+ // src/generated/cli/todo/comment/edit.ts
2831
+ import { Command as Command43 } from "commander";
2832
+ var todoCommentUpdateCommand = new Command43("edit").description("Edit a comment").argument("<id>", "id").argument("<content>", "content").action(async (id, content, opts) => {
2833
+ const client2 = await loadSdkClient();
2834
+ const result = await todoCommentUpdate({
2835
+ client: client2._rawClient,
2836
+ path: {
2837
+ id
2838
+ },
2839
+ body: {
2840
+ content
2841
+ }
2842
+ });
2843
+ if (result.error || !result.response?.ok) {
2844
+ process.stderr.write(
2845
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
2846
+ `
2847
+ );
2848
+ process.exitCode = 1;
2849
+ return;
2850
+ }
2851
+ render({ kind: "todo_comment_update", display: { "shape": "object", "format": { "id": "id-short", "todo_id": "id-short", "user_id": "id-short", "content": "truncate", "created_at": "relative-time", "updated_at": "relative-time", "deleted_at": "relative-time" } } }, result.data);
2852
+ });
2853
+
2496
2854
  // src/generated/cli/todo/rm.ts
2497
- import { Command as Command33 } from "commander";
2498
- var todoDeleteCommand = new Command33("rm").description("Soft-delete a todo").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--cascade <value>", "cascade").action(async (id, opts) => {
2855
+ import { Command as Command44 } from "commander";
2856
+ var todoDeleteCommand = new Command44("rm").description("Soft-delete a todo").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--cascade <value>", "cascade").action(async (id, opts) => {
2499
2857
  const client2 = await loadSdkClient();
2500
2858
  const result = await todoDelete({
2501
2859
  client: client2._rawClient,
@@ -2519,8 +2877,8 @@ var todoDeleteCommand = new Command33("rm").description("Soft-delete a todo").ar
2519
2877
  });
2520
2878
 
2521
2879
  // src/generated/cli/todo/show.ts
2522
- import { Command as Command34 } from "commander";
2523
- var todoGetCommand = new Command34("show").description("Get a todo by id").argument("<id>", "id").option("--include-deleted <value>", "include_deleted").option("--include-orphan-fields <value>", "include_orphan_fields").action(async (id, opts) => {
2880
+ import { Command as Command45 } from "commander";
2881
+ var todoGetCommand = new Command45("show").description("Get a todo by id").argument("<id>", "id").option("--include-deleted <value>", "include_deleted").option("--include-orphan-fields <value>", "include_orphan_fields").action(async (id, opts) => {
2524
2882
  const client2 = await loadSdkClient();
2525
2883
  const result = await todoGet({
2526
2884
  client: client2._rawClient,
@@ -2544,8 +2902,8 @@ var todoGetCommand = new Command34("show").description("Get a todo by id").argum
2544
2902
  });
2545
2903
 
2546
2904
  // src/generated/cli/todo/update.ts
2547
- import { Command as Command35 } from "commander";
2548
- var todoUpdateCommand = new Command35("update").description("Update a todo").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--title <value>", "title").option("--description <value>", "description").option("--parent-id <value>", "parent_id").option("--status <value>", "status").option("--due-at <value>", "due_at").option("--type-id <value>", "type_id").option("--custom-fields <value>", "custom_fields").option("--user-id <value>", "user_id").action(async (id, opts) => {
2905
+ import { Command as Command46 } from "commander";
2906
+ var todoUpdateCommand = new Command46("update").description("Update a todo").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--title <value>", "title").option("--description <value>", "description").option("--parent-id <value>", "parent_id").option("--status <value>", "status").option("--due-at <value>", "due_at").option("--type-id <value>", "type_id").option("--custom-fields <value>", "custom_fields").option("--user-id <value>", "user_id").action(async (id, opts) => {
2549
2907
  const client2 = await loadSdkClient();
2550
2908
  const result = await todoUpdate({
2551
2909
  client: client2._rawClient,
@@ -2577,17 +2935,26 @@ var todoUpdateCommand = new Command35("update").description("Update a todo").arg
2577
2935
 
2578
2936
  // src/generated/cli/index.ts
2579
2937
  function registerGeneratedCommands(root) {
2938
+ const root_invite = root.command("invite").description("invite commands");
2939
+ root_invite.addCommand(inviteAcceptCommand);
2940
+ root_invite.addCommand(inviteGetCommand);
2941
+ root_invite.addCommand(inviteRejectCommand);
2580
2942
  const root_keys = root.command("keys").description("keys commands");
2581
2943
  root_keys.addCommand(keyCreateCommand);
2582
2944
  root_keys.addCommand(keyListCommand);
2583
2945
  root_keys.addCommand(keyRevokeCommand);
2584
2946
  root_keys.addCommand(keyUpdateCommand);
2585
2947
  const root_org = root.command("org").description("org commands");
2948
+ const root_org_invite = root_org.command("invite").description("invite commands");
2949
+ root_org_invite.addCommand(orgInviteCreateCommand);
2950
+ root_org_invite.addCommand(orgInviteRevokeCommand);
2951
+ root_org.addCommand(orgInvitesListCommand);
2586
2952
  root_org.addCommand(orgGetCommand);
2587
2953
  root_org.addCommand(orgUpdateCommand);
2588
2954
  root_org.addCommand(orgMembersListCommand);
2589
2955
  const root_auth = root.command("auth").description("auth commands");
2590
2956
  root_auth.addCommand(authMeCommand);
2957
+ root.addCommand(invitesListCommand);
2591
2958
  const root_event = root.command("event").description("event commands");
2592
2959
  root_event.addCommand(eventCreateCommand);
2593
2960
  root_event.addCommand(eventListCommand);
@@ -2612,6 +2979,11 @@ function registerGeneratedCommands(root) {
2612
2979
  root_push_config.addCommand(pushConfigGetCommand);
2613
2980
  root_push.addCommand(pushTestCommand);
2614
2981
  const root_todo = root.command("todo").description("todo commands");
2982
+ const root_todo_comment = root_todo.command("comment").description("comment commands");
2983
+ root_todo_comment.addCommand(todoCommentCreateCommand);
2984
+ root_todo_comment.addCommand(todoCommentListCommand);
2985
+ root_todo_comment.addCommand(todoCommentDeleteCommand);
2986
+ root_todo_comment.addCommand(todoCommentUpdateCommand);
2615
2987
  const root_todo_project = root_todo.command("project").description("project commands");
2616
2988
  root_todo_project.addCommand(projectCreateCommand);
2617
2989
  root_todo_project.addCommand(projectListCommand);
@@ -2627,7 +2999,7 @@ function registerGeneratedCommands(root) {
2627
2999
  }
2628
3000
 
2629
3001
  // src/handwritten/commands/login.ts
2630
- import { Command as Command36 } from "commander";
3002
+ import { Command as Command47 } from "commander";
2631
3003
 
2632
3004
  // src/handwritten/auth/device-flow.ts
2633
3005
  var DEFAULT_SLEEP = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -2708,23 +3080,62 @@ async function ensureClientId(opts) {
2708
3080
  const body = await res.json();
2709
3081
  if (!body.client_id) throw new Error("client_registration_failed: missing client_id in response");
2710
3082
  const fresh = await opts.store.read();
2711
- const env = fresh.envs[opts.envName] ?? { api_base: opts.baseUrl };
3083
+ const env = fresh.envs[opts.envName] ?? { api_base: opts.baseUrl, accounts: {} };
2712
3084
  env.client_id = body.client_id;
2713
3085
  fresh.envs[opts.envName] = env;
2714
3086
  await opts.store.write(fresh);
2715
3087
  return body.client_id;
2716
3088
  }
2717
3089
 
3090
+ // src/handwritten/auth/fetch-me.ts
3091
+ async function fetchMe(opts) {
3092
+ const f = opts.fetchImpl ?? fetch;
3093
+ const res = await f(`${opts.baseUrl}/auth/me`, {
3094
+ headers: { authorization: `Bearer ${opts.token}` }
3095
+ });
3096
+ if (!res.ok) throw new Error(`auth_me_failed: HTTP ${res.status}`);
3097
+ const body = await res.json().catch(() => ({}));
3098
+ if (!body.user_id || !body.email) {
3099
+ throw new Error("auth_me_failed: missing user_id/email in response");
3100
+ }
3101
+ return { user_id: body.user_id, email: body.email };
3102
+ }
3103
+
2718
3104
  // src/handwritten/auth/login.ts
3105
+ function getOrCreateEnv(c, envName, apiBase) {
3106
+ const existing = c.envs[envName];
3107
+ if (existing) {
3108
+ existing.api_base = apiBase;
3109
+ existing.accounts ??= {};
3110
+ return existing;
3111
+ }
3112
+ const fresh = { api_base: apiBase, accounts: {} };
3113
+ c.envs[envName] = fresh;
3114
+ return fresh;
3115
+ }
2719
3116
  async function runLogin(opts) {
2720
3117
  const envName = opts.envName ?? "prod";
2721
3118
  const now = opts.now ?? Date.now;
2722
- const c = await opts.store.read();
3119
+ const me = opts.fetchMe ?? ((o) => fetchMe(o));
2723
3120
  if (opts.apiKey) {
2724
- c.current_env = envName;
2725
- c.envs[envName] = { ...c.envs[envName] ?? {}, api_base: opts.baseUrl, api_key: opts.apiKey };
2726
- await opts.store.write(c);
2727
- opts.output.write(`\u2713 logged in (api key) \u2192 env "${envName}"`);
3121
+ const who2 = await me({ baseUrl: opts.baseUrl, token: opts.apiKey });
3122
+ const c2 = await opts.store.read();
3123
+ const env2 = getOrCreateEnv(c2, envName, opts.baseUrl);
3124
+ const prev2 = env2.accounts[who2.email] ?? { email: who2.email };
3125
+ const acct2 = env2.accounts[who2.email] = {
3126
+ ...prev2,
3127
+ email: who2.email,
3128
+ user_id: who2.user_id,
3129
+ api_key: opts.apiKey
3130
+ };
3131
+ delete acct2.refresh_token;
3132
+ delete acct2.access_token;
3133
+ delete acct2.access_token_expires_at;
3134
+ env2.current_account = who2.email;
3135
+ if (who2.email !== LEGACY_ACCOUNT_KEY) delete env2.accounts[LEGACY_ACCOUNT_KEY];
3136
+ c2.current_env = envName;
3137
+ await opts.store.write(c2);
3138
+ opts.output.write(`\u2713 logged in (api key) as ${who2.email} \u2192 env "${envName}"`);
2728
3139
  return;
2729
3140
  }
2730
3141
  const ensureClient = opts.ensureClient ?? ((env2) => ensureClientId({ store: opts.store, envName: env2, baseUrl: opts.baseUrl }));
@@ -2745,24 +3156,29 @@ async function runLogin(opts) {
2745
3156
  `);
2746
3157
  }
2747
3158
  });
2748
- const cFinal = await opts.store.read();
2749
- cFinal.current_env = envName;
2750
- cFinal.envs[envName] = {
2751
- ...cFinal.envs[envName] ?? {},
2752
- api_base: opts.baseUrl,
3159
+ const who = await me({ baseUrl: opts.baseUrl, token: result.access_token });
3160
+ const c = await opts.store.read();
3161
+ const env = getOrCreateEnv(c, envName, opts.baseUrl);
3162
+ const prev = env.accounts[who.email] ?? { email: who.email };
3163
+ const acct = env.accounts[who.email] = {
3164
+ ...prev,
3165
+ email: who.email,
3166
+ user_id: who.user_id,
2753
3167
  refresh_token: result.refresh_token,
2754
3168
  access_token: result.access_token,
2755
3169
  access_token_expires_at: now() + result.expires_in * 1e3
2756
3170
  };
2757
- const env = cFinal.envs[envName];
2758
- if (env && "api_key" in env) delete env.api_key;
2759
- await opts.store.write(cFinal);
2760
- opts.output.writeJson({ event: "login_success" });
2761
- opts.output.write(`\u2713 logged in \u2192 env "${envName}"`);
3171
+ delete acct.api_key;
3172
+ env.current_account = who.email;
3173
+ if (who.email !== LEGACY_ACCOUNT_KEY) delete env.accounts[LEGACY_ACCOUNT_KEY];
3174
+ c.current_env = envName;
3175
+ await opts.store.write(c);
3176
+ opts.output.writeJson({ event: "login_success", email: who.email });
3177
+ opts.output.write(`\u2713 logged in as ${who.email} \u2192 env "${envName}"`);
2762
3178
  }
2763
3179
 
2764
3180
  // src/handwritten/commands/login.ts
2765
- var loginCommand = new Command36("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("--json", "Emit machine-readable events to stdout").action(async (opts) => {
3181
+ var loginCommand = new Command47("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("--json", "Emit machine-readable events to stdout").action(async (opts) => {
2766
3182
  const store = new ConfigStore();
2767
3183
  const output = opts.json ? { write: () => {
2768
3184
  }, writeJson: (e) => process.stdout.write(JSON.stringify(e) + "\n") } : {
@@ -2779,51 +3195,61 @@ var loginCommand = new Command36("login").description("Log in via OAuth device f
2779
3195
  });
2780
3196
 
2781
3197
  // src/handwritten/commands/logout.ts
2782
- import { Command as Command37 } from "commander";
3198
+ import { Command as Command48 } from "commander";
2783
3199
 
2784
3200
  // src/handwritten/auth/logout.ts
2785
3201
  async function runLogout(opts) {
2786
- const envName = opts.envName;
2787
3202
  const c = await opts.store.read();
2788
- const targetEnv = envName ?? c.current_env;
2789
- if (!targetEnv || !c.envs[targetEnv]) return;
2790
- const env = c.envs[targetEnv];
2791
- delete env.refresh_token;
2792
- delete env.access_token;
2793
- delete env.access_token_expires_at;
2794
- delete env.api_key;
3203
+ const envName = opts.envName ?? c.current_env;
3204
+ if (!envName || !c.envs[envName]) return { removed: [] };
3205
+ const env = c.envs[envName];
3206
+ env.accounts ??= {};
3207
+ if (opts.all) {
3208
+ const removed = Object.keys(env.accounts);
3209
+ env.accounts = {};
3210
+ env.current_account = void 0;
3211
+ await opts.store.write(c);
3212
+ return { removed };
3213
+ }
3214
+ const target = opts.email ?? env.current_account ?? (Object.keys(env.accounts).length === 1 ? Object.keys(env.accounts)[0] : void 0);
3215
+ if (!target || !env.accounts[target]) return { removed: [] };
3216
+ delete env.accounts[target];
3217
+ if (env.current_account === target) {
3218
+ const remaining = Object.keys(env.accounts);
3219
+ env.current_account = remaining.length === 1 ? remaining[0] : void 0;
3220
+ }
2795
3221
  await opts.store.write(c);
3222
+ return { removed: [target], newActive: env.current_account };
2796
3223
  }
2797
3224
 
2798
3225
  // src/handwritten/commands/logout.ts
2799
- var logoutCommand = new Command37("logout").description("Clear stored credentials for the current environment").action(async () => {
2800
- await runLogout({ store: new ConfigStore() });
2801
- process.stdout.write("\u2713 logged out\n");
3226
+ var logoutCommand = new Command48("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) => {
3227
+ const res = await runLogout({ store: new ConfigStore(), email, all: opts.all });
3228
+ if (res.removed.length === 0) {
3229
+ process.stdout.write("nothing to log out\n");
3230
+ return;
3231
+ }
3232
+ process.stdout.write(`\u2713 logged out: ${res.removed.join(", ")}
3233
+ `);
3234
+ if (res.newActive) process.stdout.write(`active account is now ${res.newActive}
3235
+ `);
2802
3236
  });
2803
3237
 
2804
3238
  // src/handwritten/commands/whoami.ts
2805
- import { Command as Command38 } from "commander";
3239
+ import { Command as Command49 } from "commander";
2806
3240
  var ENV_DISPLAY = {
2807
3241
  shape: "object",
2808
- fields: ["name", "api_base", "actor", "agent_label"]
3242
+ fields: ["name", "api_base", "account", "actor", "agent_label"]
2809
3243
  };
2810
3244
  var USER_DISPLAY = {
2811
3245
  shape: "object",
2812
3246
  fields: ["user_id", "email", "display_name", "api_key_id"],
2813
- format: {
2814
- user_id: "id-short",
2815
- api_key_id: "id-short"
2816
- }
3247
+ format: { user_id: "id-short", api_key_id: "id-short" }
2817
3248
  };
2818
3249
  var ORG_DISPLAY = {
2819
3250
  shape: "object",
2820
3251
  fields: ["id", "name", "created_at", "updated_at"],
2821
- format: {
2822
- id: "id-short",
2823
- name: "truncate",
2824
- created_at: "relative-time",
2825
- updated_at: "relative-time"
2826
- }
3252
+ format: { id: "id-short", name: "truncate", created_at: "relative-time", updated_at: "relative-time" }
2827
3253
  };
2828
3254
  registerRenderer("whoami", (data) => {
2829
3255
  const d = data;
@@ -2836,15 +3262,19 @@ registerRenderer("whoami", (data) => {
2836
3262
  renderObject(d.org, ORG_DISPLAY);
2837
3263
  }
2838
3264
  });
2839
- var whoamiCommand = new Command38("whoami").description("Show the active env, signed-in user, and organization").action(async () => {
2840
- const store = new ConfigStore();
2841
- const current = await store.currentEnv();
2842
- if (!current) {
2843
- printLoggedOut();
2844
- return;
3265
+ async function backfillActiveEmail(store, envName, email, userId) {
3266
+ const cfg = await store.read();
3267
+ if (rekeyLegacyAccount(cfg, envName, email, userId)) {
3268
+ await store.write(cfg);
2845
3269
  }
3270
+ }
3271
+ var whoamiCommand = new Command49("whoami").description("Show the active env, signed-in account, and organization").action(async () => {
3272
+ const store = new ConfigStore();
3273
+ const config = await store.read();
3274
+ let resolved;
2846
3275
  let sdkClient;
2847
3276
  try {
3277
+ resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
2848
3278
  sdkClient = await loadSdkClient({ store });
2849
3279
  } catch {
2850
3280
  printLoggedOut();
@@ -2873,16 +3303,17 @@ var whoamiCommand = new Command38("whoami").description("Show the active env, si
2873
3303
  }
2874
3304
  throw e;
2875
3305
  }
3306
+ if (typeof user.email === "string") {
3307
+ await backfillActiveEmail(store, resolved.envName, user.email, user.user_id);
3308
+ }
2876
3309
  const env = {
2877
- name: current.name,
2878
- api_base: current.config.api_base
3310
+ name: resolved.envName,
3311
+ api_base: resolved.apiBase,
3312
+ account: typeof user.email === "string" ? user.email : resolved.email
2879
3313
  };
2880
- if (current.config.actor) env.actor = current.config.actor;
2881
- if (current.config.agent_label) env.agent_label = current.config.agent_label;
2882
- render(
2883
- { kind: "whoami" },
2884
- { env, user, ...org ? { org } : {} }
2885
- );
3314
+ if (resolved.creds.actor) env.actor = resolved.creds.actor;
3315
+ if (resolved.creds.agent_label) env.agent_label = resolved.creds.agent_label;
3316
+ render({ kind: "whoami" }, { env, user, ...org ? { org } : {} });
2886
3317
  });
2887
3318
  function printLoggedOut() {
2888
3319
  process.stderr.write(dim('not logged in. run "wspc login".') + "\n");
@@ -2890,58 +3321,64 @@ function printLoggedOut() {
2890
3321
  }
2891
3322
 
2892
3323
  // src/handwritten/commands/config.ts
2893
- import { Command as Command39 } from "commander";
2894
- var configCommand = new Command39("config").description("Manage wspc local config");
3324
+ import { Command as Command50 } from "commander";
3325
+ var configCommand = new Command50("config").description("Manage wspc local config");
2895
3326
  registerRenderer("config_show", (data) => {
2896
3327
  const d = data;
2897
3328
  if (d.envs.length === 0) {
2898
3329
  process.stdout.write(dim(' no envs configured. run "wspc login".') + "\n");
2899
3330
  return;
2900
3331
  }
2901
- const headers = ["", "ENV", "API BASE", "ACTOR", "AUTH"];
3332
+ const headers = ["", "ENV", "API BASE", "ACTIVE ACCOUNT", "ACCOUNTS", "AUTH"];
2902
3333
  const rows = d.envs.map((e) => [
2903
3334
  e.name === d.current_env ? green("\u2713") : " ",
2904
3335
  e.name,
2905
3336
  e.api_base,
2906
- e.actor ?? dim("\u2014"),
3337
+ e.active_account ?? dim("\u2014"),
3338
+ String(e.accounts),
2907
3339
  e.auth === "none" ? dim("none") : e.auth
2908
3340
  ]);
2909
3341
  process.stdout.write(table(headers, rows));
2910
3342
  });
2911
- configCommand.command("show").description("List configured envs (tokens redacted, current marked with \u2713)").action(async () => {
2912
- const c = await new ConfigStore().read();
2913
- const envs = Object.entries(c.envs ?? {}).map(([name, env]) => ({
2914
- name,
2915
- api_base: env.api_base,
2916
- ...env.actor !== void 0 ? { actor: env.actor } : {},
2917
- auth: env.api_key ? "api_key" : env.access_token ? "oauth" : "none"
2918
- }));
2919
- render(
2920
- { kind: "config_show" },
2921
- {
2922
- ...c.current_env !== void 0 ? { current_env: c.current_env } : {},
2923
- envs
2924
- }
2925
- );
2926
- });
2927
- configCommand.command("set <key> <value>").description("Set a config field on current env (actor, agent-label, ...)").action(async (key, value) => {
2928
- const store = new ConfigStore();
3343
+ async function setConfigKey(store, key, value) {
2929
3344
  const c = await store.read();
2930
- if (!c.current_env) throw new Error("no current env; run `wspc login` first");
2931
- const env = c.envs[c.current_env];
2932
- if (!env) throw new Error(`env ${c.current_env} missing`);
3345
+ const resolved = resolveAccount(c, { accountOverride: process.env.WSPC_ACCOUNT });
3346
+ const env = c.envs[resolved.envName];
3347
+ if (!env) throw new Error(`env "${resolved.envName}" not found`);
3348
+ const acct = env.accounts[resolved.email];
3349
+ if (!acct) throw new Error(`account "${resolved.email}" not found`);
2933
3350
  switch (key) {
2934
3351
  case "actor":
2935
3352
  if (value !== "user" && value !== "agent") throw new Error("actor must be 'user' or 'agent'");
2936
- env.actor = value;
3353
+ acct.actor = value;
2937
3354
  break;
2938
3355
  case "agent-label":
2939
- env.agent_label = value;
3356
+ acct.agent_label = value;
2940
3357
  break;
2941
3358
  default:
2942
3359
  throw new Error(`unknown config key: ${key}`);
2943
3360
  }
2944
3361
  await store.write(c);
3362
+ }
3363
+ configCommand.command("show").description("List configured envs (tokens redacted, current marked with \u2713)").action(async () => {
3364
+ const c = await new ConfigStore().read();
3365
+ const envs = Object.entries(c.envs ?? {}).map(([name, env]) => {
3366
+ const active = env.current_account ? env.accounts?.[env.current_account] : void 0;
3367
+ return {
3368
+ name,
3369
+ api_base: env.api_base,
3370
+ ...env.current_account !== void 0 ? { active_account: env.current_account } : {},
3371
+ accounts: Object.keys(env.accounts ?? {}).length,
3372
+ auth: active?.api_key ? "api_key" : active?.access_token ? "oauth" : "none"
3373
+ };
3374
+ });
3375
+ render(
3376
+ { kind: "config_show" },
3377
+ { ...c.current_env !== void 0 ? { current_env: c.current_env } : {}, envs }
3378
+ );
3379
+ });
3380
+ configCommand.command("set <key> <value>").description("Set a field on the active account (actor, agent-label, ...)").action(async (key, value) => {
3381
+ await setConfigKey(new ConfigStore(), key, value);
2945
3382
  process.stdout.write(`\u2713 set ${key}=${value}
2946
3383
  `);
2947
3384
  });
@@ -2955,8 +3392,61 @@ configCommand.command("use <env>").description("Switch current_env").action(asyn
2955
3392
  `);
2956
3393
  });
2957
3394
 
3395
+ // src/handwritten/commands/account.ts
3396
+ import { Command as Command51 } from "commander";
3397
+ async function listAccounts(store) {
3398
+ const c = await store.read();
3399
+ const envName = c.current_env;
3400
+ if (!envName || !c.envs[envName]) return [];
3401
+ const env = c.envs[envName];
3402
+ return Object.values(env.accounts ?? {}).map((a) => ({
3403
+ email: a.email,
3404
+ user_id: a.user_id,
3405
+ actor: a.actor,
3406
+ auth: a.api_key ? "api_key" : a.access_token ? "oauth" : "none",
3407
+ active: env.current_account === a.email
3408
+ }));
3409
+ }
3410
+ async function switchAccount(store, email) {
3411
+ const c = await store.read();
3412
+ const envName = c.current_env;
3413
+ if (!envName || !c.envs[envName]) throw new Error("no current env; run `wspc login` first");
3414
+ const env = c.envs[envName];
3415
+ if (!env.accounts?.[email]) {
3416
+ throw new Error(`no account '${email}' in env '${envName}'. Run \`wspc account ls\` or \`wspc login\`.`);
3417
+ }
3418
+ env.current_account = email;
3419
+ await store.write(c);
3420
+ }
3421
+ registerRenderer("account_ls", (data) => {
3422
+ const rows = data.accounts;
3423
+ if (rows.length === 0) {
3424
+ process.stdout.write(dim(' no accounts. run "wspc login".') + "\n");
3425
+ return;
3426
+ }
3427
+ const headers = ["", "EMAIL", "USER", "ACTOR", "AUTH"];
3428
+ const body = rows.map((r) => [
3429
+ r.active ? green("\u2713") : " ",
3430
+ r.email,
3431
+ r.user_id ?? dim("\u2014"),
3432
+ r.actor ?? dim("\u2014"),
3433
+ r.auth === "none" ? dim("none") : r.auth
3434
+ ]);
3435
+ process.stdout.write(table(headers, body));
3436
+ });
3437
+ var accountCommand = new Command51("account").description("Manage logged-in accounts");
3438
+ accountCommand.command("ls").description("List accounts in the current env (active marked with \u2713)").action(async () => {
3439
+ const accounts = await listAccounts(new ConfigStore());
3440
+ render({ kind: "account_ls" }, { accounts });
3441
+ });
3442
+ accountCommand.command("switch <email>").description("Set the active account for the current env").action(async (email) => {
3443
+ await switchAccount(new ConfigStore(), email);
3444
+ process.stdout.write(`\u2713 active account is now ${email}
3445
+ `);
3446
+ });
3447
+
2958
3448
  // src/handwritten/commands/todo-done.ts
2959
- import { Command as Command40 } from "commander";
3449
+ import { Command as Command52 } from "commander";
2960
3450
  var TODO_UPDATE_DISPLAY = {
2961
3451
  shape: "object",
2962
3452
  format: {
@@ -2974,7 +3464,7 @@ var TODO_UPDATE_DISPLAY = {
2974
3464
  deleted_at: "relative-time"
2975
3465
  }
2976
3466
  };
2977
- var todoDoneCommand = new Command40("done").description("Mark a todo done (sugar for `update <id> --status done`)").argument("<id>", "Todo id").action(async (id) => {
3467
+ var todoDoneCommand = new Command52("done").description("Mark a todo done (sugar for `update <id> --status done`)").argument("<id>", "Todo id").action(async (id) => {
2978
3468
  const client2 = await loadSdkClient();
2979
3469
  const result = await todoUpdate({
2980
3470
  client: client2._rawClient,
@@ -2993,7 +3483,7 @@ var todoDoneCommand = new Command40("done").description("Mark a todo done (sugar
2993
3483
  });
2994
3484
 
2995
3485
  // src/handwritten/commands/email/send.ts
2996
- import { Command as Command41 } from "commander";
3486
+ import { Command as Command53 } from "commander";
2997
3487
  import { readFile, stat } from "fs/promises";
2998
3488
  import { basename } from "path";
2999
3489
 
@@ -3051,7 +3541,7 @@ async function resolveAttachment(input) {
3051
3541
  `--attach ${input}: neither a readable file nor a valid <prefix>_<ulid>:<idx> reference.`
3052
3542
  );
3053
3543
  }
3054
- var sendCommand = new Command41("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)", []).requiredOption("--idempotency-key <key>", "idempotency key").action(async (opts) => {
3544
+ var sendCommand = new Command53("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)", []).requiredOption("--idempotency-key <key>", "idempotency key").action(async (opts) => {
3055
3545
  const isReply = Boolean(opts.reply);
3056
3546
  const to = opts.to;
3057
3547
  const attachInputs = opts.attach;
@@ -3138,7 +3628,7 @@ var sendCommand = new Command41("send").description("Send an outbound email").re
3138
3628
  });
3139
3629
 
3140
3630
  // src/handwritten/commands/email/attachment.ts
3141
- import { Command as Command42 } from "commander";
3631
+ import { Command as Command54 } from "commander";
3142
3632
  import { createWriteStream } from "fs";
3143
3633
  import { Readable } from "stream";
3144
3634
  import { pipeline } from "stream/promises";
@@ -3155,7 +3645,7 @@ function parseContentDispositionFilename(header) {
3155
3645
  }
3156
3646
 
3157
3647
  // src/handwritten/commands/email/attachment.ts
3158
- var attachmentCommand = new Command42("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) => {
3648
+ var attachmentCommand = new Command54("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) => {
3159
3649
  const idx = Number(idxArg);
3160
3650
  if (!Number.isInteger(idx) || idx < 0) {
3161
3651
  process.stderr.write(`<idx> must be a non-negative integer (got "${idxArg}")
@@ -3188,13 +3678,16 @@ var attachmentCommand = new Command42("attachment").description("Download an inb
3188
3678
 
3189
3679
  // src/cli.ts
3190
3680
  function buildProgram() {
3191
- const program = new Command43().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)").hook("preAction", (thisCommand) => {
3192
- if (thisCommand.opts().json) process.env.WSPC_OUTPUT = "json";
3681
+ const program = new Command55().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) => {
3682
+ const globals = actionCommand.optsWithGlobals();
3683
+ if (globals.json) process.env.WSPC_OUTPUT = "json";
3684
+ if (globals.account) process.env.WSPC_ACCOUNT = String(globals.account);
3193
3685
  });
3194
3686
  program.addCommand(loginCommand);
3195
3687
  program.addCommand(logoutCommand);
3196
3688
  program.addCommand(whoamiCommand);
3197
3689
  program.addCommand(configCommand);
3690
+ program.addCommand(accountCommand);
3198
3691
  registerGeneratedCommands(program);
3199
3692
  const todo = program.commands.find((c) => c.name() === "todo");
3200
3693
  if (todo) todo.addCommand(todoDoneCommand);