@lex-inc/thoughtful 0.0.1 → 0.0.3

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.
Files changed (2) hide show
  1. package/dist/index.js +207 -34
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -2836,40 +2836,52 @@ class ThoughtfulClient {
2836
2836
  if (!skipAuth && this.config.accessToken) {
2837
2837
  headers["Authorization"] = `Bearer ${this.config.accessToken}`;
2838
2838
  }
2839
- const res = await fetch(`${this.config.apiUrl}${path2}`, {
2840
- ...fetchOptions,
2841
- headers
2842
- });
2843
- if (!res.ok) {
2844
- if (res.status === 401 && !skipAuth) {
2845
- const refreshed = await this.refreshTokens();
2846
- if (refreshed) {
2847
- headers["Authorization"] = `Bearer ${this.config.accessToken}`;
2848
- const retryRes = await fetch(`${this.config.apiUrl}${path2}`, {
2849
- ...fetchOptions,
2850
- headers
2851
- });
2852
- if (retryRes.ok) {
2853
- return retryRes.json();
2839
+ const controller = new AbortController;
2840
+ const timeoutId = setTimeout(() => controller.abort(), 120000);
2841
+ try {
2842
+ const res = await fetch(`${this.config.apiUrl}${path2}`, {
2843
+ ...fetchOptions,
2844
+ headers,
2845
+ signal: controller.signal
2846
+ });
2847
+ clearTimeout(timeoutId);
2848
+ if (!res.ok) {
2849
+ if (res.status === 401 && !skipAuth) {
2850
+ const refreshed = await this.refreshTokens();
2851
+ if (refreshed) {
2852
+ headers["Authorization"] = `Bearer ${this.config.accessToken}`;
2853
+ const retryRes = await fetch(`${this.config.apiUrl}${path2}`, {
2854
+ ...fetchOptions,
2855
+ headers
2856
+ });
2857
+ if (retryRes.ok) {
2858
+ return retryRes.json();
2859
+ }
2854
2860
  }
2861
+ clearAuth();
2862
+ throw new Error("Session expired. Please run 'thoughtful login' again.");
2855
2863
  }
2856
- clearAuth();
2857
- throw new Error("Session expired. Please run 'thoughtful login' again.");
2864
+ let body;
2865
+ const text2 = await res.text();
2866
+ try {
2867
+ body = JSON.parse(text2);
2868
+ } catch {
2869
+ body = text2;
2870
+ }
2871
+ throw new ApiError(res.status, res.statusText, body);
2858
2872
  }
2859
- let body;
2860
- const text2 = await res.text();
2861
- try {
2862
- body = JSON.parse(text2);
2863
- } catch {
2864
- body = text2;
2873
+ const text = await res.text();
2874
+ if (!text) {
2875
+ return {};
2865
2876
  }
2866
- throw new ApiError(res.status, res.statusText, body);
2867
- }
2868
- const text = await res.text();
2869
- if (!text) {
2870
- return {};
2877
+ return JSON.parse(text);
2878
+ } catch (error) {
2879
+ clearTimeout(timeoutId);
2880
+ if (error instanceof Error && error.name === "AbortError") {
2881
+ throw new Error("Request timed out after 2 minutes. The AI response may be taking longer than expected.");
2882
+ }
2883
+ throw error;
2871
2884
  }
2872
- return JSON.parse(text);
2873
2885
  }
2874
2886
  async sendVerificationCode(email) {
2875
2887
  return this.request("/api/auth/mobile/send-code", {
@@ -2878,6 +2890,13 @@ class ThoughtfulClient {
2878
2890
  skipAuth: true
2879
2891
  });
2880
2892
  }
2893
+ async signUp(data) {
2894
+ return this.request("/api/auth/mobile/signup", {
2895
+ method: "POST",
2896
+ body: JSON.stringify(data),
2897
+ skipAuth: true
2898
+ });
2899
+ }
2881
2900
  async verifyCode(email, code) {
2882
2901
  return this.request("/api/auth/mobile/verify-code", {
2883
2902
  method: "POST",
@@ -3207,6 +3226,145 @@ Examples:
3207
3226
  handleApiError(error);
3208
3227
  }
3209
3228
  });
3229
+ program2.command("signup").description("Create a new Thoughtful account").option("--email <email>", "Email address for signup").option("--name <name>", "Your name (optional)").option("--org <organization>", "Organization name").option("--code <code>", "Verification code (skips code prompt)").addHelpText("after", `
3230
+ Examples:
3231
+ $ thoughtful signup
3232
+ Email: alice@example.com
3233
+ Your name (optional): Alice Smith
3234
+ Organization name: Acme Corp
3235
+ Enter code: ******
3236
+
3237
+ $ thoughtful signup --email alice@example.com --org "Acme Corp"
3238
+ Verification code sent! Check your email.
3239
+ Enter code: ******
3240
+
3241
+ $ thoughtful signup --json
3242
+ {"success":true,"user":{...},"workspace":{...}}
3243
+ `).action(async (options) => {
3244
+ try {
3245
+ if (isLoggedIn()) {
3246
+ const config = loadConfig();
3247
+ if (isJson()) {
3248
+ outputJson({
3249
+ success: false,
3250
+ message: "Already logged in",
3251
+ email: config.user?.email
3252
+ });
3253
+ } else {
3254
+ log(c.yellow(`Already logged in as ${config.user?.email}. Use 'thoughtful logout' first to create a new account.`));
3255
+ }
3256
+ return;
3257
+ }
3258
+ const client = createClient();
3259
+ if (!isJson()) {
3260
+ log(c.blue("Create a Thoughtful Account"));
3261
+ log("");
3262
+ }
3263
+ let email = options.email;
3264
+ if (!email) {
3265
+ try {
3266
+ email = await prompt("Email: ", { required: true });
3267
+ } catch (error) {
3268
+ if (error instanceof Error) {
3269
+ throw new ValidationError(`Email is required. ${error.message} Provide --email flag for non-interactive mode.`);
3270
+ }
3271
+ throw error;
3272
+ }
3273
+ }
3274
+ if (!email) {
3275
+ throw new ValidationError("Email is required");
3276
+ }
3277
+ let name = options.name;
3278
+ if (!name) {
3279
+ try {
3280
+ name = await prompt("Your name (optional): ", { required: false });
3281
+ } catch {}
3282
+ }
3283
+ let firstName;
3284
+ let lastName;
3285
+ if (name) {
3286
+ const parts = name.trim().split(/\s+/);
3287
+ firstName = parts[0];
3288
+ lastName = parts.slice(1).join(" ") || undefined;
3289
+ }
3290
+ let organizationName = options.org;
3291
+ if (!organizationName) {
3292
+ try {
3293
+ organizationName = await prompt("Organization name: ", { required: true });
3294
+ } catch (error) {
3295
+ if (error instanceof Error) {
3296
+ throw new ValidationError(`Organization name is required. ${error.message} Provide --org flag for non-interactive mode.`);
3297
+ }
3298
+ throw error;
3299
+ }
3300
+ }
3301
+ if (!organizationName) {
3302
+ throw new ValidationError("Organization name is required");
3303
+ }
3304
+ if (!isJson()) {
3305
+ log(c.gray("Creating your account..."));
3306
+ }
3307
+ await client.signUp({
3308
+ email,
3309
+ firstName,
3310
+ lastName,
3311
+ organizationName
3312
+ });
3313
+ if (!isJson()) {
3314
+ log(c.green("Account created! Verification code sent to your email."));
3315
+ log("");
3316
+ }
3317
+ let code = options.code;
3318
+ if (!code) {
3319
+ try {
3320
+ code = await prompt("Enter code: ", { secure: true, required: true });
3321
+ } catch (error) {
3322
+ if (error instanceof Error) {
3323
+ throw new ValidationError(`Verification code is required. ${error.message} Provide --code flag for non-interactive mode.`);
3324
+ }
3325
+ throw error;
3326
+ }
3327
+ }
3328
+ if (!code) {
3329
+ throw new ValidationError("Verification code is required");
3330
+ }
3331
+ const result = await client.verifyCode(email, code);
3332
+ const expiresAt = new Date(Date.now() + 55 * 60 * 1000);
3333
+ updateConfig({
3334
+ accessToken: result.accessToken,
3335
+ refreshToken: result.refreshToken,
3336
+ tokenExpiresAt: expiresAt.toISOString(),
3337
+ activeOrgId: result.workspace.organizationId,
3338
+ activeWorkspaceId: result.workspace.id,
3339
+ user: {
3340
+ id: result.user.id,
3341
+ email: result.user.email,
3342
+ displayName: result.user.displayName
3343
+ }
3344
+ });
3345
+ if (isJson()) {
3346
+ outputJson({
3347
+ success: true,
3348
+ user: {
3349
+ id: result.user.id,
3350
+ email: result.user.email,
3351
+ displayName: result.user.displayName
3352
+ },
3353
+ workspace: {
3354
+ id: result.workspace.id,
3355
+ name: result.workspace.name
3356
+ }
3357
+ });
3358
+ } else {
3359
+ log("");
3360
+ log(c.green(`Welcome to Thoughtful, ${result.user.displayName || result.user.email}!`));
3361
+ log(c.gray(`Organization: ${organizationName}`));
3362
+ log(c.gray(`Workspace: ${result.workspace.name}`));
3363
+ }
3364
+ } catch (error) {
3365
+ handleApiError(error);
3366
+ }
3367
+ });
3210
3368
  program2.command("logout").description("Log out from Thoughtful").addHelpText("after", `
3211
3369
  Examples:
3212
3370
  $ thoughtful logout
@@ -3618,6 +3776,7 @@ Examples:
3618
3776
  $ thoughtful pages list
3619
3777
  $ thoughtful pages create "New Feature" --parent roadmap
3620
3778
  $ thoughtful pages get roadmap
3779
+ $ thoughtful pages get roadmap --markdown
3621
3780
  $ thoughtful pages search "quarterly goals"
3622
3781
  $ thoughtful pages update roadmap --status completed
3623
3782
  $ thoughtful pages delete old-draft --yes
@@ -3682,7 +3841,7 @@ Examples:
3682
3841
  handleApiError(error);
3683
3842
  }
3684
3843
  });
3685
- pages.command("get <slug>").description("Get page details").option("--json", "Output as JSON").addHelpText("after", `
3844
+ pages.command("get <slug>").description("Get page details").option("--markdown", "Output only the markdown content").option("--json", "Output as JSON").addHelpText("after", `
3686
3845
  Examples:
3687
3846
  $ thoughtful pages get roadmap
3688
3847
  Roadmap
@@ -3693,10 +3852,16 @@ Examples:
3693
3852
  Created: 1/15/2025, 10:30:00 AM
3694
3853
  Updated: 1/18/2025, 3:45:00 PM
3695
3854
 
3855
+ $ thoughtful pages get roadmap --markdown
3856
+ # Roadmap Overview
3857
+
3858
+ This document outlines our product roadmap...
3859
+
3696
3860
  $ thoughtful pages get roadmap --json
3697
- {"page":{"id":"pg_abc123","slug":"roadmap","title":"Roadmap",...}}
3861
+ {"page":{"id":"pg_abc123","slug":"roadmap","title":"Roadmap","markdown":"# Roadmap...",...}}
3698
3862
  `).action(async (slug, options) => {
3699
3863
  const json = options.json;
3864
+ const markdownOnly = options.markdown;
3700
3865
  try {
3701
3866
  if (!isLoggedIn()) {
3702
3867
  if (json) {
@@ -3713,6 +3878,14 @@ Examples:
3713
3878
  return;
3714
3879
  }
3715
3880
  const page = data.page;
3881
+ if (markdownOnly) {
3882
+ if (!page.markdown) {
3883
+ console.log(source_default.gray(`Page '${slug}' has no content`));
3884
+ return;
3885
+ }
3886
+ console.log(page.markdown);
3887
+ return;
3888
+ }
3716
3889
  console.log(source_default.blue(page.title));
3717
3890
  console.log();
3718
3891
  console.log(` ${source_default.gray("Slug:")} ${page.slug}`);
@@ -3728,10 +3901,10 @@ Examples:
3728
3901
  }
3729
3902
  console.log(` ${source_default.gray("Created:")} ${new Date(page.createdAt).toLocaleString()}`);
3730
3903
  console.log(` ${source_default.gray("Updated:")} ${new Date(page.updatedAt).toLocaleString()}`);
3731
- if (page.description) {
3904
+ if (page.markdown) {
3732
3905
  console.log();
3733
- console.log(source_default.gray("Description:"));
3734
- console.log(page.description);
3906
+ console.log(source_default.gray("Content:"));
3907
+ console.log(page.markdown);
3735
3908
  }
3736
3909
  } catch (error) {
3737
3910
  handleApiError(error);
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@lex-inc/thoughtful",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "CLI tool for interacting with your Thoughtful workspace",
5
5
  "type": "module",
6
6
  "bin": {
7
- "thoughtful": "./dist/index.js"
7
+ "thoughtful": "dist/index.js"
8
8
  },
9
9
  "main": "./dist/index.js",
10
10
  "files": [
@@ -46,6 +46,6 @@
46
46
  "license": "MIT",
47
47
  "repository": {
48
48
  "type": "git",
49
- "url": "https://github.com/tfl-inc/thoughtful"
49
+ "url": "git+https://github.com/lex-inc/tokatsu.git"
50
50
  }
51
51
  }