@wspc/cli 0.0.5 → 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 Command41 } 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
@@ -792,9 +792,14 @@ var createClient = (config = {}) => {
792
792
  };
793
793
 
794
794
  // src/generated/sdk/client.gen.ts
795
- var client = createClient(createConfig());
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,26 +814,78 @@ 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",
815
834
  ...options
816
835
  });
836
+ var orgUpdate = (options) => (options?.client ?? client).patch({
837
+ security: [{ scheme: "bearer", type: "http" }],
838
+ url: "/auth/me/org",
839
+ ...options,
840
+ headers: {
841
+ "Content-Type": "application/json",
842
+ ...options?.headers
843
+ }
844
+ });
845
+ var inviteGet = (options) => (options.client ?? client).get({
846
+ security: [{ scheme: "bearer", type: "http" }],
847
+ url: "/auth/invites/{id}",
848
+ ...options
849
+ });
817
850
  var authMe = (options) => (options?.client ?? client).get({
818
851
  security: [{ scheme: "bearer", type: "http" }],
819
852
  url: "/auth/me",
820
853
  ...options
821
854
  });
855
+ var invitesList = (options) => (options?.client ?? client).get({
856
+ security: [{ scheme: "bearer", type: "http" }],
857
+ url: "/auth/invites",
858
+ ...options
859
+ });
822
860
  var orgMembersList = (options) => (options?.client ?? client).get({
823
861
  security: [{ scheme: "bearer", type: "http" }],
824
862
  url: "/auth/me/org/members",
825
863
  ...options
826
864
  });
865
+ var inviteReject = (options) => (options.client ?? client).post({
866
+ security: [{ scheme: "bearer", type: "http" }],
867
+ url: "/auth/invites/{id}/reject",
868
+ ...options
869
+ });
827
870
  var keyRevoke = (options) => (options.client ?? client).delete({
828
871
  security: [{ scheme: "bearer", type: "http" }],
829
872
  url: "/auth/keys/{id}",
830
873
  ...options
831
874
  });
875
+ var keyUpdate = (options) => (options.client ?? client).patch({
876
+ security: [{ scheme: "bearer", type: "http" }],
877
+ url: "/auth/keys/{id}",
878
+ ...options,
879
+ headers: {
880
+ "Content-Type": "application/json",
881
+ ...options.headers
882
+ }
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
+ });
832
889
  var eventList = (options) => (options?.client ?? client).get({
833
890
  security: [{ scheme: "bearer", type: "http" }],
834
891
  url: "/calendar/events",
@@ -1030,7 +1087,62 @@ var todoUpdate = (options) => (options.client ?? client).patch({
1030
1087
  import { promises as fs } from "fs";
1031
1088
  import { homedir } from "os";
1032
1089
  import { join } from "path";
1090
+ var LEGACY_ACCOUNT_KEY = "(default)";
1033
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
+ }
1034
1146
  var ConfigStore = class {
1035
1147
  configDir;
1036
1148
  configFile;
@@ -1041,11 +1153,7 @@ var ConfigStore = class {
1041
1153
  async read() {
1042
1154
  try {
1043
1155
  const buf = await fs.readFile(this.configFile, "utf8");
1044
- const parsed = JSON.parse(buf);
1045
- if (typeof parsed !== "object" || parsed === null || typeof parsed.envs !== "object") {
1046
- return { envs: {} };
1047
- }
1048
- return parsed;
1156
+ return normalize(JSON.parse(buf));
1049
1157
  } catch (e) {
1050
1158
  if (e.code === "ENOENT") return { envs: {} };
1051
1159
  throw e;
@@ -1070,9 +1178,9 @@ var ConfigStore = class {
1070
1178
  };
1071
1179
 
1072
1180
  // src/version.ts
1073
- var VERSION = "0.0.5";
1074
- var SPEC_SHA = "601a9f59";
1075
- var SPEC_FETCHED_AT = "2026-05-27T14:26:43.644Z";
1181
+ var VERSION = "0.0.7";
1182
+ var SPEC_SHA = "c579a55a";
1183
+ var SPEC_FETCHED_AT = "2026-06-03T06:34:38.606Z";
1076
1184
  var API_BASE = "https://api.wspc.ai";
1077
1185
 
1078
1186
  // src/index.ts
@@ -1136,45 +1244,78 @@ function createAuthInterceptor(mode) {
1136
1244
  };
1137
1245
  }
1138
1246
 
1139
- // src/handwritten/auth/load-sdk-client.ts
1140
- async function loadSdkClient(opts = {}) {
1141
- const store = opts.store ?? new ConfigStore();
1142
- const current = await store.currentEnv();
1143
- if (!current) {
1144
- throw new Error("not logged in: run `wspc login` first");
1145
- }
1146
- const env = current.config;
1147
- if (!env.api_key && !(env.access_token && env.refresh_token)) {
1148
- throw new Error("not logged in: run `wspc login` first");
1149
- }
1150
- let interceptor;
1151
- if (env.api_key) {
1152
- interceptor = createAuthInterceptor({ apiKey: env.api_key });
1153
- } else {
1154
- 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]) {
1155
1259
  throw new Error(
1156
- "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\`.`
1157
1261
  );
1158
1262
  }
1159
- interceptor = createAuthInterceptor({
1160
- accessToken: env.access_token,
1161
- refreshToken: env.refresh_token,
1162
- baseUrl: env.api_base,
1163
- clientId: env.client_id,
1164
- onTokenRefresh: async ({ accessToken, refreshToken, expiresAt }) => {
1165
- const cfg = await store.read();
1166
- const e = cfg.envs[current.name];
1167
- if (!e) return;
1168
- e.access_token = accessToken;
1169
- e.refresh_token = refreshToken;
1170
- e.access_token_expires_at = expiresAt;
1171
- await store.write(cfg);
1172
- }
1173
- });
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);
1174
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
+ );
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);
1175
1316
  const rawClient = createClient(
1176
1317
  createConfig({
1177
- baseUrl: env.api_base,
1318
+ baseUrl: resolved.apiBase,
1178
1319
  fetch: ((input, init) => interceptor.execute(new Request(input, init)))
1179
1320
  })
1180
1321
  );
@@ -1182,39 +1323,11 @@ async function loadSdkClient(opts = {}) {
1182
1323
  }
1183
1324
  async function loadAuthedFetch(opts = {}) {
1184
1325
  const store = opts.store ?? new ConfigStore();
1185
- const current = await store.currentEnv();
1186
- if (!current) throw new Error("not logged in: run `wspc login` first");
1187
- const env = current.config;
1188
- if (!env.api_key && !(env.access_token && env.refresh_token)) {
1189
- throw new Error("not logged in: run `wspc login` first");
1190
- }
1191
- let interceptor;
1192
- if (env.api_key) {
1193
- interceptor = createAuthInterceptor({ apiKey: env.api_key });
1194
- } else {
1195
- if (!env.client_id) {
1196
- throw new Error(
1197
- "config has OAuth tokens but no client_id \u2014 run `wspc logout && wspc login` to re-register"
1198
- );
1199
- }
1200
- interceptor = createAuthInterceptor({
1201
- accessToken: env.access_token,
1202
- refreshToken: env.refresh_token,
1203
- baseUrl: env.api_base,
1204
- clientId: env.client_id,
1205
- onTokenRefresh: async ({ accessToken, refreshToken, expiresAt }) => {
1206
- const cfg = await store.read();
1207
- const e = cfg.envs[current.name];
1208
- if (!e) return;
1209
- e.access_token = accessToken;
1210
- e.refresh_token = refreshToken;
1211
- e.access_token_expires_at = expiresAt;
1212
- await store.write(cfg);
1213
- }
1214
- });
1215
- }
1326
+ const config = await store.read();
1327
+ const resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
1328
+ const interceptor = buildInterceptor(store, resolved);
1216
1329
  const authedFetch = (input, init) => interceptor.execute(new Request(input, init));
1217
- return { fetch: authedFetch, baseUrl: env.api_base };
1330
+ return { fetch: authedFetch, baseUrl: resolved.apiBase };
1218
1331
  }
1219
1332
 
1220
1333
  // src/handwritten/output/primitives.ts
@@ -1599,8 +1712,29 @@ function formatCell(value, fmt, colorMap) {
1599
1712
  }
1600
1713
  }
1601
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
+
1602
1735
  // src/generated/cli/keys/create.ts
1603
- 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) => {
1604
1738
  const client2 = await loadSdkClient();
1605
1739
  const result = await keyCreate({
1606
1740
  client: client2._rawClient,
@@ -1620,8 +1754,8 @@ var keyCreateCommand = new Command("create").description("Create a new API key (
1620
1754
  });
1621
1755
 
1622
1756
  // src/generated/cli/keys/ls.ts
1623
- import { Command as Command2 } from "commander";
1624
- 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) => {
1625
1759
  const client2 = await loadSdkClient();
1626
1760
  const result = await keyList({
1627
1761
  client: client2._rawClient
@@ -1637,9 +1771,48 @@ var keyListCommand = new Command2("ls").description("List active API keys").acti
1637
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);
1638
1772
  });
1639
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
+
1640
1813
  // src/generated/cli/org/show.ts
1641
- import { Command as Command3 } from "commander";
1642
- 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) => {
1643
1816
  const client2 = await loadSdkClient();
1644
1817
  const result = await orgGet({
1645
1818
  client: client2._rawClient
@@ -1655,9 +1828,51 @@ var orgGetCommand = new Command3("show").description("Get the authenticated user
1655
1828
  render({ kind: "org_get", 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);
1656
1829
  });
1657
1830
 
1831
+ // src/generated/cli/org/rename.ts
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) => {
1834
+ const client2 = await loadSdkClient();
1835
+ const result = await orgUpdate({
1836
+ client: client2._rawClient,
1837
+ body: {
1838
+ name: opts.name
1839
+ }
1840
+ });
1841
+ if (result.error || !result.response?.ok) {
1842
+ process.stderr.write(
1843
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1844
+ `
1845
+ );
1846
+ process.exitCode = 1;
1847
+ return;
1848
+ }
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);
1850
+ });
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
+
1658
1873
  // src/generated/cli/auth/me.ts
1659
- import { Command as Command4 } from "commander";
1660
- var authMeCommand = new Command4("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) => {
1661
1876
  const client2 = await loadSdkClient();
1662
1877
  const result = await authMe({
1663
1878
  client: client2._rawClient
@@ -1673,9 +1888,27 @@ var authMeCommand = new Command4("me").description("Fetch the user identified by
1673
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);
1674
1889
  });
1675
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
+
1676
1909
  // src/generated/cli/org/members.ts
1677
- import { Command as Command5 } from "commander";
1678
- var orgMembersListCommand = new Command5("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) => {
1679
1912
  const client2 = await loadSdkClient();
1680
1913
  const result = await orgMembersList({
1681
1914
  client: client2._rawClient,
@@ -1695,9 +1928,30 @@ var orgMembersListCommand = new Command5("members").description("List members of
1695
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);
1696
1929
  });
1697
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
+
1698
1952
  // src/generated/cli/keys/rm.ts
1699
- import { Command as Command6 } from "commander";
1700
- var keyRevokeCommand = new Command6("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) => {
1701
1955
  const client2 = await loadSdkClient();
1702
1956
  const result = await keyRevoke({
1703
1957
  client: client2._rawClient,
@@ -1716,8 +1970,53 @@ var keyRevokeCommand = new Command6("rm").description("Soft-revoke an API key").
1716
1970
  render({ kind: "key_revoke", display: void 0 }, result.data);
1717
1971
  });
1718
1972
 
1973
+ // src/generated/cli/keys/edit.ts
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) => {
1976
+ const client2 = await loadSdkClient();
1977
+ const result = await keyUpdate({
1978
+ client: client2._rawClient,
1979
+ path: {
1980
+ id
1981
+ },
1982
+ body: {
1983
+ label: opts.label
1984
+ }
1985
+ });
1986
+ if (result.error || !result.response?.ok) {
1987
+ process.stderr.write(
1988
+ `HTTP ${result.response?.status ?? "?"}: ${JSON.stringify(result.error ?? "unknown error", null, 2)}
1989
+ `
1990
+ );
1991
+ process.exitCode = 1;
1992
+ return;
1993
+ }
1994
+ render({ kind: "key_update", display: void 0 }, result.data);
1995
+ });
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
+
1719
2018
  // src/generated/cli/event/add.ts
1720
- import { Command as Command7 } from "commander";
2019
+ import { Command as Command16 } from "commander";
1721
2020
 
1722
2021
  // src/handwritten/utils/parse-time.ts
1723
2022
  import * as chrono from "chrono-node";
@@ -1803,7 +2102,7 @@ function parseAttendee(input) {
1803
2102
  }
1804
2103
 
1805
2104
  // src/generated/cli/event/add.ts
1806
- var eventCreateCommand = new Command7("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) => {
1807
2106
  memo.push(val);
1808
2107
  return memo;
1809
2108
  }, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (title, opts) => {
@@ -1852,8 +2151,8 @@ var eventCreateCommand = new Command7("add").description("Schedule a calendar ev
1852
2151
  });
1853
2152
 
1854
2153
  // src/generated/cli/event/ls.ts
1855
- import { Command as Command8 } from "commander";
1856
- var eventListCommand = new Command8("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) => {
1857
2156
  const zone = resolveTimezone(opts.tz);
1858
2157
  let fromValue;
1859
2158
  if (opts.from !== void 0) {
@@ -1890,8 +2189,8 @@ var eventListCommand = new Command8("ls").description("List calendar events").op
1890
2189
  });
1891
2190
 
1892
2191
  // src/generated/cli/event/rm.ts
1893
- import { Command as Command9 } from "commander";
1894
- var eventDeleteCommand = new Command9("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) => {
1895
2194
  const client2 = await loadSdkClient();
1896
2195
  const result = await eventDelete({
1897
2196
  client: client2._rawClient,
@@ -1914,8 +2213,8 @@ var eventDeleteCommand = new Command9("rm").description("Soft-delete a calendar
1914
2213
  });
1915
2214
 
1916
2215
  // src/generated/cli/event/show.ts
1917
- import { Command as Command10 } from "commander";
1918
- var eventGetCommand = new Command10("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) => {
1919
2218
  const client2 = await loadSdkClient();
1920
2219
  const result = await eventGet({
1921
2220
  client: client2._rawClient,
@@ -1938,8 +2237,8 @@ var eventGetCommand = new Command10("show").description("Get a calendar event by
1938
2237
  });
1939
2238
 
1940
2239
  // src/generated/cli/event/set.ts
1941
- import { Command as Command11 } from "commander";
1942
- var eventUpdateCommand = new Command11("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) => {
1943
2242
  memo.push(val);
1944
2243
  return memo;
1945
2244
  }, []).option("--all-day", "all_day").option("--tz <zone>", "IANA timezone for relative time parsing").action(async (id, opts) => {
@@ -1992,8 +2291,8 @@ var eventUpdateCommand = new Command11("set").description("Update a calendar eve
1992
2291
  });
1993
2292
 
1994
2293
  // src/generated/cli/event/ics.ts
1995
- import { Command as Command12 } from "commander";
1996
- var eventIcsDownloadCommand = new Command12("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) => {
1997
2296
  const client2 = await loadSdkClient();
1998
2297
  const result = await eventIcsDownload({
1999
2298
  client: client2._rawClient,
@@ -2013,8 +2312,8 @@ var eventIcsDownloadCommand = new Command12("ics").description("Download event a
2013
2312
  });
2014
2313
 
2015
2314
  // src/generated/cli/alias/add.ts
2016
- import { Command as Command13 } from "commander";
2017
- var emailAliasCreateCommand = new Command13("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) => {
2018
2317
  const client2 = await loadSdkClient();
2019
2318
  const result = await emailAliasCreate({
2020
2319
  client: client2._rawClient,
@@ -2034,8 +2333,8 @@ var emailAliasCreateCommand = new Command13("add").description("Create a receivi
2034
2333
  });
2035
2334
 
2036
2335
  // src/generated/cli/alias/ls.ts
2037
- import { Command as Command14 } from "commander";
2038
- var emailAliasListCommand = new Command14("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) => {
2039
2338
  const client2 = await loadSdkClient();
2040
2339
  const result = await emailAliasList({
2041
2340
  client: client2._rawClient,
@@ -2055,8 +2354,8 @@ var emailAliasListCommand = new Command14("ls").description("List the caller's a
2055
2354
  });
2056
2355
 
2057
2356
  // src/generated/cli/alias/rm.ts
2058
- import { Command as Command15 } from "commander";
2059
- var emailAliasDeleteCommand = new Command15("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) => {
2060
2359
  const client2 = await loadSdkClient();
2061
2360
  const result = await emailAliasDelete({
2062
2361
  client: client2._rawClient,
@@ -2076,8 +2375,8 @@ var emailAliasDeleteCommand = new Command15("rm").description("Soft-delete an al
2076
2375
  });
2077
2376
 
2078
2377
  // src/generated/cli/email/rm.ts
2079
- import { Command as Command16 } from "commander";
2080
- var emailDeleteCommand = new Command16("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) => {
2081
2380
  const idRaw = id;
2082
2381
  const ids = idRaw.length > 0 ? idRaw : void 0;
2083
2382
  const client2 = await loadSdkClient();
@@ -2099,8 +2398,8 @@ var emailDeleteCommand = new Command16("rm").description("Soft-delete inbound em
2099
2398
  });
2100
2399
 
2101
2400
  // src/generated/cli/email/show.ts
2102
- import { Command as Command17 } from "commander";
2103
- var emailGetCommand = new Command17("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) => {
2104
2403
  const client2 = await loadSdkClient();
2105
2404
  const result = await emailGet({
2106
2405
  client: client2._rawClient,
@@ -2124,8 +2423,8 @@ var emailGetCommand = new Command17("show").description("Get an inbound email by
2124
2423
  });
2125
2424
 
2126
2425
  // src/generated/cli/email/ls.ts
2127
- import { Command as Command18 } from "commander";
2128
- var emailListCommand = new Command18("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) => {
2129
2428
  const client2 = await loadSdkClient();
2130
2429
  const result = await emailList({
2131
2430
  client: client2._rawClient,
@@ -2150,8 +2449,8 @@ var emailListCommand = new Command18("ls").description("List inbound emails").op
2150
2449
  });
2151
2450
 
2152
2451
  // src/generated/cli/email/read.ts
2153
- import { Command as Command19 } from "commander";
2154
- var emailMarkReadCommand = new Command19("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) => {
2155
2454
  const idRaw = id;
2156
2455
  const ids = idRaw.length > 0 ? idRaw : void 0;
2157
2456
  const client2 = await loadSdkClient();
@@ -2173,8 +2472,8 @@ var emailMarkReadCommand = new Command19("read").description("Mark inbound email
2173
2472
  });
2174
2473
 
2175
2474
  // src/generated/cli/email/unread.ts
2176
- import { Command as Command20 } from "commander";
2177
- var emailMarkUnreadCommand = new Command20("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) => {
2178
2477
  const idRaw = id;
2179
2478
  const ids = idRaw.length > 0 ? idRaw : void 0;
2180
2479
  const client2 = await loadSdkClient();
@@ -2196,8 +2495,8 @@ var emailMarkUnreadCommand = new Command20("unread").description("Mark inbound e
2196
2495
  });
2197
2496
 
2198
2497
  // src/generated/cli/push/config/rm.ts
2199
- import { Command as Command21 } from "commander";
2200
- var pushConfigDeleteCommand = new Command21("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) => {
2201
2500
  const client2 = await loadSdkClient();
2202
2501
  const result = await pushConfigDelete({
2203
2502
  client: client2._rawClient,
@@ -2217,8 +2516,8 @@ var pushConfigDeleteCommand = new Command21("rm").description("Remove a push tra
2217
2516
  });
2218
2517
 
2219
2518
  // src/generated/cli/push/config/set.ts
2220
- import { Command as Command22 } from "commander";
2221
- var pushConfigSetCommand = new Command22("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) => {
2222
2521
  const client2 = await loadSdkClient();
2223
2522
  const result = await pushConfigSet({
2224
2523
  client: client2._rawClient,
@@ -2241,8 +2540,8 @@ var pushConfigSetCommand = new Command22("set").description("Register or update
2241
2540
  });
2242
2541
 
2243
2542
  // src/generated/cli/push/config/show.ts
2244
- import { Command as Command23 } from "commander";
2245
- var pushConfigGetCommand = new Command23("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) => {
2246
2545
  const client2 = await loadSdkClient();
2247
2546
  const result = await pushConfigGet({
2248
2547
  client: client2._rawClient
@@ -2259,8 +2558,8 @@ var pushConfigGetCommand = new Command23("show").description("List the caller's
2259
2558
  });
2260
2559
 
2261
2560
  // src/generated/cli/push/test.ts
2262
- import { Command as Command24 } from "commander";
2263
- var pushTestCommand = new Command24("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) => {
2264
2563
  const client2 = await loadSdkClient();
2265
2564
  const result = await pushTest({
2266
2565
  client: client2._rawClient,
@@ -2283,8 +2582,8 @@ var pushTestCommand = new Command24("test").description("Send a test push notifi
2283
2582
  });
2284
2583
 
2285
2584
  // src/generated/cli/todo/project/add.ts
2286
- import { Command as Command25 } from "commander";
2287
- var projectCreateCommand = new Command25("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) => {
2288
2587
  const client2 = await loadSdkClient();
2289
2588
  const result = await projectCreate({
2290
2589
  client: client2._rawClient,
@@ -2305,8 +2604,8 @@ var projectCreateCommand = new Command25("add").description("Create a project").
2305
2604
  });
2306
2605
 
2307
2606
  // src/generated/cli/todo/project/ls.ts
2308
- import { Command as Command26 } from "commander";
2309
- var projectListCommand = new Command26("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) => {
2310
2609
  const client2 = await loadSdkClient();
2311
2610
  const result = await projectList({
2312
2611
  client: client2._rawClient,
@@ -2326,8 +2625,8 @@ var projectListCommand = new Command26("ls").description("List projects").option
2326
2625
  });
2327
2626
 
2328
2627
  // src/generated/cli/todo/rule/ls.ts
2329
- import { Command as Command27 } from "commander";
2330
- var recurrenceRuleListCommand = new Command27("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) => {
2331
2630
  const client2 = await loadSdkClient();
2332
2631
  const result = await recurrenceRuleList({
2333
2632
  client: client2._rawClient,
@@ -2348,8 +2647,8 @@ var recurrenceRuleListCommand = new Command27("ls").description("List recurring
2348
2647
  });
2349
2648
 
2350
2649
  // src/generated/cli/todo/add.ts
2351
- import { Command as Command28 } from "commander";
2352
- var todoCreateCommand = new Command28("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) => {
2353
2652
  const client2 = await loadSdkClient();
2354
2653
  const result = await todoCreate({
2355
2654
  client: client2._rawClient,
@@ -2376,8 +2675,8 @@ var todoCreateCommand = new Command28("add").description("Create a todo").argume
2376
2675
  });
2377
2676
 
2378
2677
  // src/generated/cli/todo/ls.ts
2379
- import { Command as Command29 } from "commander";
2380
- var todoListCommand = new Command29("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) => {
2381
2680
  const client2 = await loadSdkClient();
2382
2681
  const result = await todoList({
2383
2682
  client: client2._rawClient,
@@ -2408,8 +2707,8 @@ var todoListCommand = new Command29("ls").description("List todos with filters")
2408
2707
  });
2409
2708
 
2410
2709
  // src/generated/cli/todo/type/ls.ts
2411
- import { Command as Command30 } from "commander";
2412
- var todoTypeListCommand = new Command30("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) => {
2413
2712
  const client2 = await loadSdkClient();
2414
2713
  const result = await todoTypeList({
2415
2714
  client: client2._rawClient,
@@ -2431,8 +2730,8 @@ var todoTypeListCommand = new Command30("ls").description("List todo types").opt
2431
2730
  });
2432
2731
 
2433
2732
  // src/generated/cli/todo/rm.ts
2434
- import { Command as Command31 } from "commander";
2435
- var todoDeleteCommand = new Command31("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) => {
2436
2735
  const client2 = await loadSdkClient();
2437
2736
  const result = await todoDelete({
2438
2737
  client: client2._rawClient,
@@ -2456,8 +2755,8 @@ var todoDeleteCommand = new Command31("rm").description("Soft-delete a todo").ar
2456
2755
  });
2457
2756
 
2458
2757
  // src/generated/cli/todo/show.ts
2459
- import { Command as Command32 } from "commander";
2460
- var todoGetCommand = new Command32("show").description("Get a todo by id").argument("<id>", "id").option("--include-deleted <value>", "include_deleted").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) => {
2461
2760
  const client2 = await loadSdkClient();
2462
2761
  const result = await todoGet({
2463
2762
  client: client2._rawClient,
@@ -2465,7 +2764,8 @@ var todoGetCommand = new Command32("show").description("Get a todo by id").argum
2465
2764
  id
2466
2765
  },
2467
2766
  query: {
2468
- include_deleted: opts.includeDeleted
2767
+ include_deleted: opts.includeDeleted,
2768
+ include_orphan_fields: opts.includeOrphanFields
2469
2769
  }
2470
2770
  });
2471
2771
  if (result.error || !result.response?.ok) {
@@ -2480,8 +2780,8 @@ var todoGetCommand = new Command32("show").description("Get a todo by id").argum
2480
2780
  });
2481
2781
 
2482
2782
  // src/generated/cli/todo/update.ts
2483
- import { Command as Command33 } from "commander";
2484
- var todoUpdateCommand = new Command33("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) => {
2485
2785
  const client2 = await loadSdkClient();
2486
2786
  const result = await todoUpdate({
2487
2787
  client: client2._rawClient,
@@ -2513,15 +2813,26 @@ var todoUpdateCommand = new Command33("update").description("Update a todo").arg
2513
2813
 
2514
2814
  // src/generated/cli/index.ts
2515
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);
2516
2820
  const root_keys = root.command("keys").description("keys commands");
2517
2821
  root_keys.addCommand(keyCreateCommand);
2518
2822
  root_keys.addCommand(keyListCommand);
2519
2823
  root_keys.addCommand(keyRevokeCommand);
2824
+ root_keys.addCommand(keyUpdateCommand);
2520
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);
2521
2830
  root_org.addCommand(orgGetCommand);
2831
+ root_org.addCommand(orgUpdateCommand);
2522
2832
  root_org.addCommand(orgMembersListCommand);
2523
2833
  const root_auth = root.command("auth").description("auth commands");
2524
2834
  root_auth.addCommand(authMeCommand);
2835
+ root.addCommand(invitesListCommand);
2525
2836
  const root_event = root.command("event").description("event commands");
2526
2837
  root_event.addCommand(eventCreateCommand);
2527
2838
  root_event.addCommand(eventListCommand);
@@ -2561,7 +2872,7 @@ function registerGeneratedCommands(root) {
2561
2872
  }
2562
2873
 
2563
2874
  // src/handwritten/commands/login.ts
2564
- import { Command as Command34 } from "commander";
2875
+ import { Command as Command43 } from "commander";
2565
2876
 
2566
2877
  // src/handwritten/auth/device-flow.ts
2567
2878
  var DEFAULT_SLEEP = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -2642,23 +2953,62 @@ async function ensureClientId(opts) {
2642
2953
  const body = await res.json();
2643
2954
  if (!body.client_id) throw new Error("client_registration_failed: missing client_id in response");
2644
2955
  const fresh = await opts.store.read();
2645
- const env = fresh.envs[opts.envName] ?? { api_base: opts.baseUrl };
2956
+ const env = fresh.envs[opts.envName] ?? { api_base: opts.baseUrl, accounts: {} };
2646
2957
  env.client_id = body.client_id;
2647
2958
  fresh.envs[opts.envName] = env;
2648
2959
  await opts.store.write(fresh);
2649
2960
  return body.client_id;
2650
2961
  }
2651
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
+
2652
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
+ }
2653
2989
  async function runLogin(opts) {
2654
2990
  const envName = opts.envName ?? "prod";
2655
2991
  const now = opts.now ?? Date.now;
2656
- const c = await opts.store.read();
2992
+ const me = opts.fetchMe ?? ((o) => fetchMe(o));
2657
2993
  if (opts.apiKey) {
2658
- c.current_env = envName;
2659
- c.envs[envName] = { ...c.envs[envName] ?? {}, api_base: opts.baseUrl, api_key: opts.apiKey };
2660
- await opts.store.write(c);
2661
- 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}"`);
2662
3012
  return;
2663
3013
  }
2664
3014
  const ensureClient = opts.ensureClient ?? ((env2) => ensureClientId({ store: opts.store, envName: env2, baseUrl: opts.baseUrl }));
@@ -2679,24 +3029,29 @@ async function runLogin(opts) {
2679
3029
  `);
2680
3030
  }
2681
3031
  });
2682
- const cFinal = await opts.store.read();
2683
- cFinal.current_env = envName;
2684
- cFinal.envs[envName] = {
2685
- ...cFinal.envs[envName] ?? {},
2686
- 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,
2687
3040
  refresh_token: result.refresh_token,
2688
3041
  access_token: result.access_token,
2689
3042
  access_token_expires_at: now() + result.expires_in * 1e3
2690
3043
  };
2691
- const env = cFinal.envs[envName];
2692
- if (env && "api_key" in env) delete env.api_key;
2693
- await opts.store.write(cFinal);
2694
- opts.output.writeJson({ event: "login_success" });
2695
- 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}"`);
2696
3051
  }
2697
3052
 
2698
3053
  // src/handwritten/commands/login.ts
2699
- var loginCommand = new Command34("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) => {
2700
3055
  const store = new ConfigStore();
2701
3056
  const output = opts.json ? { write: () => {
2702
3057
  }, writeJson: (e) => process.stdout.write(JSON.stringify(e) + "\n") } : {
@@ -2713,51 +3068,61 @@ var loginCommand = new Command34("login").description("Log in via OAuth device f
2713
3068
  });
2714
3069
 
2715
3070
  // src/handwritten/commands/logout.ts
2716
- import { Command as Command35 } from "commander";
3071
+ import { Command as Command44 } from "commander";
2717
3072
 
2718
3073
  // src/handwritten/auth/logout.ts
2719
3074
  async function runLogout(opts) {
2720
- const envName = opts.envName;
2721
3075
  const c = await opts.store.read();
2722
- const targetEnv = envName ?? c.current_env;
2723
- if (!targetEnv || !c.envs[targetEnv]) return;
2724
- const env = c.envs[targetEnv];
2725
- delete env.refresh_token;
2726
- delete env.access_token;
2727
- delete env.access_token_expires_at;
2728
- 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
+ }
2729
3094
  await opts.store.write(c);
3095
+ return { removed: [target], newActive: env.current_account };
2730
3096
  }
2731
3097
 
2732
3098
  // src/handwritten/commands/logout.ts
2733
- var logoutCommand = new Command35("logout").description("Clear stored credentials for the current environment").action(async () => {
2734
- await runLogout({ store: new ConfigStore() });
2735
- 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
+ `);
2736
3109
  });
2737
3110
 
2738
3111
  // src/handwritten/commands/whoami.ts
2739
- import { Command as Command36 } from "commander";
3112
+ import { Command as Command45 } from "commander";
2740
3113
  var ENV_DISPLAY = {
2741
3114
  shape: "object",
2742
- fields: ["name", "api_base", "actor", "agent_label"]
3115
+ fields: ["name", "api_base", "account", "actor", "agent_label"]
2743
3116
  };
2744
3117
  var USER_DISPLAY = {
2745
3118
  shape: "object",
2746
3119
  fields: ["user_id", "email", "display_name", "api_key_id"],
2747
- format: {
2748
- user_id: "id-short",
2749
- api_key_id: "id-short"
2750
- }
3120
+ format: { user_id: "id-short", api_key_id: "id-short" }
2751
3121
  };
2752
3122
  var ORG_DISPLAY = {
2753
3123
  shape: "object",
2754
3124
  fields: ["id", "name", "created_at", "updated_at"],
2755
- format: {
2756
- id: "id-short",
2757
- name: "truncate",
2758
- created_at: "relative-time",
2759
- updated_at: "relative-time"
2760
- }
3125
+ format: { id: "id-short", name: "truncate", created_at: "relative-time", updated_at: "relative-time" }
2761
3126
  };
2762
3127
  registerRenderer("whoami", (data) => {
2763
3128
  const d = data;
@@ -2770,15 +3135,19 @@ registerRenderer("whoami", (data) => {
2770
3135
  renderObject(d.org, ORG_DISPLAY);
2771
3136
  }
2772
3137
  });
2773
- var whoamiCommand = new Command36("whoami").description("Show the active env, signed-in user, and organization").action(async () => {
2774
- const store = new ConfigStore();
2775
- const current = await store.currentEnv();
2776
- if (!current) {
2777
- printLoggedOut();
2778
- 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);
2779
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;
2780
3148
  let sdkClient;
2781
3149
  try {
3150
+ resolved = resolveAccount(config, { accountOverride: process.env.WSPC_ACCOUNT });
2782
3151
  sdkClient = await loadSdkClient({ store });
2783
3152
  } catch {
2784
3153
  printLoggedOut();
@@ -2807,16 +3176,17 @@ var whoamiCommand = new Command36("whoami").description("Show the active env, si
2807
3176
  }
2808
3177
  throw e;
2809
3178
  }
3179
+ if (typeof user.email === "string") {
3180
+ await backfillActiveEmail(store, resolved.envName, user.email, user.user_id);
3181
+ }
2810
3182
  const env = {
2811
- name: current.name,
2812
- 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
2813
3186
  };
2814
- if (current.config.actor) env.actor = current.config.actor;
2815
- if (current.config.agent_label) env.agent_label = current.config.agent_label;
2816
- render(
2817
- { kind: "whoami" },
2818
- { env, user, ...org ? { org } : {} }
2819
- );
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 } : {} });
2820
3190
  });
2821
3191
  function printLoggedOut() {
2822
3192
  process.stderr.write(dim('not logged in. run "wspc login".') + "\n");
@@ -2824,58 +3194,64 @@ function printLoggedOut() {
2824
3194
  }
2825
3195
 
2826
3196
  // src/handwritten/commands/config.ts
2827
- import { Command as Command37 } from "commander";
2828
- var configCommand = new Command37("config").description("Manage wspc local config");
3197
+ import { Command as Command46 } from "commander";
3198
+ var configCommand = new Command46("config").description("Manage wspc local config");
2829
3199
  registerRenderer("config_show", (data) => {
2830
3200
  const d = data;
2831
3201
  if (d.envs.length === 0) {
2832
3202
  process.stdout.write(dim(' no envs configured. run "wspc login".') + "\n");
2833
3203
  return;
2834
3204
  }
2835
- const headers = ["", "ENV", "API BASE", "ACTOR", "AUTH"];
3205
+ const headers = ["", "ENV", "API BASE", "ACTIVE ACCOUNT", "ACCOUNTS", "AUTH"];
2836
3206
  const rows = d.envs.map((e) => [
2837
3207
  e.name === d.current_env ? green("\u2713") : " ",
2838
3208
  e.name,
2839
3209
  e.api_base,
2840
- e.actor ?? dim("\u2014"),
3210
+ e.active_account ?? dim("\u2014"),
3211
+ String(e.accounts),
2841
3212
  e.auth === "none" ? dim("none") : e.auth
2842
3213
  ]);
2843
3214
  process.stdout.write(table(headers, rows));
2844
3215
  });
2845
- configCommand.command("show").description("List configured envs (tokens redacted, current marked with \u2713)").action(async () => {
2846
- const c = await new ConfigStore().read();
2847
- const envs = Object.entries(c.envs ?? {}).map(([name, env]) => ({
2848
- name,
2849
- api_base: env.api_base,
2850
- ...env.actor !== void 0 ? { actor: env.actor } : {},
2851
- auth: env.api_key ? "api_key" : env.access_token ? "oauth" : "none"
2852
- }));
2853
- render(
2854
- { kind: "config_show" },
2855
- {
2856
- ...c.current_env !== void 0 ? { current_env: c.current_env } : {},
2857
- envs
2858
- }
2859
- );
2860
- });
2861
- configCommand.command("set <key> <value>").description("Set a config field on current env (actor, agent-label, ...)").action(async (key, value) => {
2862
- const store = new ConfigStore();
3216
+ async function setConfigKey(store, key, value) {
2863
3217
  const c = await store.read();
2864
- if (!c.current_env) throw new Error("no current env; run `wspc login` first");
2865
- const env = c.envs[c.current_env];
2866
- 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`);
2867
3223
  switch (key) {
2868
3224
  case "actor":
2869
3225
  if (value !== "user" && value !== "agent") throw new Error("actor must be 'user' or 'agent'");
2870
- env.actor = value;
3226
+ acct.actor = value;
2871
3227
  break;
2872
3228
  case "agent-label":
2873
- env.agent_label = value;
3229
+ acct.agent_label = value;
2874
3230
  break;
2875
3231
  default:
2876
3232
  throw new Error(`unknown config key: ${key}`);
2877
3233
  }
2878
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);
2879
3255
  process.stdout.write(`\u2713 set ${key}=${value}
2880
3256
  `);
2881
3257
  });
@@ -2889,8 +3265,61 @@ configCommand.command("use <env>").description("Switch current_env").action(asyn
2889
3265
  `);
2890
3266
  });
2891
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
+
2892
3321
  // src/handwritten/commands/todo-done.ts
2893
- import { Command as Command38 } from "commander";
3322
+ import { Command as Command48 } from "commander";
2894
3323
  var TODO_UPDATE_DISPLAY = {
2895
3324
  shape: "object",
2896
3325
  format: {
@@ -2908,7 +3337,7 @@ var TODO_UPDATE_DISPLAY = {
2908
3337
  deleted_at: "relative-time"
2909
3338
  }
2910
3339
  };
2911
- var todoDoneCommand = new Command38("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) => {
2912
3341
  const client2 = await loadSdkClient();
2913
3342
  const result = await todoUpdate({
2914
3343
  client: client2._rawClient,
@@ -2927,7 +3356,7 @@ var todoDoneCommand = new Command38("done").description("Mark a todo done (sugar
2927
3356
  });
2928
3357
 
2929
3358
  // src/handwritten/commands/email/send.ts
2930
- import { Command as Command39 } from "commander";
3359
+ import { Command as Command49 } from "commander";
2931
3360
  import { readFile, stat } from "fs/promises";
2932
3361
  import { basename } from "path";
2933
3362
 
@@ -2985,7 +3414,7 @@ async function resolveAttachment(input) {
2985
3414
  `--attach ${input}: neither a readable file nor a valid <prefix>_<ulid>:<idx> reference.`
2986
3415
  );
2987
3416
  }
2988
- var sendCommand = new Command39("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) => {
2989
3418
  const isReply = Boolean(opts.reply);
2990
3419
  const to = opts.to;
2991
3420
  const attachInputs = opts.attach;
@@ -3072,7 +3501,7 @@ var sendCommand = new Command39("send").description("Send an outbound email").re
3072
3501
  });
3073
3502
 
3074
3503
  // src/handwritten/commands/email/attachment.ts
3075
- import { Command as Command40 } from "commander";
3504
+ import { Command as Command50 } from "commander";
3076
3505
  import { createWriteStream } from "fs";
3077
3506
  import { Readable } from "stream";
3078
3507
  import { pipeline } from "stream/promises";
@@ -3089,7 +3518,7 @@ function parseContentDispositionFilename(header) {
3089
3518
  }
3090
3519
 
3091
3520
  // src/handwritten/commands/email/attachment.ts
3092
- var attachmentCommand = new Command40("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) => {
3093
3522
  const idx = Number(idxArg);
3094
3523
  if (!Number.isInteger(idx) || idx < 0) {
3095
3524
  process.stderr.write(`<idx> must be a non-negative integer (got "${idxArg}")
@@ -3122,13 +3551,16 @@ var attachmentCommand = new Command40("attachment").description("Download an inb
3122
3551
 
3123
3552
  // src/cli.ts
3124
3553
  function buildProgram() {
3125
- const program = new Command41().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) => {
3126
- 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);
3127
3558
  });
3128
3559
  program.addCommand(loginCommand);
3129
3560
  program.addCommand(logoutCommand);
3130
3561
  program.addCommand(whoamiCommand);
3131
3562
  program.addCommand(configCommand);
3563
+ program.addCommand(accountCommand);
3132
3564
  registerGeneratedCommands(program);
3133
3565
  const todo = program.commands.find((c) => c.name() === "todo");
3134
3566
  if (todo) todo.addCommand(todoDoneCommand);