@wspc/cli 0.0.6 → 0.0.7

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 Command51 } 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",
@@ -1048,7 +1087,62 @@ var todoUpdate = (options) => (options.client ?? client).patch({
1048
1087
  import { promises as fs } from "fs";
1049
1088
  import { homedir } from "os";
1050
1089
  import { join } from "path";
1090
+ var LEGACY_ACCOUNT_KEY = "(default)";
1051
1091
  var DEFAULT_DIR = join(homedir(), ".wspc");
1092
+ var V1_CRED_KEYS = [
1093
+ "refresh_token",
1094
+ "access_token",
1095
+ "access_token_expires_at",
1096
+ "api_key",
1097
+ "actor",
1098
+ "agent_label"
1099
+ ];
1100
+ function migrateEnv(raw) {
1101
+ const api_base = typeof raw.api_base === "string" ? raw.api_base : "";
1102
+ const env = { api_base, accounts: {} };
1103
+ if (typeof raw.client_id === "string") env.client_id = raw.client_id;
1104
+ if (raw.accounts && typeof raw.accounts === "object") {
1105
+ env.accounts = raw.accounts;
1106
+ if (typeof raw.current_account === "string") env.current_account = raw.current_account;
1107
+ return env;
1108
+ }
1109
+ const hasCreds = V1_CRED_KEYS.some((k) => raw[k] !== void 0);
1110
+ if (hasCreds) {
1111
+ const creds = { email: LEGACY_ACCOUNT_KEY };
1112
+ for (const k of V1_CRED_KEYS) {
1113
+ if (raw[k] !== void 0) creds[k] = raw[k];
1114
+ }
1115
+ env.accounts[LEGACY_ACCOUNT_KEY] = creds;
1116
+ env.current_account = LEGACY_ACCOUNT_KEY;
1117
+ }
1118
+ return env;
1119
+ }
1120
+ function normalize(parsed) {
1121
+ if (typeof parsed !== "object" || parsed === null) return { envs: {} };
1122
+ const obj = parsed;
1123
+ if (typeof obj.envs !== "object" || obj.envs === null) return { envs: {} };
1124
+ const envs = {};
1125
+ for (const [name, rawEnv] of Object.entries(obj.envs)) {
1126
+ if (typeof rawEnv === "object" && rawEnv !== null) {
1127
+ envs[name] = migrateEnv(rawEnv);
1128
+ }
1129
+ }
1130
+ const out = { schema_version: 2, envs };
1131
+ if (typeof obj.current_env === "string") out.current_env = obj.current_env;
1132
+ return out;
1133
+ }
1134
+ function rekeyLegacyAccount(config, envName, email, userId) {
1135
+ if (email === LEGACY_ACCOUNT_KEY) return false;
1136
+ const env = config.envs[envName];
1137
+ const legacy = env?.accounts?.[LEGACY_ACCOUNT_KEY];
1138
+ if (!env || !legacy) return false;
1139
+ delete env.accounts[LEGACY_ACCOUNT_KEY];
1140
+ if (!env.accounts[email]) {
1141
+ env.accounts[email] = { ...legacy, email, ...userId ? { user_id: userId } : {} };
1142
+ }
1143
+ if (env.current_account === LEGACY_ACCOUNT_KEY) env.current_account = email;
1144
+ return true;
1145
+ }
1052
1146
  var ConfigStore = class {
1053
1147
  configDir;
1054
1148
  configFile;
@@ -1059,11 +1153,7 @@ var ConfigStore = class {
1059
1153
  async read() {
1060
1154
  try {
1061
1155
  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;
1156
+ return normalize(JSON.parse(buf));
1067
1157
  } catch (e) {
1068
1158
  if (e.code === "ENOENT") return { envs: {} };
1069
1159
  throw e;
@@ -1088,9 +1178,9 @@ var ConfigStore = class {
1088
1178
  };
1089
1179
 
1090
1180
  // 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";
1181
+ var VERSION = "0.0.7";
1182
+ var SPEC_SHA = "c579a55a";
1183
+ var SPEC_FETCHED_AT = "2026-06-03T06:34:38.606Z";
1094
1184
  var API_BASE = "https://api.wspc.ai";
1095
1185
 
1096
1186
  // src/index.ts
@@ -1154,45 +1244,78 @@ function createAuthInterceptor(mode) {
1154
1244
  };
1155
1245
  }
1156
1246
 
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) {
1247
+ // src/handwritten/auth/resolve-account.ts
1248
+ var NOT_LOGGED_IN = "not logged in: run `wspc login` first";
1249
+ function resolveAccount(config, opts = {}) {
1250
+ const envName = config.current_env;
1251
+ if (!envName || !config.envs[envName]) throw new Error(NOT_LOGGED_IN);
1252
+ const env = config.envs[envName];
1253
+ const accounts = env.accounts ?? {};
1254
+ const emails = Object.keys(accounts);
1255
+ let email;
1256
+ const override = opts.accountOverride;
1257
+ if (override) {
1258
+ if (!accounts[override]) {
1173
1259
  throw new Error(
1174
- "config has OAuth tokens but no client_id \u2014 run `wspc logout && wspc login` to re-register"
1260
+ `no account '${override}' in env '${envName}'. Run \`wspc account ls\` or \`wspc login\`.`
1175
1261
  );
1176
1262
  }
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
- });
1263
+ email = override;
1264
+ } else if (env.current_account && accounts[env.current_account]) {
1265
+ email = env.current_account;
1266
+ } else if (emails.length === 1) {
1267
+ email = emails[0];
1268
+ } else if (emails.length === 0) {
1269
+ throw new Error(NOT_LOGGED_IN);
1270
+ } else {
1271
+ throw new Error(
1272
+ `multiple accounts in env '${envName}'; specify --account <email> or run \`wspc account switch <email>\`.`
1273
+ );
1274
+ }
1275
+ if (email === void 0) throw new Error(NOT_LOGGED_IN);
1276
+ const creds = accounts[email];
1277
+ if (!creds) throw new Error(NOT_LOGGED_IN);
1278
+ if (!creds.api_key && !(creds.access_token && creds.refresh_token)) {
1279
+ throw new Error(NOT_LOGGED_IN);
1280
+ }
1281
+ return { envName, apiBase: env.api_base, clientId: env.client_id, email, creds };
1282
+ }
1283
+
1284
+ // src/handwritten/auth/load-sdk-client.ts
1285
+ function buildInterceptor(store, resolved) {
1286
+ const { envName, apiBase, clientId, email, creds } = resolved;
1287
+ if (creds.api_key) {
1288
+ return createAuthInterceptor({ apiKey: creds.api_key });
1289
+ }
1290
+ if (!clientId) {
1291
+ throw new Error(
1292
+ "config has OAuth tokens but no client_id \u2014 run `wspc logout && wspc login` to re-register"
1293
+ );
1192
1294
  }
1295
+ return createAuthInterceptor({
1296
+ accessToken: creds.access_token,
1297
+ refreshToken: creds.refresh_token,
1298
+ baseUrl: apiBase,
1299
+ clientId,
1300
+ onTokenRefresh: async ({ accessToken, refreshToken, expiresAt }) => {
1301
+ const cfg = await store.read();
1302
+ const a = cfg.envs[envName]?.accounts?.[email];
1303
+ if (!a) return;
1304
+ a.access_token = accessToken;
1305
+ a.refresh_token = refreshToken;
1306
+ a.access_token_expires_at = expiresAt;
1307
+ await store.write(cfg);
1308
+ }
1309
+ });
1310
+ }
1311
+ async function loadSdkClient(opts = {}) {
1312
+ const store = opts.store ?? new ConfigStore();
1313
+ const config = await store.read();
1314
+ const resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
1315
+ const interceptor = buildInterceptor(store, resolved);
1193
1316
  const rawClient = createClient(
1194
1317
  createConfig({
1195
- baseUrl: env.api_base,
1318
+ baseUrl: resolved.apiBase,
1196
1319
  fetch: ((input, init) => interceptor.execute(new Request(input, init)))
1197
1320
  })
1198
1321
  );
@@ -1200,39 +1323,11 @@ async function loadSdkClient(opts = {}) {
1200
1323
  }
1201
1324
  async function loadAuthedFetch(opts = {}) {
1202
1325
  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
- }
1326
+ const config = await store.read();
1327
+ const resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
1328
+ const interceptor = buildInterceptor(store, resolved);
1234
1329
  const authedFetch = (input, init) => interceptor.execute(new Request(input, init));
1235
- return { fetch: authedFetch, baseUrl: env.api_base };
1330
+ return { fetch: authedFetch, baseUrl: resolved.apiBase };
1236
1331
  }
1237
1332
 
1238
1333
  // src/handwritten/output/primitives.ts
@@ -1617,8 +1712,29 @@ function formatCell(value, fmt, colorMap) {
1617
1712
  }
1618
1713
  }
1619
1714
 
1715
+ // src/generated/cli/invite/accept.ts
1716
+ var inviteAcceptCommand = new Command("accept").description("Accept an invite and switch into the inviting organization").argument("<id>", "id").action(async (id, opts) => {
1717
+ const client2 = await loadSdkClient();
1718
+ const result = await inviteAccept({
1719
+ client: client2._rawClient,
1720
+ path: {
1721
+ id
1722
+ }
1723
+ });
1724
+ if (result.error || !result.response?.ok) {
1725
+ process.stderr.write(
1726
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1727
+ `
1728
+ );
1729
+ process.exitCode = 1;
1730
+ return;
1731
+ }
1732
+ render({ kind: "invite_accept", display: { "shape": "object", "fields": ["id", "name", "created_at", "updated_at"] } }, result.data);
1733
+ });
1734
+
1620
1735
  // 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) => {
1736
+ import { Command as Command2 } from "commander";
1737
+ var keyCreateCommand = new Command2("create").description("Create a new API key (full value returned once)").option("--label <value>", "label").action(async (opts) => {
1622
1738
  const client2 = await loadSdkClient();
1623
1739
  const result = await keyCreate({
1624
1740
  client: client2._rawClient,
@@ -1638,8 +1754,8 @@ var keyCreateCommand = new Command("create").description("Create a new API key (
1638
1754
  });
1639
1755
 
1640
1756
  // 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) => {
1757
+ import { Command as Command3 } from "commander";
1758
+ var keyListCommand = new Command3("ls").description("List active API keys").action(async (opts) => {
1643
1759
  const client2 = await loadSdkClient();
1644
1760
  const result = await keyList({
1645
1761
  client: client2._rawClient
@@ -1655,9 +1771,48 @@ var keyListCommand = new Command2("ls").description("List active API keys").acti
1655
1771
  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
1772
  });
1657
1773
 
1774
+ // src/generated/cli/org/invite.ts
1775
+ import { Command as Command4 } from "commander";
1776
+ var orgInviteCreateCommand = new Command4("invite").description("Invite an email to join the caller's organization").option("--email <value>", "email").action(async (opts) => {
1777
+ const client2 = await loadSdkClient();
1778
+ const result = await orgInviteCreate({
1779
+ client: client2._rawClient,
1780
+ body: {
1781
+ email: opts.email
1782
+ }
1783
+ });
1784
+ if (result.error || !result.response?.ok) {
1785
+ process.stderr.write(
1786
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1787
+ `
1788
+ );
1789
+ process.exitCode = 1;
1790
+ return;
1791
+ }
1792
+ render({ kind: "org_invite_create", display: { "shape": "object", "fields": ["id", "email", "state", "expires_at", "invite_url"] } }, result.data);
1793
+ });
1794
+
1795
+ // src/generated/cli/org/invites.ts
1796
+ import { Command as Command5 } from "commander";
1797
+ var orgInvitesListCommand = new Command5("invites").description("List invites issued by the caller's organization").action(async (opts) => {
1798
+ const client2 = await loadSdkClient();
1799
+ const result = await orgInvitesList({
1800
+ client: client2._rawClient
1801
+ });
1802
+ if (result.error || !result.response?.ok) {
1803
+ process.stderr.write(
1804
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1805
+ `
1806
+ );
1807
+ process.exitCode = 1;
1808
+ return;
1809
+ }
1810
+ 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);
1811
+ });
1812
+
1658
1813
  // 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) => {
1814
+ import { Command as Command6 } from "commander";
1815
+ var orgGetCommand = new Command6("show").description("Get the authenticated user's organization").action(async (opts) => {
1661
1816
  const client2 = await loadSdkClient();
1662
1817
  const result = await orgGet({
1663
1818
  client: client2._rawClient
@@ -1674,8 +1829,8 @@ var orgGetCommand = new Command3("show").description("Get the authenticated user
1674
1829
  });
1675
1830
 
1676
1831
  // 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) => {
1832
+ import { Command as Command7 } from "commander";
1833
+ var orgUpdateCommand = new Command7("rename").description("Update the authenticated user's organization").option("--name <value>", "name").action(async (opts) => {
1679
1834
  const client2 = await loadSdkClient();
1680
1835
  const result = await orgUpdate({
1681
1836
  client: client2._rawClient,
@@ -1694,9 +1849,30 @@ var orgUpdateCommand = new Command4("rename").description("Update the authentica
1694
1849
  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
1850
  });
1696
1851
 
1852
+ // src/generated/cli/invite/show.ts
1853
+ import { Command as Command8 } from "commander";
1854
+ var inviteGetCommand = new Command8("show").description("Get a single invite addressed to the caller").argument("<id>", "id").action(async (id, opts) => {
1855
+ const client2 = await loadSdkClient();
1856
+ const result = await inviteGet({
1857
+ client: client2._rawClient,
1858
+ path: {
1859
+ id
1860
+ }
1861
+ });
1862
+ if (result.error || !result.response?.ok) {
1863
+ process.stderr.write(
1864
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1865
+ `
1866
+ );
1867
+ process.exitCode = 1;
1868
+ return;
1869
+ }
1870
+ render({ kind: "invite_get", display: void 0 }, result.data);
1871
+ });
1872
+
1697
1873
  // 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) => {
1874
+ import { Command as Command9 } from "commander";
1875
+ var authMeCommand = new Command9("me").description("Fetch the user identified by the bearer token").action(async (opts) => {
1700
1876
  const client2 = await loadSdkClient();
1701
1877
  const result = await authMe({
1702
1878
  client: client2._rawClient
@@ -1712,9 +1888,27 @@ var authMeCommand = new Command5("me").description("Fetch the user identified by
1712
1888
  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
1889
  });
1714
1890
 
1891
+ // src/generated/cli/invites.ts
1892
+ import { Command as Command10 } from "commander";
1893
+ var invitesListCommand = new Command10("invites").description("List invites addressed to the authenticated user's email").action(async (opts) => {
1894
+ const client2 = await loadSdkClient();
1895
+ const result = await invitesList({
1896
+ client: client2._rawClient
1897
+ });
1898
+ if (result.error || !result.response?.ok) {
1899
+ process.stderr.write(
1900
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1901
+ `
1902
+ );
1903
+ process.exitCode = 1;
1904
+ return;
1905
+ }
1906
+ 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);
1907
+ });
1908
+
1715
1909
  // 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) => {
1910
+ import { Command as Command11 } from "commander";
1911
+ 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
1912
  const client2 = await loadSdkClient();
1719
1913
  const result = await orgMembersList({
1720
1914
  client: client2._rawClient,
@@ -1734,9 +1928,30 @@ var orgMembersListCommand = new Command6("members").description("List members of
1734
1928
  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
1929
  });
1736
1930
 
1931
+ // src/generated/cli/invite/reject.ts
1932
+ import { Command as Command12 } from "commander";
1933
+ var inviteRejectCommand = new Command12("reject").description("Reject an invite").argument("<id>", "id").action(async (id, opts) => {
1934
+ const client2 = await loadSdkClient();
1935
+ const result = await inviteReject({
1936
+ client: client2._rawClient,
1937
+ path: {
1938
+ id
1939
+ }
1940
+ });
1941
+ if (result.error || !result.response?.ok) {
1942
+ process.stderr.write(
1943
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1944
+ `
1945
+ );
1946
+ process.exitCode = 1;
1947
+ return;
1948
+ }
1949
+ render({ kind: "invite_reject", display: void 0 }, result.data);
1950
+ });
1951
+
1737
1952
  // 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) => {
1953
+ import { Command as Command13 } from "commander";
1954
+ var keyRevokeCommand = new Command13("rm").description("Soft-revoke an API key").argument("<id>", "id").action(async (id, opts) => {
1740
1955
  const client2 = await loadSdkClient();
1741
1956
  const result = await keyRevoke({
1742
1957
  client: client2._rawClient,
@@ -1756,8 +1971,8 @@ var keyRevokeCommand = new Command7("rm").description("Soft-revoke an API key").
1756
1971
  });
1757
1972
 
1758
1973
  // 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) => {
1974
+ import { Command as Command14 } from "commander";
1975
+ 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
1976
  const client2 = await loadSdkClient();
1762
1977
  const result = await keyUpdate({
1763
1978
  client: client2._rawClient,
@@ -1779,8 +1994,29 @@ var keyUpdateCommand = new Command8("edit").description("Update an active API ke
1779
1994
  render({ kind: "key_update", display: void 0 }, result.data);
1780
1995
  });
1781
1996
 
1997
+ // src/generated/cli/org/invite/revoke.ts
1998
+ import { Command as Command15 } from "commander";
1999
+ var orgInviteRevokeCommand = new Command15("revoke").description("Revoke a pending invite").argument("<id>", "id").action(async (id, opts) => {
2000
+ const client2 = await loadSdkClient();
2001
+ const result = await orgInviteRevoke({
2002
+ client: client2._rawClient,
2003
+ path: {
2004
+ id
2005
+ }
2006
+ });
2007
+ if (result.error || !result.response?.ok) {
2008
+ process.stderr.write(
2009
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
2010
+ `
2011
+ );
2012
+ process.exitCode = 1;
2013
+ return;
2014
+ }
2015
+ render({ kind: "org_invite_revoke", display: void 0 }, result.data);
2016
+ });
2017
+
1782
2018
  // src/generated/cli/event/add.ts
1783
- import { Command as Command9 } from "commander";
2019
+ import { Command as Command16 } from "commander";
1784
2020
 
1785
2021
  // src/handwritten/utils/parse-time.ts
1786
2022
  import * as chrono from "chrono-node";
@@ -1866,7 +2102,7 @@ function parseAttendee(input) {
1866
2102
  }
1867
2103
 
1868
2104
  // 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) => {
2105
+ 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
2106
  memo.push(val);
1871
2107
  return memo;
1872
2108
  }, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (title, opts) => {
@@ -1915,8 +2151,8 @@ var eventCreateCommand = new Command9("add").description("Schedule a calendar ev
1915
2151
  });
1916
2152
 
1917
2153
  // 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) => {
2154
+ import { Command as Command17 } from "commander";
2155
+ 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
2156
  const zone = resolveTimezone(opts.tz);
1921
2157
  let fromValue;
1922
2158
  if (opts.from !== void 0) {
@@ -1953,8 +2189,8 @@ var eventListCommand = new Command10("ls").description("List calendar events").o
1953
2189
  });
1954
2190
 
1955
2191
  // 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) => {
2192
+ import { Command as Command18 } from "commander";
2193
+ 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
2194
  const client2 = await loadSdkClient();
1959
2195
  const result = await eventDelete({
1960
2196
  client: client2._rawClient,
@@ -1977,8 +2213,8 @@ var eventDeleteCommand = new Command11("rm").description("Soft-delete a calendar
1977
2213
  });
1978
2214
 
1979
2215
  // 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) => {
2216
+ import { Command as Command19 } from "commander";
2217
+ 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
2218
  const client2 = await loadSdkClient();
1983
2219
  const result = await eventGet({
1984
2220
  client: client2._rawClient,
@@ -2001,8 +2237,8 @@ var eventGetCommand = new Command12("show").description("Get a calendar event by
2001
2237
  });
2002
2238
 
2003
2239
  // 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) => {
2240
+ import { Command as Command20 } from "commander";
2241
+ 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
2242
  memo.push(val);
2007
2243
  return memo;
2008
2244
  }, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (id, opts) => {
@@ -2055,8 +2291,8 @@ var eventUpdateCommand = new Command13("set").description("Update a calendar eve
2055
2291
  });
2056
2292
 
2057
2293
  // 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) => {
2294
+ import { Command as Command21 } from "commander";
2295
+ var eventIcsDownloadCommand = new Command21("ics").description("Download event as `.ics`").argument("<id>", "id").action(async (id, opts) => {
2060
2296
  const client2 = await loadSdkClient();
2061
2297
  const result = await eventIcsDownload({
2062
2298
  client: client2._rawClient,
@@ -2076,8 +2312,8 @@ var eventIcsDownloadCommand = new Command14("ics").description("Download event a
2076
2312
  });
2077
2313
 
2078
2314
  // 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) => {
2315
+ import { Command as Command22 } from "commander";
2316
+ var emailAliasCreateCommand = new Command22("add").description("Create a receiving alias").argument("<email>", "email").action(async (email, opts) => {
2081
2317
  const client2 = await loadSdkClient();
2082
2318
  const result = await emailAliasCreate({
2083
2319
  client: client2._rawClient,
@@ -2097,8 +2333,8 @@ var emailAliasCreateCommand = new Command15("add").description("Create a receivi
2097
2333
  });
2098
2334
 
2099
2335
  // 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) => {
2336
+ import { Command as Command23 } from "commander";
2337
+ var emailAliasListCommand = new Command23("ls").description("List the caller's aliases").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2102
2338
  const client2 = await loadSdkClient();
2103
2339
  const result = await emailAliasList({
2104
2340
  client: client2._rawClient,
@@ -2118,8 +2354,8 @@ var emailAliasListCommand = new Command16("ls").description("List the caller's a
2118
2354
  });
2119
2355
 
2120
2356
  // 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) => {
2357
+ import { Command as Command24 } from "commander";
2358
+ var emailAliasDeleteCommand = new Command24("rm").description("Soft-delete an alias").argument("<email>", "email").action(async (email, opts) => {
2123
2359
  const client2 = await loadSdkClient();
2124
2360
  const result = await emailAliasDelete({
2125
2361
  client: client2._rawClient,
@@ -2139,8 +2375,8 @@ var emailAliasDeleteCommand = new Command17("rm").description("Soft-delete an al
2139
2375
  });
2140
2376
 
2141
2377
  // 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) => {
2378
+ import { Command as Command25 } from "commander";
2379
+ var emailDeleteCommand = new Command25("rm").description("Soft-delete inbound emails").argument("<id...>", "id").action(async (id, opts) => {
2144
2380
  const idRaw = id;
2145
2381
  const ids = idRaw.length > 0 ? idRaw : void 0;
2146
2382
  const client2 = await loadSdkClient();
@@ -2162,8 +2398,8 @@ var emailDeleteCommand = new Command18("rm").description("Soft-delete inbound em
2162
2398
  });
2163
2399
 
2164
2400
  // 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) => {
2401
+ import { Command as Command26 } from "commander";
2402
+ 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
2403
  const client2 = await loadSdkClient();
2168
2404
  const result = await emailGet({
2169
2405
  client: client2._rawClient,
@@ -2187,8 +2423,8 @@ var emailGetCommand = new Command19("show").description("Get an inbound email by
2187
2423
  });
2188
2424
 
2189
2425
  // 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) => {
2426
+ import { Command as Command27 } from "commander";
2427
+ 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
2428
  const client2 = await loadSdkClient();
2193
2429
  const result = await emailList({
2194
2430
  client: client2._rawClient,
@@ -2213,8 +2449,8 @@ var emailListCommand = new Command20("ls").description("List inbound emails").op
2213
2449
  });
2214
2450
 
2215
2451
  // 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) => {
2452
+ import { Command as Command28 } from "commander";
2453
+ var emailMarkReadCommand = new Command28("read").description("Mark inbound emails as read").argument("<id...>", "id").action(async (id, opts) => {
2218
2454
  const idRaw = id;
2219
2455
  const ids = idRaw.length > 0 ? idRaw : void 0;
2220
2456
  const client2 = await loadSdkClient();
@@ -2236,8 +2472,8 @@ var emailMarkReadCommand = new Command21("read").description("Mark inbound email
2236
2472
  });
2237
2473
 
2238
2474
  // 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) => {
2475
+ import { Command as Command29 } from "commander";
2476
+ var emailMarkUnreadCommand = new Command29("unread").description("Mark inbound emails as unread").argument("<id...>", "id").action(async (id, opts) => {
2241
2477
  const idRaw = id;
2242
2478
  const ids = idRaw.length > 0 ? idRaw : void 0;
2243
2479
  const client2 = await loadSdkClient();
@@ -2259,8 +2495,8 @@ var emailMarkUnreadCommand = new Command22("unread").description("Mark inbound e
2259
2495
  });
2260
2496
 
2261
2497
  // 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) => {
2498
+ import { Command as Command30 } from "commander";
2499
+ var pushConfigDeleteCommand = new Command30("rm").description("Remove a push transport").argument("<transport>", "transport").action(async (transport, opts) => {
2264
2500
  const client2 = await loadSdkClient();
2265
2501
  const result = await pushConfigDelete({
2266
2502
  client: client2._rawClient,
@@ -2280,8 +2516,8 @@ var pushConfigDeleteCommand = new Command23("rm").description("Remove a push tra
2280
2516
  });
2281
2517
 
2282
2518
  // 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) => {
2519
+ import { Command as Command31 } from "commander";
2520
+ 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
2521
  const client2 = await loadSdkClient();
2286
2522
  const result = await pushConfigSet({
2287
2523
  client: client2._rawClient,
@@ -2304,8 +2540,8 @@ var pushConfigSetCommand = new Command24("set").description("Register or update
2304
2540
  });
2305
2541
 
2306
2542
  // 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) => {
2543
+ import { Command as Command32 } from "commander";
2544
+ var pushConfigGetCommand = new Command32("show").description("List the caller's push transports").action(async (opts) => {
2309
2545
  const client2 = await loadSdkClient();
2310
2546
  const result = await pushConfigGet({
2311
2547
  client: client2._rawClient
@@ -2322,8 +2558,8 @@ var pushConfigGetCommand = new Command25("show").description("List the caller's
2322
2558
  });
2323
2559
 
2324
2560
  // 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) => {
2561
+ import { Command as Command33 } from "commander";
2562
+ var pushTestCommand = new Command33("test").description("Send a test push notification").option("--transport <value>", "transport").action(async (opts) => {
2327
2563
  const client2 = await loadSdkClient();
2328
2564
  const result = await pushTest({
2329
2565
  client: client2._rawClient,
@@ -2346,8 +2582,8 @@ var pushTestCommand = new Command26("test").description("Send a test push notifi
2346
2582
  });
2347
2583
 
2348
2584
  // 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) => {
2585
+ import { Command as Command34 } from "commander";
2586
+ var projectCreateCommand = new Command34("add").description("Create a project").argument("<name>", "name").option("--default-todo-type-id <value>", "default_todo_type_id").action(async (name, opts) => {
2351
2587
  const client2 = await loadSdkClient();
2352
2588
  const result = await projectCreate({
2353
2589
  client: client2._rawClient,
@@ -2368,8 +2604,8 @@ var projectCreateCommand = new Command27("add").description("Create a project").
2368
2604
  });
2369
2605
 
2370
2606
  // 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) => {
2607
+ import { Command as Command35 } from "commander";
2608
+ var projectListCommand = new Command35("ls").description("List projects").option("--include-deleted <value>", "include_deleted").action(async (opts) => {
2373
2609
  const client2 = await loadSdkClient();
2374
2610
  const result = await projectList({
2375
2611
  client: client2._rawClient,
@@ -2389,8 +2625,8 @@ var projectListCommand = new Command28("ls").description("List projects").option
2389
2625
  });
2390
2626
 
2391
2627
  // 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) => {
2628
+ import { Command as Command36 } from "commander";
2629
+ var recurrenceRuleListCommand = new Command36("ls").description("List recurring todo rules").option("--project-id <value>", "project_id").option("--user-id <value>", "user_id").action(async (opts) => {
2394
2630
  const client2 = await loadSdkClient();
2395
2631
  const result = await recurrenceRuleList({
2396
2632
  client: client2._rawClient,
@@ -2411,8 +2647,8 @@ var recurrenceRuleListCommand = new Command29("ls").description("List recurring
2411
2647
  });
2412
2648
 
2413
2649
  // 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) => {
2650
+ import { Command as Command37 } from "commander";
2651
+ var todoCreateCommand = new Command37("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
2652
  const client2 = await loadSdkClient();
2417
2653
  const result = await todoCreate({
2418
2654
  client: client2._rawClient,
@@ -2439,8 +2675,8 @@ var todoCreateCommand = new Command30("add").description("Create a todo").argume
2439
2675
  });
2440
2676
 
2441
2677
  // 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) => {
2678
+ import { Command as Command38 } from "commander";
2679
+ var todoListCommand = new Command38("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
2680
  const client2 = await loadSdkClient();
2445
2681
  const result = await todoList({
2446
2682
  client: client2._rawClient,
@@ -2471,8 +2707,8 @@ var todoListCommand = new Command31("ls").description("List todos with filters")
2471
2707
  });
2472
2708
 
2473
2709
  // 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) => {
2710
+ import { Command as Command39 } from "commander";
2711
+ var todoTypeListCommand = new Command39("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
2712
  const client2 = await loadSdkClient();
2477
2713
  const result = await todoTypeList({
2478
2714
  client: client2._rawClient,
@@ -2494,8 +2730,8 @@ var todoTypeListCommand = new Command32("ls").description("List todo types").opt
2494
2730
  });
2495
2731
 
2496
2732
  // 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) => {
2733
+ import { Command as Command40 } from "commander";
2734
+ var todoDeleteCommand = new Command40("rm").description("Soft-delete a todo").argument("<id>", "id").option("--expected-version <value>", "expected_version").option("--cascade <value>", "cascade").action(async (id, opts) => {
2499
2735
  const client2 = await loadSdkClient();
2500
2736
  const result = await todoDelete({
2501
2737
  client: client2._rawClient,
@@ -2519,8 +2755,8 @@ var todoDeleteCommand = new Command33("rm").description("Soft-delete a todo").ar
2519
2755
  });
2520
2756
 
2521
2757
  // 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) => {
2758
+ import { Command as Command41 } from "commander";
2759
+ var todoGetCommand = new Command41("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
2760
  const client2 = await loadSdkClient();
2525
2761
  const result = await todoGet({
2526
2762
  client: client2._rawClient,
@@ -2544,8 +2780,8 @@ var todoGetCommand = new Command34("show").description("Get a todo by id").argum
2544
2780
  });
2545
2781
 
2546
2782
  // 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) => {
2783
+ import { Command as Command42 } from "commander";
2784
+ var todoUpdateCommand = new Command42("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
2785
  const client2 = await loadSdkClient();
2550
2786
  const result = await todoUpdate({
2551
2787
  client: client2._rawClient,
@@ -2577,17 +2813,26 @@ var todoUpdateCommand = new Command35("update").description("Update a todo").arg
2577
2813
 
2578
2814
  // src/generated/cli/index.ts
2579
2815
  function registerGeneratedCommands(root) {
2816
+ const root_invite = root.command("invite").description("invite commands");
2817
+ root_invite.addCommand(inviteAcceptCommand);
2818
+ root_invite.addCommand(inviteGetCommand);
2819
+ root_invite.addCommand(inviteRejectCommand);
2580
2820
  const root_keys = root.command("keys").description("keys commands");
2581
2821
  root_keys.addCommand(keyCreateCommand);
2582
2822
  root_keys.addCommand(keyListCommand);
2583
2823
  root_keys.addCommand(keyRevokeCommand);
2584
2824
  root_keys.addCommand(keyUpdateCommand);
2585
2825
  const root_org = root.command("org").description("org commands");
2826
+ const root_org_invite = root_org.command("invite").description("invite commands");
2827
+ root_org_invite.addCommand(orgInviteCreateCommand);
2828
+ root_org_invite.addCommand(orgInviteRevokeCommand);
2829
+ root_org.addCommand(orgInvitesListCommand);
2586
2830
  root_org.addCommand(orgGetCommand);
2587
2831
  root_org.addCommand(orgUpdateCommand);
2588
2832
  root_org.addCommand(orgMembersListCommand);
2589
2833
  const root_auth = root.command("auth").description("auth commands");
2590
2834
  root_auth.addCommand(authMeCommand);
2835
+ root.addCommand(invitesListCommand);
2591
2836
  const root_event = root.command("event").description("event commands");
2592
2837
  root_event.addCommand(eventCreateCommand);
2593
2838
  root_event.addCommand(eventListCommand);
@@ -2627,7 +2872,7 @@ function registerGeneratedCommands(root) {
2627
2872
  }
2628
2873
 
2629
2874
  // src/handwritten/commands/login.ts
2630
- import { Command as Command36 } from "commander";
2875
+ import { Command as Command43 } from "commander";
2631
2876
 
2632
2877
  // src/handwritten/auth/device-flow.ts
2633
2878
  var DEFAULT_SLEEP = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -2708,23 +2953,62 @@ async function ensureClientId(opts) {
2708
2953
  const body = await res.json();
2709
2954
  if (!body.client_id) throw new Error("client_registration_failed: missing client_id in response");
2710
2955
  const fresh = await opts.store.read();
2711
- const env = fresh.envs[opts.envName] ?? { api_base: opts.baseUrl };
2956
+ const env = fresh.envs[opts.envName] ?? { api_base: opts.baseUrl, accounts: {} };
2712
2957
  env.client_id = body.client_id;
2713
2958
  fresh.envs[opts.envName] = env;
2714
2959
  await opts.store.write(fresh);
2715
2960
  return body.client_id;
2716
2961
  }
2717
2962
 
2963
+ // src/handwritten/auth/fetch-me.ts
2964
+ async function fetchMe(opts) {
2965
+ const f = opts.fetchImpl ?? fetch;
2966
+ const res = await f(`${opts.baseUrl}/auth/me`, {
2967
+ headers: { authorization: `Bearer ${opts.token}` }
2968
+ });
2969
+ if (!res.ok) throw new Error(`auth_me_failed: HTTP ${res.status}`);
2970
+ const body = await res.json().catch(() => ({}));
2971
+ if (!body.user_id || !body.email) {
2972
+ throw new Error("auth_me_failed: missing user_id/email in response");
2973
+ }
2974
+ return { user_id: body.user_id, email: body.email };
2975
+ }
2976
+
2718
2977
  // src/handwritten/auth/login.ts
2978
+ function getOrCreateEnv(c, envName, apiBase) {
2979
+ const existing = c.envs[envName];
2980
+ if (existing) {
2981
+ existing.api_base = apiBase;
2982
+ existing.accounts ??= {};
2983
+ return existing;
2984
+ }
2985
+ const fresh = { api_base: apiBase, accounts: {} };
2986
+ c.envs[envName] = fresh;
2987
+ return fresh;
2988
+ }
2719
2989
  async function runLogin(opts) {
2720
2990
  const envName = opts.envName ?? "prod";
2721
2991
  const now = opts.now ?? Date.now;
2722
- const c = await opts.store.read();
2992
+ const me = opts.fetchMe ?? ((o) => fetchMe(o));
2723
2993
  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}"`);
2994
+ const who2 = await me({ baseUrl: opts.baseUrl, token: opts.apiKey });
2995
+ const c2 = await opts.store.read();
2996
+ const env2 = getOrCreateEnv(c2, envName, opts.baseUrl);
2997
+ const prev2 = env2.accounts[who2.email] ?? { email: who2.email };
2998
+ const acct2 = env2.accounts[who2.email] = {
2999
+ ...prev2,
3000
+ email: who2.email,
3001
+ user_id: who2.user_id,
3002
+ api_key: opts.apiKey
3003
+ };
3004
+ delete acct2.refresh_token;
3005
+ delete acct2.access_token;
3006
+ delete acct2.access_token_expires_at;
3007
+ env2.current_account = who2.email;
3008
+ if (who2.email !== LEGACY_ACCOUNT_KEY) delete env2.accounts[LEGACY_ACCOUNT_KEY];
3009
+ c2.current_env = envName;
3010
+ await opts.store.write(c2);
3011
+ opts.output.write(`\u2713 logged in (api key) as ${who2.email} \u2192 env "${envName}"`);
2728
3012
  return;
2729
3013
  }
2730
3014
  const ensureClient = opts.ensureClient ?? ((env2) => ensureClientId({ store: opts.store, envName: env2, baseUrl: opts.baseUrl }));
@@ -2745,24 +3029,29 @@ async function runLogin(opts) {
2745
3029
  `);
2746
3030
  }
2747
3031
  });
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,
3032
+ const who = await me({ baseUrl: opts.baseUrl, token: result.access_token });
3033
+ const c = await opts.store.read();
3034
+ const env = getOrCreateEnv(c, envName, opts.baseUrl);
3035
+ const prev = env.accounts[who.email] ?? { email: who.email };
3036
+ const acct = env.accounts[who.email] = {
3037
+ ...prev,
3038
+ email: who.email,
3039
+ user_id: who.user_id,
2753
3040
  refresh_token: result.refresh_token,
2754
3041
  access_token: result.access_token,
2755
3042
  access_token_expires_at: now() + result.expires_in * 1e3
2756
3043
  };
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}"`);
3044
+ delete acct.api_key;
3045
+ env.current_account = who.email;
3046
+ if (who.email !== LEGACY_ACCOUNT_KEY) delete env.accounts[LEGACY_ACCOUNT_KEY];
3047
+ c.current_env = envName;
3048
+ await opts.store.write(c);
3049
+ opts.output.writeJson({ event: "login_success", email: who.email });
3050
+ opts.output.write(`\u2713 logged in as ${who.email} \u2192 env "${envName}"`);
2762
3051
  }
2763
3052
 
2764
3053
  // 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) => {
3054
+ var loginCommand = new Command43("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
3055
  const store = new ConfigStore();
2767
3056
  const output = opts.json ? { write: () => {
2768
3057
  }, writeJson: (e) => process.stdout.write(JSON.stringify(e) + "\n") } : {
@@ -2779,51 +3068,61 @@ var loginCommand = new Command36("login").description("Log in via OAuth device f
2779
3068
  });
2780
3069
 
2781
3070
  // src/handwritten/commands/logout.ts
2782
- import { Command as Command37 } from "commander";
3071
+ import { Command as Command44 } from "commander";
2783
3072
 
2784
3073
  // src/handwritten/auth/logout.ts
2785
3074
  async function runLogout(opts) {
2786
- const envName = opts.envName;
2787
3075
  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;
3076
+ const envName = opts.envName ?? c.current_env;
3077
+ if (!envName || !c.envs[envName]) return { removed: [] };
3078
+ const env = c.envs[envName];
3079
+ env.accounts ??= {};
3080
+ if (opts.all) {
3081
+ const removed = Object.keys(env.accounts);
3082
+ env.accounts = {};
3083
+ env.current_account = void 0;
3084
+ await opts.store.write(c);
3085
+ return { removed };
3086
+ }
3087
+ const target = opts.email ?? env.current_account ?? (Object.keys(env.accounts).length === 1 ? Object.keys(env.accounts)[0] : void 0);
3088
+ if (!target || !env.accounts[target]) return { removed: [] };
3089
+ delete env.accounts[target];
3090
+ if (env.current_account === target) {
3091
+ const remaining = Object.keys(env.accounts);
3092
+ env.current_account = remaining.length === 1 ? remaining[0] : void 0;
3093
+ }
2795
3094
  await opts.store.write(c);
3095
+ return { removed: [target], newActive: env.current_account };
2796
3096
  }
2797
3097
 
2798
3098
  // 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");
3099
+ var logoutCommand = new Command44("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) => {
3100
+ const res = await runLogout({ store: new ConfigStore(), email, all: opts.all });
3101
+ if (res.removed.length === 0) {
3102
+ process.stdout.write("nothing to log out\n");
3103
+ return;
3104
+ }
3105
+ process.stdout.write(`\u2713 logged out: ${res.removed.join(", ")}
3106
+ `);
3107
+ if (res.newActive) process.stdout.write(`active account is now ${res.newActive}
3108
+ `);
2802
3109
  });
2803
3110
 
2804
3111
  // src/handwritten/commands/whoami.ts
2805
- import { Command as Command38 } from "commander";
3112
+ import { Command as Command45 } from "commander";
2806
3113
  var ENV_DISPLAY = {
2807
3114
  shape: "object",
2808
- fields: ["name", "api_base", "actor", "agent_label"]
3115
+ fields: ["name", "api_base", "account", "actor", "agent_label"]
2809
3116
  };
2810
3117
  var USER_DISPLAY = {
2811
3118
  shape: "object",
2812
3119
  fields: ["user_id", "email", "display_name", "api_key_id"],
2813
- format: {
2814
- user_id: "id-short",
2815
- api_key_id: "id-short"
2816
- }
3120
+ format: { user_id: "id-short", api_key_id: "id-short" }
2817
3121
  };
2818
3122
  var ORG_DISPLAY = {
2819
3123
  shape: "object",
2820
3124
  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
- }
3125
+ format: { id: "id-short", name: "truncate", created_at: "relative-time", updated_at: "relative-time" }
2827
3126
  };
2828
3127
  registerRenderer("whoami", (data) => {
2829
3128
  const d = data;
@@ -2836,15 +3135,19 @@ registerRenderer("whoami", (data) => {
2836
3135
  renderObject(d.org, ORG_DISPLAY);
2837
3136
  }
2838
3137
  });
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;
3138
+ async function backfillActiveEmail(store, envName, email, userId) {
3139
+ const cfg = await store.read();
3140
+ if (rekeyLegacyAccount(cfg, envName, email, userId)) {
3141
+ await store.write(cfg);
2845
3142
  }
3143
+ }
3144
+ var whoamiCommand = new Command45("whoami").description("Show the active env, signed-in account, and organization").action(async () => {
3145
+ const store = new ConfigStore();
3146
+ const config = await store.read();
3147
+ let resolved;
2846
3148
  let sdkClient;
2847
3149
  try {
3150
+ resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
2848
3151
  sdkClient = await loadSdkClient({ store });
2849
3152
  } catch {
2850
3153
  printLoggedOut();
@@ -2873,16 +3176,17 @@ var whoamiCommand = new Command38("whoami").description("Show the active env, si
2873
3176
  }
2874
3177
  throw e;
2875
3178
  }
3179
+ if (typeof user.email === "string") {
3180
+ await backfillActiveEmail(store, resolved.envName, user.email, user.user_id);
3181
+ }
2876
3182
  const env = {
2877
- name: current.name,
2878
- api_base: current.config.api_base
3183
+ name: resolved.envName,
3184
+ api_base: resolved.apiBase,
3185
+ account: typeof user.email === "string" ? user.email : resolved.email
2879
3186
  };
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
- );
3187
+ if (resolved.creds.actor) env.actor = resolved.creds.actor;
3188
+ if (resolved.creds.agent_label) env.agent_label = resolved.creds.agent_label;
3189
+ render({ kind: "whoami" }, { env, user, ...org ? { org } : {} });
2886
3190
  });
2887
3191
  function printLoggedOut() {
2888
3192
  process.stderr.write(dim('not logged in. run "wspc login".') + "\n");
@@ -2890,58 +3194,64 @@ function printLoggedOut() {
2890
3194
  }
2891
3195
 
2892
3196
  // src/handwritten/commands/config.ts
2893
- import { Command as Command39 } from "commander";
2894
- var configCommand = new Command39("config").description("Manage wspc local config");
3197
+ import { Command as Command46 } from "commander";
3198
+ var configCommand = new Command46("config").description("Manage wspc local config");
2895
3199
  registerRenderer("config_show", (data) => {
2896
3200
  const d = data;
2897
3201
  if (d.envs.length === 0) {
2898
3202
  process.stdout.write(dim(' no envs configured. run "wspc login".') + "\n");
2899
3203
  return;
2900
3204
  }
2901
- const headers = ["", "ENV", "API BASE", "ACTOR", "AUTH"];
3205
+ const headers = ["", "ENV", "API BASE", "ACTIVE ACCOUNT", "ACCOUNTS", "AUTH"];
2902
3206
  const rows = d.envs.map((e) => [
2903
3207
  e.name === d.current_env ? green("\u2713") : " ",
2904
3208
  e.name,
2905
3209
  e.api_base,
2906
- e.actor ?? dim("\u2014"),
3210
+ e.active_account ?? dim("\u2014"),
3211
+ String(e.accounts),
2907
3212
  e.auth === "none" ? dim("none") : e.auth
2908
3213
  ]);
2909
3214
  process.stdout.write(table(headers, rows));
2910
3215
  });
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();
3216
+ async function setConfigKey(store, key, value) {
2929
3217
  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`);
3218
+ const resolved = resolveAccount(c, { accountOverride: process.env.WSPC_ACCOUNT });
3219
+ const env = c.envs[resolved.envName];
3220
+ if (!env) throw new Error(`env "${resolved.envName}" not found`);
3221
+ const acct = env.accounts[resolved.email];
3222
+ if (!acct) throw new Error(`account "${resolved.email}" not found`);
2933
3223
  switch (key) {
2934
3224
  case "actor":
2935
3225
  if (value !== "user" && value !== "agent") throw new Error("actor must be 'user' or 'agent'");
2936
- env.actor = value;
3226
+ acct.actor = value;
2937
3227
  break;
2938
3228
  case "agent-label":
2939
- env.agent_label = value;
3229
+ acct.agent_label = value;
2940
3230
  break;
2941
3231
  default:
2942
3232
  throw new Error(`unknown config key: ${key}`);
2943
3233
  }
2944
3234
  await store.write(c);
3235
+ }
3236
+ configCommand.command("show").description("List configured envs (tokens redacted, current marked with \u2713)").action(async () => {
3237
+ const c = await new ConfigStore().read();
3238
+ const envs = Object.entries(c.envs ?? {}).map(([name, env]) => {
3239
+ const active = env.current_account ? env.accounts?.[env.current_account] : void 0;
3240
+ return {
3241
+ name,
3242
+ api_base: env.api_base,
3243
+ ...env.current_account !== void 0 ? { active_account: env.current_account } : {},
3244
+ accounts: Object.keys(env.accounts ?? {}).length,
3245
+ auth: active?.api_key ? "api_key" : active?.access_token ? "oauth" : "none"
3246
+ };
3247
+ });
3248
+ render(
3249
+ { kind: "config_show" },
3250
+ { ...c.current_env !== void 0 ? { current_env: c.current_env } : {}, envs }
3251
+ );
3252
+ });
3253
+ configCommand.command("set <key> <value>").description("Set a field on the active account (actor, agent-label, ...)").action(async (key, value) => {
3254
+ await setConfigKey(new ConfigStore(), key, value);
2945
3255
  process.stdout.write(`\u2713 set ${key}=${value}
2946
3256
  `);
2947
3257
  });
@@ -2955,8 +3265,61 @@ configCommand.command("use <env>").description("Switch current_env").action(asyn
2955
3265
  `);
2956
3266
  });
2957
3267
 
3268
+ // src/handwritten/commands/account.ts
3269
+ import { Command as Command47 } from "commander";
3270
+ async function listAccounts(store) {
3271
+ const c = await store.read();
3272
+ const envName = c.current_env;
3273
+ if (!envName || !c.envs[envName]) return [];
3274
+ const env = c.envs[envName];
3275
+ return Object.values(env.accounts ?? {}).map((a) => ({
3276
+ email: a.email,
3277
+ user_id: a.user_id,
3278
+ actor: a.actor,
3279
+ auth: a.api_key ? "api_key" : a.access_token ? "oauth" : "none",
3280
+ active: env.current_account === a.email
3281
+ }));
3282
+ }
3283
+ async function switchAccount(store, email) {
3284
+ const c = await store.read();
3285
+ const envName = c.current_env;
3286
+ if (!envName || !c.envs[envName]) throw new Error("no current env; run `wspc login` first");
3287
+ const env = c.envs[envName];
3288
+ if (!env.accounts?.[email]) {
3289
+ throw new Error(`no account '${email}' in env '${envName}'. Run \`wspc account ls\` or \`wspc login\`.`);
3290
+ }
3291
+ env.current_account = email;
3292
+ await store.write(c);
3293
+ }
3294
+ registerRenderer("account_ls", (data) => {
3295
+ const rows = data.accounts;
3296
+ if (rows.length === 0) {
3297
+ process.stdout.write(dim(' no accounts. run "wspc login".') + "\n");
3298
+ return;
3299
+ }
3300
+ const headers = ["", "EMAIL", "USER", "ACTOR", "AUTH"];
3301
+ const body = rows.map((r) => [
3302
+ r.active ? green("\u2713") : " ",
3303
+ r.email,
3304
+ r.user_id ?? dim("\u2014"),
3305
+ r.actor ?? dim("\u2014"),
3306
+ r.auth === "none" ? dim("none") : r.auth
3307
+ ]);
3308
+ process.stdout.write(table(headers, body));
3309
+ });
3310
+ var accountCommand = new Command47("account").description("Manage logged-in accounts");
3311
+ accountCommand.command("ls").description("List accounts in the current env (active marked with \u2713)").action(async () => {
3312
+ const accounts = await listAccounts(new ConfigStore());
3313
+ render({ kind: "account_ls" }, { accounts });
3314
+ });
3315
+ accountCommand.command("switch <email>").description("Set the active account for the current env").action(async (email) => {
3316
+ await switchAccount(new ConfigStore(), email);
3317
+ process.stdout.write(`\u2713 active account is now ${email}
3318
+ `);
3319
+ });
3320
+
2958
3321
  // src/handwritten/commands/todo-done.ts
2959
- import { Command as Command40 } from "commander";
3322
+ import { Command as Command48 } from "commander";
2960
3323
  var TODO_UPDATE_DISPLAY = {
2961
3324
  shape: "object",
2962
3325
  format: {
@@ -2974,7 +3337,7 @@ var TODO_UPDATE_DISPLAY = {
2974
3337
  deleted_at: "relative-time"
2975
3338
  }
2976
3339
  };
2977
- var todoDoneCommand = new Command40("done").description("Mark a todo done (sugar for `update <id> --status done`)").argument("<id>", "Todo id").action(async (id) => {
3340
+ var todoDoneCommand = new Command48("done").description("Mark a todo done (sugar for `update <id> --status done`)").argument("<id>", "Todo id").action(async (id) => {
2978
3341
  const client2 = await loadSdkClient();
2979
3342
  const result = await todoUpdate({
2980
3343
  client: client2._rawClient,
@@ -2993,7 +3356,7 @@ var todoDoneCommand = new Command40("done").description("Mark a todo done (sugar
2993
3356
  });
2994
3357
 
2995
3358
  // src/handwritten/commands/email/send.ts
2996
- import { Command as Command41 } from "commander";
3359
+ import { Command as Command49 } from "commander";
2997
3360
  import { readFile, stat } from "fs/promises";
2998
3361
  import { basename } from "path";
2999
3362
 
@@ -3051,7 +3414,7 @@ async function resolveAttachment(input) {
3051
3414
  `--attach ${input}: neither a readable file nor a valid <prefix>_<ulid>:<idx> reference.`
3052
3415
  );
3053
3416
  }
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) => {
3417
+ var sendCommand = new Command49("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
3418
  const isReply = Boolean(opts.reply);
3056
3419
  const to = opts.to;
3057
3420
  const attachInputs = opts.attach;
@@ -3138,7 +3501,7 @@ var sendCommand = new Command41("send").description("Send an outbound email").re
3138
3501
  });
3139
3502
 
3140
3503
  // src/handwritten/commands/email/attachment.ts
3141
- import { Command as Command42 } from "commander";
3504
+ import { Command as Command50 } from "commander";
3142
3505
  import { createWriteStream } from "fs";
3143
3506
  import { Readable } from "stream";
3144
3507
  import { pipeline } from "stream/promises";
@@ -3155,7 +3518,7 @@ function parseContentDispositionFilename(header) {
3155
3518
  }
3156
3519
 
3157
3520
  // 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) => {
3521
+ var attachmentCommand = new Command50("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
3522
  const idx = Number(idxArg);
3160
3523
  if (!Number.isInteger(idx) || idx < 0) {
3161
3524
  process.stderr.write(`<idx> must be a non-negative integer (got "${idxArg}")
@@ -3188,13 +3551,16 @@ var attachmentCommand = new Command42("attachment").description("Download an inb
3188
3551
 
3189
3552
  // src/cli.ts
3190
3553
  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";
3554
+ const program = new Command51().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) => {
3555
+ const globals = actionCommand.optsWithGlobals();
3556
+ if (globals.json) process.env.WSPC_OUTPUT = "json";
3557
+ if (globals.account) process.env.WSPC_ACCOUNT = String(globals.account);
3193
3558
  });
3194
3559
  program.addCommand(loginCommand);
3195
3560
  program.addCommand(logoutCommand);
3196
3561
  program.addCommand(whoamiCommand);
3197
3562
  program.addCommand(configCommand);
3563
+ program.addCommand(accountCommand);
3198
3564
  registerGeneratedCommands(program);
3199
3565
  const todo = program.commands.find((c) => c.name() === "todo");
3200
3566
  if (todo) todo.addCommand(todoDoneCommand);