@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.
- package/dist/index.js +207 -34
- 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
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
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
|
-
|
|
2857
|
-
|
|
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
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
body = JSON.parse(text2);
|
|
2863
|
-
} catch {
|
|
2864
|
-
body = text2;
|
|
2873
|
+
const text = await res.text();
|
|
2874
|
+
if (!text) {
|
|
2875
|
+
return {};
|
|
2865
2876
|
}
|
|
2866
|
-
|
|
2867
|
-
}
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
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.
|
|
3904
|
+
if (page.markdown) {
|
|
3732
3905
|
console.log();
|
|
3733
|
-
console.log(source_default.gray("
|
|
3734
|
-
console.log(page.
|
|
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.
|
|
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": "
|
|
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/
|
|
49
|
+
"url": "git+https://github.com/lex-inc/tokatsu.git"
|
|
50
50
|
}
|
|
51
51
|
}
|