@tostudy-ai/cli 0.16.10 → 0.16.12
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 +282 -221
- package/dist/cli.js.map +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1058,8 +1058,9 @@ async function cliApiFetch(url2, token, init) {
|
|
|
1058
1058
|
if (!response.ok) {
|
|
1059
1059
|
const code = typeof body.error === "string" && body.error.length > 0 ? body.error : void 0;
|
|
1060
1060
|
const friendly = typeof body.message === "string" && body.message.length > 0 ? body.message : void 0;
|
|
1061
|
+
const unauthenticated = response.status === 401 ? "Sess\xE3o inv\xE1lida ou expirada. Rode: tostudy login" : void 0;
|
|
1061
1062
|
throw new CliApiError(
|
|
1062
|
-
friendly ?? code ?? `API error ${response.status}`,
|
|
1063
|
+
friendly ?? unauthenticated ?? code ?? `API error ${response.status}`,
|
|
1063
1064
|
response.status,
|
|
1064
1065
|
code
|
|
1065
1066
|
);
|
|
@@ -2617,11 +2618,18 @@ var init_login = __esm({
|
|
|
2617
2618
|
}
|
|
2618
2619
|
if (opts.manual) {
|
|
2619
2620
|
console.log(`
|
|
2620
|
-
|
|
2621
|
-
console.log(`
|
|
2621
|
+
Login sem browser nesta m\xE1quina:`);
|
|
2622
|
+
console.log(` 1. Em um computador com browser, acesse:`);
|
|
2623
|
+
console.log(` ${apiUrl}/api/cli/auth/authorize`);
|
|
2624
|
+
console.log(
|
|
2625
|
+
` 2. Ap\xF3s autorizar, o browser tenta abrir http://localhost:9876/callback?code=...`
|
|
2626
|
+
);
|
|
2627
|
+
console.log(
|
|
2628
|
+
` e falha (n\xE3o h\xE1 CLI nesse computador). Copie o valor de "code" da barra de endere\xE7o.`
|
|
2629
|
+
);
|
|
2630
|
+
console.log(` 3. Em at\xE9 5 minutos, volte aqui e rode:`);
|
|
2631
|
+
console.log(` tostudy login --code <code>
|
|
2622
2632
|
`);
|
|
2623
|
-
console.log(" Ap\xF3s autorizar, o browser ser\xE1 redirecionado e o login ser\xE1 conclu\xEDdo.");
|
|
2624
|
-
console.log(" Certifique-se de rodar este comando sem --manual para o fluxo autom\xE1tico.\n");
|
|
2625
2633
|
return;
|
|
2626
2634
|
}
|
|
2627
2635
|
console.log("\n Abrindo browser para autentica\xE7\xE3o...\n");
|
|
@@ -2829,18 +2837,6 @@ var init_errors_en_us = __esm({
|
|
|
2829
2837
|
});
|
|
2830
2838
|
|
|
2831
2839
|
// src/errors/index.ts
|
|
2832
|
-
import fs6 from "node:fs";
|
|
2833
|
-
import path7 from "node:path";
|
|
2834
|
-
function readStoredLocale() {
|
|
2835
|
-
try {
|
|
2836
|
-
const p = path7.join(getConfigDir(), "config.json");
|
|
2837
|
-
if (!fs6.existsSync(p)) return null;
|
|
2838
|
-
const { locale } = JSON.parse(fs6.readFileSync(p, "utf-8"));
|
|
2839
|
-
return locale === "pt-BR" || locale === "en-US" ? locale : null;
|
|
2840
|
-
} catch {
|
|
2841
|
-
return null;
|
|
2842
|
-
}
|
|
2843
|
-
}
|
|
2844
2840
|
function resolveLocale() {
|
|
2845
2841
|
if (_cachedLocale !== null) return _cachedLocale;
|
|
2846
2842
|
const argv = process.argv;
|
|
@@ -2852,8 +2848,8 @@ function resolveLocale() {
|
|
|
2852
2848
|
return val;
|
|
2853
2849
|
}
|
|
2854
2850
|
}
|
|
2855
|
-
const stored =
|
|
2856
|
-
if (stored) {
|
|
2851
|
+
const stored = process.env["TOSTUDY_LOCALE"];
|
|
2852
|
+
if (stored === "pt-BR" || stored === "en-US") {
|
|
2857
2853
|
_cachedLocale = stored;
|
|
2858
2854
|
return stored;
|
|
2859
2855
|
}
|
|
@@ -2888,7 +2884,6 @@ var BUNDLES, _cachedLocale;
|
|
|
2888
2884
|
var init_errors = __esm({
|
|
2889
2885
|
"src/errors/index.ts"() {
|
|
2890
2886
|
"use strict";
|
|
2891
|
-
init_config_dir();
|
|
2892
2887
|
init_errors_pt_br();
|
|
2893
2888
|
init_errors_en_us();
|
|
2894
2889
|
BUNDLES = {
|
|
@@ -2902,12 +2897,12 @@ var init_errors = __esm({
|
|
|
2902
2897
|
// src/workspace/workspace-marker.ts
|
|
2903
2898
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
2904
2899
|
import os4 from "node:os";
|
|
2905
|
-
import
|
|
2900
|
+
import path7 from "node:path";
|
|
2906
2901
|
function resolveMarkerPath(workspacePath) {
|
|
2907
|
-
if (
|
|
2908
|
-
return
|
|
2902
|
+
if (path7.basename(workspacePath) === ".tostudy") {
|
|
2903
|
+
return path7.join(workspacePath, "workspace.json");
|
|
2909
2904
|
}
|
|
2910
|
-
return
|
|
2905
|
+
return path7.join(workspacePath, ".tostudy", "workspace.json");
|
|
2911
2906
|
}
|
|
2912
2907
|
async function readWorkspaceMarker(workspacePath) {
|
|
2913
2908
|
const filePath = resolveMarkerPath(workspacePath);
|
|
@@ -2925,13 +2920,13 @@ async function readWorkspaceMarker(workspacePath) {
|
|
|
2925
2920
|
}
|
|
2926
2921
|
}
|
|
2927
2922
|
async function writeWorkspaceMarker(workspacePath, input2, options = {}) {
|
|
2928
|
-
const homeDir =
|
|
2929
|
-
const resolvedWorkspace =
|
|
2930
|
-
if (resolvedWorkspace === homeDir || homeDir.startsWith(resolvedWorkspace +
|
|
2923
|
+
const homeDir = path7.resolve(options.homeDir ?? os4.homedir());
|
|
2924
|
+
const resolvedWorkspace = path7.resolve(workspacePath);
|
|
2925
|
+
if (resolvedWorkspace === homeDir || homeDir.startsWith(resolvedWorkspace + path7.sep)) {
|
|
2931
2926
|
throw new Error(getErrors().workspaceRefusedAtHome);
|
|
2932
2927
|
}
|
|
2933
2928
|
const filePath = resolveMarkerPath(workspacePath);
|
|
2934
|
-
const dir =
|
|
2929
|
+
const dir = path7.dirname(filePath);
|
|
2935
2930
|
if (!existsSync3(dir)) {
|
|
2936
2931
|
mkdirSync3(dir, { recursive: true });
|
|
2937
2932
|
}
|
|
@@ -2968,7 +2963,7 @@ __export(workspace_state_exports, {
|
|
|
2968
2963
|
});
|
|
2969
2964
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2970
2965
|
import os5 from "node:os";
|
|
2971
|
-
import
|
|
2966
|
+
import path8 from "node:path";
|
|
2972
2967
|
async function readWorkspaceState(workspacePath) {
|
|
2973
2968
|
const marker = await readWorkspaceMarker(workspacePath);
|
|
2974
2969
|
if (!marker) return null;
|
|
@@ -2997,13 +2992,13 @@ async function readWorkspaceState(workspacePath) {
|
|
|
2997
2992
|
}
|
|
2998
2993
|
}
|
|
2999
2994
|
async function findWorkspaceState(startCwd = process.cwd(), homeDir = os5.homedir()) {
|
|
3000
|
-
const home =
|
|
3001
|
-
let current =
|
|
2995
|
+
const home = path8.resolve(homeDir);
|
|
2996
|
+
let current = path8.resolve(startCwd);
|
|
3002
2997
|
while (true) {
|
|
3003
2998
|
if (current === home) return null;
|
|
3004
2999
|
const state = await readWorkspaceState(current);
|
|
3005
3000
|
if (state) return { state, workspacePath: current };
|
|
3006
|
-
const parent =
|
|
3001
|
+
const parent = path8.dirname(current);
|
|
3007
3002
|
if (parent === current) return null;
|
|
3008
3003
|
current = parent;
|
|
3009
3004
|
}
|
|
@@ -3072,7 +3067,7 @@ __export(course_state_exports, {
|
|
|
3072
3067
|
setCourseWorkspacePath: () => setCourseWorkspacePath,
|
|
3073
3068
|
setLastInitCourseId: () => setLastInitCourseId
|
|
3074
3069
|
});
|
|
3075
|
-
import
|
|
3070
|
+
import fs6 from "node:fs";
|
|
3076
3071
|
async function getCourseOnboardingState(courseId, configDir) {
|
|
3077
3072
|
const state = readCourseOnboardingState(configDir);
|
|
3078
3073
|
return state[courseId] ?? null;
|
|
@@ -3094,7 +3089,7 @@ async function saveCourseLearnerProfile(course, learnerProfile, artifacts, confi
|
|
|
3094
3089
|
}
|
|
3095
3090
|
async function clearAllCourseOnboarding(configDir) {
|
|
3096
3091
|
const onboardingPath = getCourseOnboardingPath(configDir);
|
|
3097
|
-
if (
|
|
3092
|
+
if (fs6.existsSync(onboardingPath)) fs6.unlinkSync(onboardingPath);
|
|
3098
3093
|
}
|
|
3099
3094
|
var init_course_state = __esm({
|
|
3100
3095
|
"src/onboarding/course-state.ts"() {
|
|
@@ -3137,14 +3132,14 @@ __export(resolve_exports, {
|
|
|
3137
3132
|
resolveVaultPath: () => resolveVaultPath,
|
|
3138
3133
|
resolveWorkspace: () => resolveWorkspace
|
|
3139
3134
|
});
|
|
3140
|
-
import
|
|
3141
|
-
import
|
|
3135
|
+
import fs7 from "node:fs/promises";
|
|
3136
|
+
import path9 from "node:path";
|
|
3142
3137
|
import os6 from "node:os";
|
|
3143
3138
|
async function resolveWorkspace(courseTitle, basePath = DEFAULT_BASE) {
|
|
3144
3139
|
const slug = courseSlug(courseTitle);
|
|
3145
|
-
const candidate =
|
|
3140
|
+
const candidate = path9.join(basePath, slug);
|
|
3146
3141
|
try {
|
|
3147
|
-
await
|
|
3142
|
+
await fs7.access(path9.join(candidate, ".ana-config.json"));
|
|
3148
3143
|
return { found: true, workspacePath: candidate, source: "default" };
|
|
3149
3144
|
} catch {
|
|
3150
3145
|
return { found: false, workspacePath: null };
|
|
@@ -3154,49 +3149,49 @@ async function isCwdWorkspace(cwd = process.cwd()) {
|
|
|
3154
3149
|
return await resolveCwdWorkspacePath(cwd) !== null;
|
|
3155
3150
|
}
|
|
3156
3151
|
async function resolveCwdWorkspacePath(cwd = process.cwd()) {
|
|
3157
|
-
const tostudyDir =
|
|
3152
|
+
const tostudyDir = path9.join(cwd, ".tostudy");
|
|
3158
3153
|
try {
|
|
3159
|
-
const stat = await
|
|
3154
|
+
const stat = await fs7.stat(tostudyDir);
|
|
3160
3155
|
if (stat.isDirectory()) return tostudyDir;
|
|
3161
3156
|
} catch {
|
|
3162
3157
|
}
|
|
3163
3158
|
try {
|
|
3164
|
-
await
|
|
3159
|
+
await fs7.access(path9.join(cwd, ".ana-config.json"));
|
|
3165
3160
|
return cwd;
|
|
3166
3161
|
} catch {
|
|
3167
3162
|
return null;
|
|
3168
3163
|
}
|
|
3169
3164
|
}
|
|
3170
3165
|
async function findCwdWorkspaceUpwards(startCwd = process.cwd(), homeDir = os6.homedir()) {
|
|
3171
|
-
const home =
|
|
3172
|
-
let current =
|
|
3166
|
+
const home = path9.resolve(homeDir);
|
|
3167
|
+
let current = path9.resolve(startCwd);
|
|
3173
3168
|
while (true) {
|
|
3174
3169
|
if (current === home) return null;
|
|
3175
3170
|
const direct = await resolveCwdWorkspacePath(current);
|
|
3176
3171
|
if (direct) return direct;
|
|
3177
|
-
const parent =
|
|
3172
|
+
const parent = path9.dirname(current);
|
|
3178
3173
|
if (parent === current) return null;
|
|
3179
3174
|
current = parent;
|
|
3180
3175
|
}
|
|
3181
3176
|
}
|
|
3182
3177
|
function resolveVaultPath(workspacePath, slug) {
|
|
3183
|
-
const base =
|
|
3184
|
-
return
|
|
3178
|
+
const base = path9.basename(workspacePath) === ".tostudy" ? path9.dirname(workspacePath) : workspacePath;
|
|
3179
|
+
return path9.join(base, `vault-${slug}`);
|
|
3185
3180
|
}
|
|
3186
3181
|
function cliWorkspacePaths(workspacePath, courseTitle) {
|
|
3187
|
-
const base =
|
|
3182
|
+
const base = path9.basename(workspacePath) === ".tostudy" ? path9.dirname(workspacePath) : workspacePath;
|
|
3188
3183
|
return { workspace: base, vault: resolveVaultPath(workspacePath, courseSlug(courseTitle)) };
|
|
3189
3184
|
}
|
|
3190
3185
|
async function findExistingVault(workspacePath, slug) {
|
|
3191
3186
|
const slugged = resolveVaultPath(workspacePath, slug);
|
|
3192
3187
|
try {
|
|
3193
|
-
await
|
|
3188
|
+
await fs7.access(path9.join(slugged, ".ana-vault.json"));
|
|
3194
3189
|
return slugged;
|
|
3195
3190
|
} catch {
|
|
3196
3191
|
}
|
|
3197
|
-
const legacy =
|
|
3192
|
+
const legacy = path9.join(workspacePath, "vault");
|
|
3198
3193
|
try {
|
|
3199
|
-
await
|
|
3194
|
+
await fs7.access(path9.join(legacy, ".ana-vault.json"));
|
|
3200
3195
|
return legacy;
|
|
3201
3196
|
} catch {
|
|
3202
3197
|
return null;
|
|
@@ -3209,7 +3204,7 @@ async function resolveEffectiveWorkspace(courseTitle, storedPath, cwd = process.
|
|
|
3209
3204
|
}
|
|
3210
3205
|
if (storedPath) {
|
|
3211
3206
|
try {
|
|
3212
|
-
await
|
|
3207
|
+
await fs7.access(path9.join(storedPath, ".ana-config.json"));
|
|
3213
3208
|
return { found: true, workspacePath: storedPath, source: "stored" };
|
|
3214
3209
|
} catch {
|
|
3215
3210
|
}
|
|
@@ -3230,37 +3225,50 @@ var init_resolve = __esm({
|
|
|
3230
3225
|
"src/workspace/resolve.ts"() {
|
|
3231
3226
|
"use strict";
|
|
3232
3227
|
init_slug();
|
|
3233
|
-
DEFAULT_BASE =
|
|
3228
|
+
DEFAULT_BASE = path9.join(os6.homedir(), "study");
|
|
3234
3229
|
courseSlug = slugify;
|
|
3235
3230
|
resolveActiveCourseWithOverride = resolveActiveCourseFromWorkspace;
|
|
3236
3231
|
}
|
|
3237
3232
|
});
|
|
3238
3233
|
|
|
3239
3234
|
// src/auth/guards.ts
|
|
3235
|
+
var guards_exports = {};
|
|
3236
|
+
__export(guards_exports, {
|
|
3237
|
+
requireActiveCourse: () => requireActiveCourse,
|
|
3238
|
+
requireSession: () => requireSession
|
|
3239
|
+
});
|
|
3240
3240
|
async function refreshCliSession(session, configDir) {
|
|
3241
|
+
let response;
|
|
3241
3242
|
try {
|
|
3242
|
-
|
|
3243
|
+
response = await fetch(`${session.apiUrl}/api/cli/auth/refresh`, {
|
|
3243
3244
|
method: "POST",
|
|
3244
3245
|
headers: { "Content-Type": "application/json" },
|
|
3245
3246
|
body: JSON.stringify({ refreshToken: session.refreshToken })
|
|
3246
3247
|
});
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
const data = await response.json();
|
|
3252
|
-
const refreshed = {
|
|
3253
|
-
...session,
|
|
3254
|
-
token: data.token,
|
|
3255
|
-
refreshToken: data.refreshToken,
|
|
3256
|
-
expiresAt: data.expiresAt
|
|
3257
|
-
};
|
|
3258
|
-
await saveSession(refreshed, configDir);
|
|
3259
|
-
return refreshed;
|
|
3260
|
-
} catch {
|
|
3248
|
+
} catch (err) {
|
|
3249
|
+
return { status: "unavailable", reason: err instanceof Error ? err.message : String(err) };
|
|
3250
|
+
}
|
|
3251
|
+
if (response.status === 401 || response.status === 403) {
|
|
3261
3252
|
await clearSessionArtifacts(configDir);
|
|
3262
|
-
return
|
|
3253
|
+
return { status: "rejected" };
|
|
3254
|
+
}
|
|
3255
|
+
if (!response.ok) {
|
|
3256
|
+
return { status: "unavailable", reason: `HTTP ${response.status}` };
|
|
3257
|
+
}
|
|
3258
|
+
let data;
|
|
3259
|
+
try {
|
|
3260
|
+
data = await response.json();
|
|
3261
|
+
} catch (err) {
|
|
3262
|
+
return { status: "unavailable", reason: err instanceof Error ? err.message : String(err) };
|
|
3263
3263
|
}
|
|
3264
|
+
const refreshed = {
|
|
3265
|
+
...session,
|
|
3266
|
+
token: data.token,
|
|
3267
|
+
refreshToken: data.refreshToken,
|
|
3268
|
+
expiresAt: data.expiresAt
|
|
3269
|
+
};
|
|
3270
|
+
await saveSession(refreshed, configDir);
|
|
3271
|
+
return { status: "ok", session: refreshed };
|
|
3264
3272
|
}
|
|
3265
3273
|
async function requireSession(configDir) {
|
|
3266
3274
|
const session = await getSession(configDir);
|
|
@@ -3270,12 +3278,17 @@ async function requireSession(configDir) {
|
|
|
3270
3278
|
}
|
|
3271
3279
|
const expiresAt = new Date(session.expiresAt);
|
|
3272
3280
|
if (expiresAt < /* @__PURE__ */ new Date()) {
|
|
3273
|
-
const
|
|
3274
|
-
if (
|
|
3281
|
+
const outcome = await refreshCliSession(session, configDir);
|
|
3282
|
+
if (outcome.status === "ok") return outcome.session;
|
|
3283
|
+
if (outcome.status === "rejected") {
|
|
3275
3284
|
process.stderr.write("Erro: Sess\xE3o expirada. Rode: tostudy login\n");
|
|
3276
3285
|
process.exit(2);
|
|
3277
3286
|
}
|
|
3278
|
-
|
|
3287
|
+
process.stderr.write(
|
|
3288
|
+
`Erro: N\xE3o foi poss\xEDvel renovar a sess\xE3o (${outcome.reason}). Sua sess\xE3o foi mantida \u2014 verifique a conex\xE3o e tente de novo.
|
|
3289
|
+
`
|
|
3290
|
+
);
|
|
3291
|
+
process.exit(4);
|
|
3279
3292
|
}
|
|
3280
3293
|
return session;
|
|
3281
3294
|
}
|
|
@@ -3426,7 +3439,7 @@ var CLI_VERSION;
|
|
|
3426
3439
|
var init_version = __esm({
|
|
3427
3440
|
"src/version.ts"() {
|
|
3428
3441
|
"use strict";
|
|
3429
|
-
CLI_VERSION = true ? "0.16.
|
|
3442
|
+
CLI_VERSION = true ? "0.16.12" : "0.7.1";
|
|
3430
3443
|
}
|
|
3431
3444
|
});
|
|
3432
3445
|
|
|
@@ -3440,13 +3453,13 @@ __export(update_checker_exports, {
|
|
|
3440
3453
|
readCache: () => readCache,
|
|
3441
3454
|
writeCache: () => writeCache
|
|
3442
3455
|
});
|
|
3443
|
-
import
|
|
3444
|
-
import
|
|
3456
|
+
import fs8 from "node:fs";
|
|
3457
|
+
import path10 from "node:path";
|
|
3445
3458
|
function readCache(configDir) {
|
|
3446
3459
|
try {
|
|
3447
|
-
const p =
|
|
3448
|
-
if (!
|
|
3449
|
-
return JSON.parse(
|
|
3460
|
+
const p = path10.join(configDir ?? getConfigDir(), CACHE_FILE);
|
|
3461
|
+
if (!fs8.existsSync(p)) return null;
|
|
3462
|
+
return JSON.parse(fs8.readFileSync(p, "utf-8"));
|
|
3450
3463
|
} catch {
|
|
3451
3464
|
return null;
|
|
3452
3465
|
}
|
|
@@ -3454,8 +3467,8 @@ function readCache(configDir) {
|
|
|
3454
3467
|
function writeCache(cache, configDir) {
|
|
3455
3468
|
try {
|
|
3456
3469
|
const dir = configDir ?? getConfigDir();
|
|
3457
|
-
|
|
3458
|
-
|
|
3470
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
3471
|
+
fs8.writeFileSync(path10.join(dir, CACHE_FILE), JSON.stringify(cache));
|
|
3459
3472
|
} catch {
|
|
3460
3473
|
}
|
|
3461
3474
|
}
|
|
@@ -3525,17 +3538,17 @@ var init_update_checker = __esm({
|
|
|
3525
3538
|
});
|
|
3526
3539
|
|
|
3527
3540
|
// src/learner-brief/cache.ts
|
|
3528
|
-
import
|
|
3529
|
-
import
|
|
3541
|
+
import fs9 from "node:fs";
|
|
3542
|
+
import path11 from "node:path";
|
|
3530
3543
|
function resolveCachePath(configDir) {
|
|
3531
|
-
return
|
|
3544
|
+
return path11.join(configDir, "student-brief.json");
|
|
3532
3545
|
}
|
|
3533
3546
|
async function readBriefCache(configDir) {
|
|
3534
3547
|
const dir = configDir ?? getConfigDir();
|
|
3535
3548
|
const p = resolveCachePath(dir);
|
|
3536
|
-
if (!
|
|
3549
|
+
if (!fs9.existsSync(p)) return null;
|
|
3537
3550
|
try {
|
|
3538
|
-
const raw =
|
|
3551
|
+
const raw = fs9.readFileSync(p, "utf-8");
|
|
3539
3552
|
return JSON.parse(raw);
|
|
3540
3553
|
} catch {
|
|
3541
3554
|
return null;
|
|
@@ -3543,8 +3556,8 @@ async function readBriefCache(configDir) {
|
|
|
3543
3556
|
}
|
|
3544
3557
|
async function writeBriefCache(configDir, cache) {
|
|
3545
3558
|
const dir = configDir ?? getConfigDir();
|
|
3546
|
-
|
|
3547
|
-
|
|
3559
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
3560
|
+
fs9.writeFileSync(resolveCachePath(dir), JSON.stringify(cache, null, 2), { mode: 384 });
|
|
3548
3561
|
}
|
|
3549
3562
|
var init_cache = __esm({
|
|
3550
3563
|
"src/learner-brief/cache.ts"() {
|
|
@@ -3554,23 +3567,23 @@ var init_cache = __esm({
|
|
|
3554
3567
|
});
|
|
3555
3568
|
|
|
3556
3569
|
// src/tutor-persona/cache.ts
|
|
3557
|
-
import
|
|
3558
|
-
import
|
|
3570
|
+
import fs10 from "node:fs";
|
|
3571
|
+
import path12 from "node:path";
|
|
3559
3572
|
function resolveCachePath2(configDir) {
|
|
3560
|
-
return
|
|
3573
|
+
return path12.join(configDir, "tutor-personalities.json");
|
|
3561
3574
|
}
|
|
3562
3575
|
function readAll(configDir) {
|
|
3563
3576
|
const p = resolveCachePath2(configDir);
|
|
3564
|
-
if (!
|
|
3577
|
+
if (!fs10.existsSync(p)) return {};
|
|
3565
3578
|
try {
|
|
3566
|
-
return JSON.parse(
|
|
3579
|
+
return JSON.parse(fs10.readFileSync(p, "utf-8"));
|
|
3567
3580
|
} catch {
|
|
3568
3581
|
return {};
|
|
3569
3582
|
}
|
|
3570
3583
|
}
|
|
3571
3584
|
function writeAll(configDir, cache) {
|
|
3572
|
-
|
|
3573
|
-
|
|
3585
|
+
fs10.mkdirSync(configDir, { recursive: true });
|
|
3586
|
+
fs10.writeFileSync(resolveCachePath2(configDir), JSON.stringify(cache, null, 2), { mode: 384 });
|
|
3574
3587
|
}
|
|
3575
3588
|
async function readPersonaCacheForCourse(configDir, courseId) {
|
|
3576
3589
|
const dir = configDir ?? getConfigDir();
|
|
@@ -4385,6 +4398,7 @@ var init_select = __esm({
|
|
|
4385
4398
|
interactive: isInteractiveTerminal(opts.json)
|
|
4386
4399
|
});
|
|
4387
4400
|
let pipelineResult = null;
|
|
4401
|
+
let pipelineError = null;
|
|
4388
4402
|
try {
|
|
4389
4403
|
pipelineResult = await resolveAndGenerate(
|
|
4390
4404
|
{ courseId: detail.courseId, enrollmentId },
|
|
@@ -4395,9 +4409,8 @@ var init_select = __esm({
|
|
|
4395
4409
|
}
|
|
4396
4410
|
);
|
|
4397
4411
|
} catch (err) {
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
});
|
|
4412
|
+
pipelineError = err instanceof Error ? err.message : String(err);
|
|
4413
|
+
logger8.warn("Failed to run instruction pipeline", { error: pipelineError });
|
|
4401
4414
|
}
|
|
4402
4415
|
const slugMatch = pipelineResult?.wroteFiles.find((f) => f.startsWith(".claude/commands/"))?.match(/tostudy-(.+)\.md$/);
|
|
4403
4416
|
const courseSlug2 = slugMatch?.[1] ?? "";
|
|
@@ -4415,7 +4428,8 @@ var init_select = __esm({
|
|
|
4415
4428
|
usedT0: pipelineResult?.usedT0 ?? false,
|
|
4416
4429
|
usedT1: pipelineResult?.usedT1 ?? false,
|
|
4417
4430
|
usedT2: pipelineResult?.usedT2 ?? false,
|
|
4418
|
-
instruction: pipelineResult?.renderedInstruction ?? null
|
|
4431
|
+
instruction: pipelineResult?.renderedInstruction ?? null,
|
|
4432
|
+
pipelineError
|
|
4419
4433
|
},
|
|
4420
4434
|
{ json: true }
|
|
4421
4435
|
);
|
|
@@ -4439,7 +4453,8 @@ var init_select = __esm({
|
|
|
4439
4453
|
` Progresso: ${detail.progress}% | ${detail.moduleCount} m\xF3dulos | ${detail.lessonCount} li\xE7\xF5es`,
|
|
4440
4454
|
wsLine,
|
|
4441
4455
|
"",
|
|
4442
|
-
|
|
4456
|
+
pipelineError ? `\u26A0 Arquivos de contexto N\xC3O foram criados (${pipelineError}).
|
|
4457
|
+
Rode \`tostudy select\` de novo com a conex\xE3o ativa.` : " Arquivos de contexto criados para seu assistente AI."
|
|
4443
4458
|
];
|
|
4444
4459
|
if (pipelineResult && !pipelineResult.usedT0) {
|
|
4445
4460
|
lines.push(" (sem persona do creator \u2014 usando tutor neutro)");
|
|
@@ -4813,7 +4828,7 @@ var init_next = __esm({
|
|
|
4813
4828
|
|
|
4814
4829
|
// src/commands/lesson.ts
|
|
4815
4830
|
import { Command as Command11 } from "commander";
|
|
4816
|
-
import
|
|
4831
|
+
import path13 from "node:path";
|
|
4817
4832
|
function adjustTimeEstimate(type, baseMinutes) {
|
|
4818
4833
|
if (type === "exercise") return Math.max(baseMinutes, 30);
|
|
4819
4834
|
return baseMinutes;
|
|
@@ -4826,7 +4841,7 @@ function formatLessonContent(data, workspacePath, courseTitle) {
|
|
|
4826
4841
|
const isPractical = data.type === "exercise" || isCheckpoint(data.title);
|
|
4827
4842
|
const lines = [`\u2501\u2501\u2501 Li\xE7\xE3o: ${data.title} \u2501\u2501\u2501`];
|
|
4828
4843
|
if (isPractical && workspacePath) {
|
|
4829
|
-
const base =
|
|
4844
|
+
const base = path13.basename(workspacePath) === ".tostudy" ? path13.dirname(workspacePath) : workspacePath;
|
|
4830
4845
|
const slug = courseSlug(courseTitle);
|
|
4831
4846
|
const vaultPath = resolveVaultPath(workspacePath, slug);
|
|
4832
4847
|
lines.push(
|
|
@@ -5370,10 +5385,10 @@ function mergeDefs(...defs) {
|
|
|
5370
5385
|
function cloneDef(schema) {
|
|
5371
5386
|
return mergeDefs(schema._zod.def);
|
|
5372
5387
|
}
|
|
5373
|
-
function getElementAtPath(obj,
|
|
5374
|
-
if (!
|
|
5388
|
+
function getElementAtPath(obj, path24) {
|
|
5389
|
+
if (!path24)
|
|
5375
5390
|
return obj;
|
|
5376
|
-
return
|
|
5391
|
+
return path24.reduce((acc, key) => acc?.[key], obj);
|
|
5377
5392
|
}
|
|
5378
5393
|
function promiseAllObject(promisesObj) {
|
|
5379
5394
|
const keys = Object.keys(promisesObj);
|
|
@@ -5685,11 +5700,11 @@ function aborted(x, startIndex = 0) {
|
|
|
5685
5700
|
}
|
|
5686
5701
|
return false;
|
|
5687
5702
|
}
|
|
5688
|
-
function prefixIssues(
|
|
5703
|
+
function prefixIssues(path24, issues) {
|
|
5689
5704
|
return issues.map((iss) => {
|
|
5690
5705
|
var _a2;
|
|
5691
5706
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
5692
|
-
iss.path.unshift(
|
|
5707
|
+
iss.path.unshift(path24);
|
|
5693
5708
|
return iss;
|
|
5694
5709
|
});
|
|
5695
5710
|
}
|
|
@@ -5931,7 +5946,7 @@ function formatError(error49, mapper = (issue2) => issue2.message) {
|
|
|
5931
5946
|
}
|
|
5932
5947
|
function treeifyError(error49, mapper = (issue2) => issue2.message) {
|
|
5933
5948
|
const result = { errors: [] };
|
|
5934
|
-
const processError = (error50,
|
|
5949
|
+
const processError = (error50, path24 = []) => {
|
|
5935
5950
|
var _a2, _b;
|
|
5936
5951
|
for (const issue2 of error50.issues) {
|
|
5937
5952
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -5941,7 +5956,7 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
|
|
|
5941
5956
|
} else if (issue2.code === "invalid_element") {
|
|
5942
5957
|
processError({ issues: issue2.issues }, issue2.path);
|
|
5943
5958
|
} else {
|
|
5944
|
-
const fullpath = [...
|
|
5959
|
+
const fullpath = [...path24, ...issue2.path];
|
|
5945
5960
|
if (fullpath.length === 0) {
|
|
5946
5961
|
result.errors.push(mapper(issue2));
|
|
5947
5962
|
continue;
|
|
@@ -5973,8 +5988,8 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
|
|
|
5973
5988
|
}
|
|
5974
5989
|
function toDotPath(_path) {
|
|
5975
5990
|
const segs = [];
|
|
5976
|
-
const
|
|
5977
|
-
for (const seg of
|
|
5991
|
+
const path24 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5992
|
+
for (const seg of path24) {
|
|
5978
5993
|
if (typeof seg === "number")
|
|
5979
5994
|
segs.push(`[${seg}]`);
|
|
5980
5995
|
else if (typeof seg === "symbol")
|
|
@@ -18668,13 +18683,13 @@ function resolveRef(ref, ctx) {
|
|
|
18668
18683
|
if (!ref.startsWith("#")) {
|
|
18669
18684
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
18670
18685
|
}
|
|
18671
|
-
const
|
|
18672
|
-
if (
|
|
18686
|
+
const path24 = ref.slice(1).split("/").filter(Boolean);
|
|
18687
|
+
if (path24.length === 0) {
|
|
18673
18688
|
return ctx.rootSchema;
|
|
18674
18689
|
}
|
|
18675
18690
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
18676
|
-
if (
|
|
18677
|
-
const key =
|
|
18691
|
+
if (path24[0] === defsKey) {
|
|
18692
|
+
const key = path24[1];
|
|
18678
18693
|
if (!key || !ctx.defs[key]) {
|
|
18679
18694
|
throw new Error(`Reference not found: ${ref}`);
|
|
18680
18695
|
}
|
|
@@ -20006,8 +20021,8 @@ var init_init_template = __esm({
|
|
|
20006
20021
|
});
|
|
20007
20022
|
|
|
20008
20023
|
// src/commands/validate.ts
|
|
20009
|
-
import
|
|
20010
|
-
import
|
|
20024
|
+
import fs11 from "node:fs";
|
|
20025
|
+
import path14 from "node:path";
|
|
20011
20026
|
import { Command as Command14 } from "commander";
|
|
20012
20027
|
var logger16, validateCommand;
|
|
20013
20028
|
var init_validate = __esm({
|
|
@@ -20051,21 +20066,21 @@ var init_validate = __esm({
|
|
|
20051
20066
|
}
|
|
20052
20067
|
let solution;
|
|
20053
20068
|
if (opts.stdin) {
|
|
20054
|
-
solution =
|
|
20069
|
+
solution = fs11.readFileSync("/dev/stdin", "utf-8");
|
|
20055
20070
|
} else if (file2) {
|
|
20056
|
-
if (!
|
|
20071
|
+
if (!fs11.existsSync(file2)) {
|
|
20057
20072
|
if (opts.json)
|
|
20058
20073
|
jsonError("file_not_found", { message: `Arquivo n\xE3o encontrado: ${file2}` });
|
|
20059
20074
|
error(`Arquivo n\xE3o encontrado: ${file2}`);
|
|
20060
20075
|
}
|
|
20061
|
-
solution =
|
|
20076
|
+
solution = fs11.readFileSync(file2, "utf-8");
|
|
20062
20077
|
} else {
|
|
20063
20078
|
if (opts.json)
|
|
20064
20079
|
jsonError("no_solution_provided", { message: "Forne\xE7a um arquivo ou use --stdin" });
|
|
20065
20080
|
error("Forne\xE7a um arquivo ou use --stdin.\n\nExemplo: tostudy validate resposta.md");
|
|
20066
20081
|
}
|
|
20067
20082
|
if (file2 && activeCourse.courseTags?.length) {
|
|
20068
|
-
const ext =
|
|
20083
|
+
const ext = path14.extname(file2).toLowerCase();
|
|
20069
20084
|
const LANG_EXTENSIONS = {
|
|
20070
20085
|
".html": ["html", "html5"],
|
|
20071
20086
|
".css": ["css"],
|
|
@@ -20440,15 +20455,27 @@ Rode \`tostudy select <n\xFAmero>\` para ativar um curso.`,
|
|
|
20440
20455
|
progressData,
|
|
20441
20456
|
learnerProfile
|
|
20442
20457
|
);
|
|
20443
|
-
await deps.saveRemoteEnrollmentOnboarding({
|
|
20444
|
-
apiUrl: session.apiUrl,
|
|
20445
|
-
token: session.token,
|
|
20446
|
-
enrollmentId: activeCourse.enrollmentId,
|
|
20447
|
-
learnerBrief: artifacts.learnerBrief,
|
|
20448
|
-
learnerProfile,
|
|
20449
|
-
source: "cli"
|
|
20450
|
-
});
|
|
20451
20458
|
await deps.saveCourseLearnerProfile(activeCourse, learnerProfile, artifacts);
|
|
20459
|
+
try {
|
|
20460
|
+
await deps.saveRemoteEnrollmentOnboarding({
|
|
20461
|
+
apiUrl: session.apiUrl,
|
|
20462
|
+
token: session.token,
|
|
20463
|
+
enrollmentId: activeCourse.enrollmentId,
|
|
20464
|
+
learnerBrief: artifacts.learnerBrief,
|
|
20465
|
+
learnerProfile,
|
|
20466
|
+
source: "cli"
|
|
20467
|
+
});
|
|
20468
|
+
} catch (err) {
|
|
20469
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
20470
|
+
deps.logger.warn("Failed to save enrollment onboarding remotely", { error: reason });
|
|
20471
|
+
if (!flags.json) {
|
|
20472
|
+
process.stderr.write(
|
|
20473
|
+
`\u26A0 Suas respostas foram salvas neste computador, mas n\xE3o chegaram ao servidor (${reason}).
|
|
20474
|
+
Rode \`tostudy init\` de novo com a conex\xE3o ativa para sincronizar.
|
|
20475
|
+
`
|
|
20476
|
+
);
|
|
20477
|
+
}
|
|
20478
|
+
}
|
|
20452
20479
|
try {
|
|
20453
20480
|
const rootAgents = await resolveRootAgentsConsent({
|
|
20454
20481
|
cwd: process.cwd(),
|
|
@@ -20506,7 +20533,13 @@ var init_init = __esm({
|
|
|
20506
20533
|
init_pipeline_deps();
|
|
20507
20534
|
logger17 = createLogger("cli:init");
|
|
20508
20535
|
defaultDeps4 = {
|
|
20509
|
-
|
|
20536
|
+
// GH #1419 item 3 — `init` used the raw session, so an expired access
|
|
20537
|
+
// token met the POST as a 401. Refresh through the guard when one exists.
|
|
20538
|
+
getSession: async () => {
|
|
20539
|
+
if (!await getSession()) return null;
|
|
20540
|
+
const { requireSession: requireSession2 } = await Promise.resolve().then(() => (init_guards(), guards_exports));
|
|
20541
|
+
return requireSession2();
|
|
20542
|
+
},
|
|
20510
20543
|
findWorkspaceState,
|
|
20511
20544
|
listCourses,
|
|
20512
20545
|
getProgress,
|
|
@@ -20533,14 +20566,14 @@ var init_init = __esm({
|
|
|
20533
20566
|
});
|
|
20534
20567
|
|
|
20535
20568
|
// ../../packages/tostudy-core/src/workspace/setup-workspace.ts
|
|
20536
|
-
import
|
|
20537
|
-
import
|
|
20569
|
+
import fs12 from "node:fs/promises";
|
|
20570
|
+
import path15 from "node:path";
|
|
20538
20571
|
async function setupWorkspace(input2) {
|
|
20539
|
-
const workspacePath =
|
|
20572
|
+
const workspacePath = path15.join(input2.basePath, input2.courseSlug);
|
|
20540
20573
|
for (const dir of WORKSPACE_DIRS) {
|
|
20541
|
-
await
|
|
20574
|
+
await fs12.mkdir(path15.join(workspacePath, dir), { recursive: true });
|
|
20542
20575
|
}
|
|
20543
|
-
const configPath =
|
|
20576
|
+
const configPath = path15.join(workspacePath, ".ana-config.json");
|
|
20544
20577
|
const config2 = {
|
|
20545
20578
|
courseId: input2.courseId,
|
|
20546
20579
|
courseSlug: input2.courseSlug,
|
|
@@ -20550,7 +20583,7 @@ async function setupWorkspace(input2) {
|
|
|
20550
20583
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20551
20584
|
lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20552
20585
|
};
|
|
20553
|
-
await
|
|
20586
|
+
await fs12.writeFile(configPath, JSON.stringify(config2, null, 2), "utf-8");
|
|
20554
20587
|
const readme = [
|
|
20555
20588
|
`# ${input2.courseName}`,
|
|
20556
20589
|
"",
|
|
@@ -20575,7 +20608,7 @@ async function setupWorkspace(input2) {
|
|
|
20575
20608
|
"tostudy vault sync # Sincronizar progresso",
|
|
20576
20609
|
"```"
|
|
20577
20610
|
].join("\n");
|
|
20578
|
-
await
|
|
20611
|
+
await fs12.writeFile(path15.join(workspacePath, "README.md"), readme, "utf-8");
|
|
20579
20612
|
return { workspacePath, directories: WORKSPACE_DIRS, configPath };
|
|
20580
20613
|
}
|
|
20581
20614
|
var WORKSPACE_DIRS;
|
|
@@ -20676,8 +20709,8 @@ var init_templates = __esm({
|
|
|
20676
20709
|
});
|
|
20677
20710
|
|
|
20678
20711
|
// ../../packages/tostudy-core/src/workspace/extract-exercise.ts
|
|
20679
|
-
import
|
|
20680
|
-
import
|
|
20712
|
+
import fs13 from "node:fs/promises";
|
|
20713
|
+
import path16 from "node:path";
|
|
20681
20714
|
function padOrder(n) {
|
|
20682
20715
|
return String(n).padStart(2, "0");
|
|
20683
20716
|
}
|
|
@@ -20703,16 +20736,16 @@ async function extractExercise(input2) {
|
|
|
20703
20736
|
const lessonData = resolveWorkspaceTokens(input2.lessonData, paths);
|
|
20704
20737
|
const moduleDir = `${padOrder(lessonData.moduleOrder)}-${lessonData.moduleSlug}`;
|
|
20705
20738
|
const lessonDir = `${padOrder(lessonData.lessonOrder)}-${lessonData.lessonSlug}`;
|
|
20706
|
-
const exercisePath =
|
|
20707
|
-
await
|
|
20739
|
+
const exercisePath = path16.join(workspacePath, "exercises", moduleDir, lessonDir);
|
|
20740
|
+
await fs13.mkdir(exercisePath, { recursive: true });
|
|
20708
20741
|
const extractedFiles = [];
|
|
20709
20742
|
let hasStarterCode = false;
|
|
20710
20743
|
if (lessonData.sandpackConfig?.files) {
|
|
20711
20744
|
for (const [filePath, fileData] of Object.entries(lessonData.sandpackConfig.files)) {
|
|
20712
20745
|
const cleanPath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
20713
|
-
const fullPath =
|
|
20714
|
-
await
|
|
20715
|
-
await
|
|
20746
|
+
const fullPath = path16.join(exercisePath, cleanPath);
|
|
20747
|
+
await fs13.mkdir(path16.dirname(fullPath), { recursive: true });
|
|
20748
|
+
await fs13.writeFile(fullPath, fileData.code, "utf-8");
|
|
20716
20749
|
extractedFiles.push(cleanPath);
|
|
20717
20750
|
hasStarterCode = true;
|
|
20718
20751
|
}
|
|
@@ -20720,13 +20753,13 @@ async function extractExercise(input2) {
|
|
|
20720
20753
|
const tierData = getTierData(lessonData.structuredData, exerciseTier);
|
|
20721
20754
|
const tierCode = tierData?.code;
|
|
20722
20755
|
if (tierCode) {
|
|
20723
|
-
await
|
|
20756
|
+
await fs13.writeFile(path16.join(exercisePath, "exercise.js"), tierCode, "utf-8");
|
|
20724
20757
|
extractedFiles.push("exercise.js");
|
|
20725
20758
|
hasStarterCode = true;
|
|
20726
20759
|
} else {
|
|
20727
20760
|
const starter = getStarterCode(lessonData.structuredData);
|
|
20728
20761
|
if (starter) {
|
|
20729
|
-
await
|
|
20762
|
+
await fs13.writeFile(path16.join(exercisePath, "exercise.js"), starter, "utf-8");
|
|
20730
20763
|
extractedFiles.push("exercise.js");
|
|
20731
20764
|
hasStarterCode = true;
|
|
20732
20765
|
}
|
|
@@ -20744,8 +20777,8 @@ async function extractExercise(input2) {
|
|
|
20744
20777
|
...exerciseDeps
|
|
20745
20778
|
}
|
|
20746
20779
|
};
|
|
20747
|
-
await
|
|
20748
|
-
|
|
20780
|
+
await fs13.writeFile(
|
|
20781
|
+
path16.join(exercisePath, "package.json"),
|
|
20749
20782
|
JSON.stringify(pkgJson, null, 2),
|
|
20750
20783
|
"utf-8"
|
|
20751
20784
|
);
|
|
@@ -20757,20 +20790,20 @@ async function extractExercise(input2) {
|
|
|
20757
20790
|
);
|
|
20758
20791
|
for (const [configFile, configContent] of Object.entries(scaffold.configs)) {
|
|
20759
20792
|
if (!sandpackFileNames.has(configFile)) {
|
|
20760
|
-
await
|
|
20793
|
+
await fs13.writeFile(path16.join(exercisePath, configFile), configContent, "utf-8");
|
|
20761
20794
|
extractedFiles.push(configFile);
|
|
20762
20795
|
}
|
|
20763
20796
|
}
|
|
20764
20797
|
const setupSh = `#!/bin/sh
|
|
20765
20798
|
${scaffold.setupScript}
|
|
20766
20799
|
`;
|
|
20767
|
-
await
|
|
20800
|
+
await fs13.writeFile(path16.join(exercisePath, "setup.sh"), setupSh, "utf-8");
|
|
20768
20801
|
extractedFiles.push("setup.sh");
|
|
20769
20802
|
}
|
|
20770
20803
|
}
|
|
20771
20804
|
const readme = generateReadme(lessonData, exerciseTier);
|
|
20772
|
-
const readmePath =
|
|
20773
|
-
await
|
|
20805
|
+
const readmePath = path16.join(exercisePath, "README.md");
|
|
20806
|
+
await fs13.writeFile(readmePath, readme, "utf-8");
|
|
20774
20807
|
extractedFiles.push("README.md");
|
|
20775
20808
|
return {
|
|
20776
20809
|
exercisePath,
|
|
@@ -20852,9 +20885,9 @@ var init_workspace = __esm({
|
|
|
20852
20885
|
|
|
20853
20886
|
// src/commands/workspace.ts
|
|
20854
20887
|
import { Command as Command17 } from "commander";
|
|
20855
|
-
import
|
|
20888
|
+
import path17 from "node:path";
|
|
20856
20889
|
import os8 from "node:os";
|
|
20857
|
-
import
|
|
20890
|
+
import fs14 from "node:fs/promises";
|
|
20858
20891
|
var logger18, workspaceCommand;
|
|
20859
20892
|
var init_workspace2 = __esm({
|
|
20860
20893
|
"src/commands/workspace.ts"() {
|
|
@@ -20878,14 +20911,14 @@ var init_workspace2 = __esm({
|
|
|
20878
20911
|
let directories;
|
|
20879
20912
|
if (!opts.path && cwdIsWorkspace) {
|
|
20880
20913
|
const resolvedCwd = await resolveCwdWorkspacePath(process.cwd());
|
|
20881
|
-
workspacePath = resolvedCwd ??
|
|
20882
|
-
await
|
|
20914
|
+
workspacePath = resolvedCwd ?? path17.join(process.cwd(), ".tostudy");
|
|
20915
|
+
await fs14.mkdir(workspacePath, { recursive: true });
|
|
20883
20916
|
directories = ["exercises", "generated", "notes", "diagrams"];
|
|
20884
20917
|
for (const dir of directories) {
|
|
20885
|
-
await
|
|
20918
|
+
await fs14.mkdir(path17.join(workspacePath, dir), { recursive: true });
|
|
20886
20919
|
}
|
|
20887
|
-
const configPath =
|
|
20888
|
-
await
|
|
20920
|
+
const configPath = path17.join(workspacePath, ".ana-config.json");
|
|
20921
|
+
await fs14.writeFile(
|
|
20889
20922
|
configPath,
|
|
20890
20923
|
JSON.stringify(
|
|
20891
20924
|
{
|
|
@@ -20903,7 +20936,7 @@ var init_workspace2 = __esm({
|
|
|
20903
20936
|
"utf-8"
|
|
20904
20937
|
);
|
|
20905
20938
|
} else {
|
|
20906
|
-
const basePath = opts.path ??
|
|
20939
|
+
const basePath = opts.path ?? path17.join(os8.homedir(), "study");
|
|
20907
20940
|
const result2 = await setupWorkspace({
|
|
20908
20941
|
courseId: activeCourse.courseId,
|
|
20909
20942
|
courseSlug: courseSlug(activeCourse.courseTitle),
|
|
@@ -20937,7 +20970,7 @@ Pr\xF3ximo passo: tostudy export
|
|
|
20937
20970
|
process.exit(1);
|
|
20938
20971
|
}
|
|
20939
20972
|
});
|
|
20940
|
-
workspaceCommand.command("status").description("Mostrar status do workspace do curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
20973
|
+
workspaceCommand.command("status").description("Mostrar status do workspace do curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path17.join(os8.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
20941
20974
|
try {
|
|
20942
20975
|
const activeCourse = await requireActiveCourse();
|
|
20943
20976
|
const onboardingState = await getCourseOnboardingState(activeCourse.courseId);
|
|
@@ -20954,40 +20987,40 @@ Pr\xF3ximo passo: tostudy export
|
|
|
20954
20987
|
const workspacePath = ws.workspacePath;
|
|
20955
20988
|
let configData = null;
|
|
20956
20989
|
try {
|
|
20957
|
-
const raw = await
|
|
20990
|
+
const raw = await fs14.readFile(path17.join(workspacePath, ".ana-config.json"), "utf-8");
|
|
20958
20991
|
configData = JSON.parse(raw);
|
|
20959
20992
|
} catch {
|
|
20960
20993
|
configData = null;
|
|
20961
20994
|
}
|
|
20962
|
-
const exercisesDir =
|
|
20995
|
+
const exercisesDir = path17.join(workspacePath, "exercises");
|
|
20963
20996
|
let exerciseCount = 0;
|
|
20964
20997
|
try {
|
|
20965
|
-
const moduleDirs = await
|
|
20998
|
+
const moduleDirs = await fs14.readdir(exercisesDir);
|
|
20966
20999
|
for (const modDir of moduleDirs) {
|
|
20967
|
-
const modPath =
|
|
20968
|
-
const stat = await
|
|
21000
|
+
const modPath = path17.join(exercisesDir, modDir);
|
|
21001
|
+
const stat = await fs14.stat(modPath);
|
|
20969
21002
|
if (stat.isDirectory()) {
|
|
20970
|
-
const lessonDirs = await
|
|
21003
|
+
const lessonDirs = await fs14.readdir(modPath);
|
|
20971
21004
|
for (const lessonDir of lessonDirs) {
|
|
20972
|
-
const lessonPath =
|
|
20973
|
-
const lstat = await
|
|
21005
|
+
const lessonPath = path17.join(modPath, lessonDir);
|
|
21006
|
+
const lstat = await fs14.stat(lessonPath);
|
|
20974
21007
|
if (lstat.isDirectory()) exerciseCount++;
|
|
20975
21008
|
}
|
|
20976
21009
|
}
|
|
20977
21010
|
}
|
|
20978
21011
|
} catch {
|
|
20979
21012
|
}
|
|
20980
|
-
const generatedDir =
|
|
21013
|
+
const generatedDir = path17.join(workspacePath, "generated");
|
|
20981
21014
|
let artifactCount = 0;
|
|
20982
21015
|
try {
|
|
20983
|
-
const files = await
|
|
21016
|
+
const files = await fs14.readdir(generatedDir);
|
|
20984
21017
|
artifactCount = files.length;
|
|
20985
21018
|
} catch {
|
|
20986
21019
|
}
|
|
20987
|
-
const diagramsDir =
|
|
21020
|
+
const diagramsDir = path17.join(workspacePath, "diagrams");
|
|
20988
21021
|
let diagramCount = 0;
|
|
20989
21022
|
try {
|
|
20990
|
-
const files = await
|
|
21023
|
+
const files = await fs14.readdir(diagramsDir);
|
|
20991
21024
|
diagramCount = files.length;
|
|
20992
21025
|
} catch {
|
|
20993
21026
|
}
|
|
@@ -21036,9 +21069,9 @@ Pr\xF3ximo passo: tostudy export
|
|
|
21036
21069
|
|
|
21037
21070
|
// src/commands/export.ts
|
|
21038
21071
|
import { Command as Command18 } from "commander";
|
|
21039
|
-
import
|
|
21072
|
+
import path18 from "node:path";
|
|
21040
21073
|
import os9 from "node:os";
|
|
21041
|
-
import
|
|
21074
|
+
import fs15 from "node:fs/promises";
|
|
21042
21075
|
var logger19, exportCommand;
|
|
21043
21076
|
var init_export = __esm({
|
|
21044
21077
|
"src/commands/export.ts"() {
|
|
@@ -21051,7 +21084,7 @@ var init_export = __esm({
|
|
|
21051
21084
|
init_resolve();
|
|
21052
21085
|
init_errors();
|
|
21053
21086
|
logger19 = createLogger("cli:export");
|
|
21054
|
-
exportCommand = new Command18("export").description("Extrair exerc\xEDcio atual para o workspace local").option("--tier <tier>", "Tier do exerc\xEDcio: guided, semiGuided, challenging", "guided").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21087
|
+
exportCommand = new Command18("export").description("Extrair exerc\xEDcio atual para o workspace local").option("--tier <tier>", "Tier do exerc\xEDcio: guided, semiGuided, challenging", "guided").option("--path <dir>", "Diret\xF3rio base do workspace", path18.join(os9.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
21055
21088
|
try {
|
|
21056
21089
|
const session = await requireSession();
|
|
21057
21090
|
const activeCourse = await requireActiveCourse();
|
|
@@ -21069,21 +21102,21 @@ var init_export = __esm({
|
|
|
21069
21102
|
opts.path
|
|
21070
21103
|
);
|
|
21071
21104
|
if (ws.found && ws.source === "cwd" && ws.workspacePath) {
|
|
21072
|
-
const configPath =
|
|
21105
|
+
const configPath = path18.join(ws.workspacePath, ".ana-config.json");
|
|
21073
21106
|
let hasConfig = false;
|
|
21074
21107
|
try {
|
|
21075
|
-
await
|
|
21108
|
+
await fs15.access(configPath);
|
|
21076
21109
|
hasConfig = true;
|
|
21077
21110
|
} catch {
|
|
21078
21111
|
}
|
|
21079
21112
|
if (!hasConfig) {
|
|
21080
21113
|
const slug = courseSlug(activeCourse.courseTitle);
|
|
21081
21114
|
logger19.info("Auto-initializing workspace", { workspacePath: ws.workspacePath });
|
|
21082
|
-
await
|
|
21115
|
+
await fs15.mkdir(ws.workspacePath, { recursive: true });
|
|
21083
21116
|
for (const dir of ["exercises", "generated", "notes", "diagrams"]) {
|
|
21084
|
-
await
|
|
21117
|
+
await fs15.mkdir(path18.join(ws.workspacePath, dir), { recursive: true });
|
|
21085
21118
|
}
|
|
21086
|
-
await
|
|
21119
|
+
await fs15.writeFile(
|
|
21087
21120
|
configPath,
|
|
21088
21121
|
JSON.stringify(
|
|
21089
21122
|
{
|
|
@@ -21101,7 +21134,7 @@ var init_export = __esm({
|
|
|
21101
21134
|
"utf-8"
|
|
21102
21135
|
);
|
|
21103
21136
|
await setCourseWorkspacePath(activeCourse.courseId, ws.workspacePath);
|
|
21104
|
-
const isNamespaced = ws.workspacePath ===
|
|
21137
|
+
const isNamespaced = ws.workspacePath === path18.join(process.cwd(), ".tostudy");
|
|
21105
21138
|
process.stderr.write(
|
|
21106
21139
|
isNamespaced ? `\u2728 Workspace inicializado em .tostudy/ (isolado do projeto).
|
|
21107
21140
|
` : `\u2728 Workspace inicializado nesta pasta.
|
|
@@ -21155,7 +21188,7 @@ ${result.files.map((f) => ` \u{1F4C4} ${f}`).join("\n")}
|
|
|
21155
21188
|
// src/commands/open.ts
|
|
21156
21189
|
import { Command as Command19 } from "commander";
|
|
21157
21190
|
import { execFile as execFile3 } from "node:child_process";
|
|
21158
|
-
import
|
|
21191
|
+
import path19 from "node:path";
|
|
21159
21192
|
import os10 from "node:os";
|
|
21160
21193
|
var logger20, openCommand;
|
|
21161
21194
|
var init_open = __esm({
|
|
@@ -21167,7 +21200,7 @@ var init_open = __esm({
|
|
|
21167
21200
|
init_resolve();
|
|
21168
21201
|
init_errors();
|
|
21169
21202
|
logger20 = createLogger("cli:open");
|
|
21170
|
-
openCommand = new Command19("open").description("Abrir workspace do curso na IDE").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21203
|
+
openCommand = new Command19("open").description("Abrir workspace do curso na IDE").option("--path <dir>", "Diret\xF3rio base do workspace", path19.join(os10.homedir(), "study")).action(async (opts) => {
|
|
21171
21204
|
try {
|
|
21172
21205
|
const activeCourse = await requireActiveCourse();
|
|
21173
21206
|
const onboardingState = await getCourseOnboardingState(activeCourse.courseId);
|
|
@@ -21221,24 +21254,24 @@ var init_types = __esm({
|
|
|
21221
21254
|
});
|
|
21222
21255
|
|
|
21223
21256
|
// ../../packages/tostudy-core/src/vault/write-vault.ts
|
|
21224
|
-
import
|
|
21225
|
-
import
|
|
21257
|
+
import fs16 from "node:fs/promises";
|
|
21258
|
+
import path20 from "node:path";
|
|
21226
21259
|
async function writeVaultFiles(files, outputPath, courseId, courseSlug2) {
|
|
21227
21260
|
for (const file2 of files) {
|
|
21228
|
-
const fullPath =
|
|
21229
|
-
await
|
|
21230
|
-
await
|
|
21261
|
+
const fullPath = path20.join(outputPath, file2.relativePath);
|
|
21262
|
+
await fs16.mkdir(path20.dirname(fullPath), { recursive: true });
|
|
21263
|
+
await fs16.writeFile(fullPath, file2.content, "utf-8");
|
|
21231
21264
|
}
|
|
21232
|
-
const vaultPath =
|
|
21265
|
+
const vaultPath = path20.join(outputPath, courseSlug2);
|
|
21233
21266
|
const marker = {
|
|
21234
21267
|
courseId,
|
|
21235
21268
|
courseSlug: courseSlug2,
|
|
21236
21269
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21237
21270
|
version: VAULT_MARKER_VERSION
|
|
21238
21271
|
};
|
|
21239
|
-
await
|
|
21240
|
-
await
|
|
21241
|
-
|
|
21272
|
+
await fs16.mkdir(vaultPath, { recursive: true });
|
|
21273
|
+
await fs16.writeFile(
|
|
21274
|
+
path20.join(vaultPath, VAULT_MARKER_FILENAME),
|
|
21242
21275
|
JSON.stringify(marker, null, 2),
|
|
21243
21276
|
"utf-8"
|
|
21244
21277
|
);
|
|
@@ -21263,9 +21296,9 @@ var init_vault = __esm({
|
|
|
21263
21296
|
|
|
21264
21297
|
// src/commands/vault.ts
|
|
21265
21298
|
import { Command as Command20 } from "commander";
|
|
21266
|
-
import
|
|
21299
|
+
import path21 from "node:path";
|
|
21267
21300
|
import os11 from "node:os";
|
|
21268
|
-
import
|
|
21301
|
+
import fs17 from "node:fs/promises";
|
|
21269
21302
|
var logger21, vaultCommand;
|
|
21270
21303
|
var init_vault2 = __esm({
|
|
21271
21304
|
"src/commands/vault.ts"() {
|
|
@@ -21281,7 +21314,7 @@ var init_vault2 = __esm({
|
|
|
21281
21314
|
init_errors();
|
|
21282
21315
|
logger21 = createLogger("cli:vault");
|
|
21283
21316
|
vaultCommand = new Command20("vault").description("Gerenciar vault Obsidian do curso");
|
|
21284
|
-
vaultCommand.command("init").description("Gerar vault Obsidian para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21317
|
+
vaultCommand.command("init").description("Gerar vault Obsidian para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path21.join(os11.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
21285
21318
|
try {
|
|
21286
21319
|
const session = await requireSession();
|
|
21287
21320
|
const activeCourse = await requireActiveCourse();
|
|
@@ -21362,7 +21395,7 @@ Para visualizar:
|
|
|
21362
21395
|
process.exit(1);
|
|
21363
21396
|
}
|
|
21364
21397
|
});
|
|
21365
|
-
vaultCommand.command("sync").description("Sincronizar progresso do curso com o vault local").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21398
|
+
vaultCommand.command("sync").description("Sincronizar progresso do curso com o vault local").option("--path <dir>", "Diret\xF3rio base do workspace", path21.join(os11.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
21366
21399
|
try {
|
|
21367
21400
|
const session = await requireSession();
|
|
21368
21401
|
const activeCourse = await requireActiveCourse();
|
|
@@ -21388,8 +21421,8 @@ Para visualizar:
|
|
|
21388
21421
|
const data = createHttpProvider(session.apiUrl, session.token);
|
|
21389
21422
|
const deps = { data, logger: logger21 };
|
|
21390
21423
|
const progress = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
|
|
21391
|
-
const markerPath =
|
|
21392
|
-
const markerRaw = await
|
|
21424
|
+
const markerPath = path21.join(vaultPath, ".ana-vault.json");
|
|
21425
|
+
const markerRaw = await fs17.readFile(markerPath, "utf-8");
|
|
21393
21426
|
const marker = JSON.parse(markerRaw);
|
|
21394
21427
|
marker.lastSyncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21395
21428
|
marker.progress = {
|
|
@@ -21397,10 +21430,10 @@ Para visualizar:
|
|
|
21397
21430
|
currentModule: progress.currentModule.title,
|
|
21398
21431
|
currentLesson: progress.currentLesson.title
|
|
21399
21432
|
};
|
|
21400
|
-
await
|
|
21401
|
-
const courseIndexPath =
|
|
21433
|
+
await fs17.writeFile(markerPath, JSON.stringify(marker, null, 2), "utf-8");
|
|
21434
|
+
const courseIndexPath = path21.join(vaultPath, slug, "index.md");
|
|
21402
21435
|
try {
|
|
21403
|
-
let indexContent = await
|
|
21436
|
+
let indexContent = await fs17.readFile(courseIndexPath, "utf-8");
|
|
21404
21437
|
indexContent = indexContent.replace(/\n---\n\n> 📊 Progresso:.*\n/g, "");
|
|
21405
21438
|
const titleEnd = indexContent.indexOf("\n");
|
|
21406
21439
|
if (titleEnd !== -1) {
|
|
@@ -21411,7 +21444,7 @@ Para visualizar:
|
|
|
21411
21444
|
`;
|
|
21412
21445
|
indexContent = indexContent.slice(0, titleEnd) + banner + indexContent.slice(titleEnd);
|
|
21413
21446
|
}
|
|
21414
|
-
await
|
|
21447
|
+
await fs17.writeFile(courseIndexPath, indexContent, "utf-8");
|
|
21415
21448
|
} catch {
|
|
21416
21449
|
}
|
|
21417
21450
|
const syncedAt = marker.lastSyncedAt;
|
|
@@ -21731,16 +21764,16 @@ var init_brief_open = __esm({
|
|
|
21731
21764
|
});
|
|
21732
21765
|
|
|
21733
21766
|
// src/sessions/storage.ts
|
|
21734
|
-
import
|
|
21735
|
-
import
|
|
21767
|
+
import fs18 from "node:fs";
|
|
21768
|
+
import path22 from "node:path";
|
|
21736
21769
|
function sessionsDir(workspacePath) {
|
|
21737
|
-
return
|
|
21770
|
+
return path22.join(workspacePath, ".tostudy", "sessions");
|
|
21738
21771
|
}
|
|
21739
21772
|
async function saveModuleSummary(workspacePath, input2) {
|
|
21740
21773
|
const dir = sessionsDir(workspacePath);
|
|
21741
|
-
|
|
21774
|
+
fs18.mkdirSync(dir, { recursive: true });
|
|
21742
21775
|
const filename = `module-${input2.moduleId}-summary.md`;
|
|
21743
|
-
const filePath =
|
|
21776
|
+
const filePath = path22.join(dir, filename);
|
|
21744
21777
|
const header = [
|
|
21745
21778
|
"---",
|
|
21746
21779
|
`moduleId: ${input2.moduleId}`,
|
|
@@ -21749,17 +21782,17 @@ async function saveModuleSummary(workspacePath, input2) {
|
|
|
21749
21782
|
"---",
|
|
21750
21783
|
""
|
|
21751
21784
|
].join("\n");
|
|
21752
|
-
|
|
21785
|
+
fs18.writeFileSync(filePath, header + input2.summary, { mode: 384 });
|
|
21753
21786
|
logger25.debug("Module summary saved", { moduleId: input2.moduleId, path: filePath });
|
|
21754
21787
|
return filePath;
|
|
21755
21788
|
}
|
|
21756
21789
|
async function loadSessionContext(workspacePath) {
|
|
21757
21790
|
const dir = sessionsDir(workspacePath);
|
|
21758
|
-
if (!
|
|
21759
|
-
const files =
|
|
21791
|
+
if (!fs18.existsSync(dir)) return { moduleSummaries: [] };
|
|
21792
|
+
const files = fs18.readdirSync(dir).filter((f) => f.startsWith("module-") && f.endsWith("-summary.md")).sort();
|
|
21760
21793
|
const summaries = [];
|
|
21761
21794
|
for (const file2 of files) {
|
|
21762
|
-
const content =
|
|
21795
|
+
const content = fs18.readFileSync(path22.join(dir, file2), "utf-8");
|
|
21763
21796
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
21764
21797
|
if (!frontmatterMatch) continue;
|
|
21765
21798
|
const meta3 = frontmatterMatch[1];
|
|
@@ -21781,7 +21814,7 @@ var init_storage = __esm({
|
|
|
21781
21814
|
});
|
|
21782
21815
|
|
|
21783
21816
|
// src/commands/compact.ts
|
|
21784
|
-
import
|
|
21817
|
+
import fs19 from "node:fs";
|
|
21785
21818
|
import { Command as Command26 } from "commander";
|
|
21786
21819
|
var logger26, compactCommand;
|
|
21787
21820
|
var init_compact = __esm({
|
|
@@ -21801,7 +21834,7 @@ var init_compact = __esm({
|
|
|
21801
21834
|
if (opts.json) jsonError("no_workspace");
|
|
21802
21835
|
error("Nenhum workspace encontrado.");
|
|
21803
21836
|
}
|
|
21804
|
-
const summary =
|
|
21837
|
+
const summary = fs19.readFileSync("/dev/stdin", "utf-8").trim();
|
|
21805
21838
|
if (!summary) {
|
|
21806
21839
|
if (opts.json) jsonError("empty_summary", { message: "Summary vazio" });
|
|
21807
21840
|
error("Summary vazio. Envie o conte\xFAdo via stdin.");
|
|
@@ -22970,8 +23003,17 @@ __export(cli_exports, {
|
|
|
22970
23003
|
import { Command as Command35 } from "commander";
|
|
22971
23004
|
function createProgram() {
|
|
22972
23005
|
const program2 = new Command35();
|
|
22973
|
-
program2.name("tostudy").description("ToStudy CLI \u2014 study courses from the terminal").version(CLI_VERSION).option("--verbose", "Enable debug output").option("--course <id>", "Override active course ID").option("--locale <code>", "Output locale (pt-BR | en-US); defaults to LANG env then pt-BR")
|
|
22974
|
-
|
|
23006
|
+
program2.name("tostudy").description("ToStudy CLI \u2014 study courses from the terminal").version(CLI_VERSION).option("--verbose", "Enable debug output").option("--course <id>", "Override active course ID").option("--locale <code>", "Output locale (pt-BR | en-US); defaults to LANG env then pt-BR").addHelpText(
|
|
23007
|
+
"before",
|
|
23008
|
+
[
|
|
23009
|
+
"",
|
|
23010
|
+
" Come\xE7ando: login \u2192 courses \u2192 select <n> \u2192 start",
|
|
23011
|
+
" Estudando: next \xB7 lesson \xB7 hint \xB7 validate \xB7 theory \xB7 progress",
|
|
23012
|
+
" Com d\xFAvida: tostudy menu (mostra onde voc\xEA est\xE1 e o que fazer)",
|
|
23013
|
+
""
|
|
23014
|
+
].join("\n")
|
|
23015
|
+
);
|
|
23016
|
+
program2.addCommand(setupCommand, { hidden: true });
|
|
22975
23017
|
program2.addCommand(doctorCommand);
|
|
22976
23018
|
program2.addCommand(initCommand);
|
|
22977
23019
|
program2.addCommand(loginCommand);
|
|
@@ -23055,11 +23097,11 @@ __export(auto_updater_exports, {
|
|
|
23055
23097
|
detectManager: () => detectManager,
|
|
23056
23098
|
maybeAutoUpdate: () => maybeAutoUpdate
|
|
23057
23099
|
});
|
|
23058
|
-
import
|
|
23059
|
-
import
|
|
23100
|
+
import fs20 from "node:fs";
|
|
23101
|
+
import path23 from "node:path";
|
|
23060
23102
|
import { spawn as spawn2 } from "node:child_process";
|
|
23061
23103
|
function detectManager(entryRealPath) {
|
|
23062
|
-
const p = entryRealPath.split(
|
|
23104
|
+
const p = entryRealPath.split(path23.sep).join("/");
|
|
23063
23105
|
if (p.includes("/pnpm/")) return { cmd: "pnpm", args: ["add", "-g", `${PACKAGE_NAME2}@latest`] };
|
|
23064
23106
|
if (p.includes("/.bun/")) return { cmd: "bun", args: ["add", "-g", `${PACKAGE_NAME2}@latest`] };
|
|
23065
23107
|
if (p.includes(`/node_modules/${PACKAGE_NAME2}/`))
|
|
@@ -23067,10 +23109,10 @@ function detectManager(entryRealPath) {
|
|
|
23067
23109
|
return null;
|
|
23068
23110
|
}
|
|
23069
23111
|
function installDir(entryRealPath) {
|
|
23070
|
-
const normalized = entryRealPath.split(
|
|
23112
|
+
const normalized = entryRealPath.split(path23.sep).join("/");
|
|
23071
23113
|
const marker = `/node_modules/${PACKAGE_NAME2}/`;
|
|
23072
23114
|
const idx = normalized.indexOf(marker);
|
|
23073
|
-
if (idx === -1) return
|
|
23115
|
+
if (idx === -1) return path23.dirname(entryRealPath);
|
|
23074
23116
|
return entryRealPath.slice(0, idx + marker.length - 1);
|
|
23075
23117
|
}
|
|
23076
23118
|
function maybeAutoUpdate(currentVersion, opts = {}) {
|
|
@@ -23086,10 +23128,10 @@ function maybeAutoUpdate(currentVersion, opts = {}) {
|
|
|
23086
23128
|
if (cache.attemptedVersion === cache.latest) return;
|
|
23087
23129
|
const entryPath = opts.entryPath ?? argv[1];
|
|
23088
23130
|
if (!entryPath) return;
|
|
23089
|
-
const real =
|
|
23131
|
+
const real = fs20.realpathSync(entryPath);
|
|
23090
23132
|
const mgr = detectManager(real);
|
|
23091
23133
|
if (!mgr) return;
|
|
23092
|
-
|
|
23134
|
+
fs20.accessSync(installDir(real), fs20.constants.W_OK);
|
|
23093
23135
|
writeCache({ ...cache, attemptedVersion: cache.latest }, configDir);
|
|
23094
23136
|
process.stderr.write(
|
|
23095
23137
|
`
|
|
@@ -23132,9 +23174,28 @@ Update at https://nodejs.org and run the command again.
|
|
|
23132
23174
|
);
|
|
23133
23175
|
process.exit(1);
|
|
23134
23176
|
}
|
|
23177
|
+
if (!process.env["TOSTUDY_LOCALE"]) {
|
|
23178
|
+
try {
|
|
23179
|
+
const { readFileSync: readFileSync4 } = await import("node:fs");
|
|
23180
|
+
const { join: join3 } = await import("node:path");
|
|
23181
|
+
const { homedir: homedir2 } = await import("node:os");
|
|
23182
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
23183
|
+
const dir = process.platform === "linux" && xdg ? join3(xdg, "tostudy") : join3(homedir2(), ".tostudy");
|
|
23184
|
+
const { locale } = JSON.parse(readFileSync4(join3(dir, "config.json"), "utf-8"));
|
|
23185
|
+
if (locale === "pt-BR" || locale === "en-US") process.env["TOSTUDY_LOCALE"] = locale;
|
|
23186
|
+
} catch {
|
|
23187
|
+
}
|
|
23188
|
+
}
|
|
23135
23189
|
var { createProgram: createProgram2, CLI_VERSION: CLI_VERSION2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
23136
23190
|
var { checkForUpdates: checkForUpdates2 } = await Promise.resolve().then(() => (init_update_checker(), update_checker_exports));
|
|
23137
23191
|
var { maybeAutoUpdate: maybeAutoUpdate2 } = await Promise.resolve().then(() => (init_auto_updater(), auto_updater_exports));
|
|
23192
|
+
process.on("unhandledRejection", (reason) => {
|
|
23193
|
+
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
23194
|
+
process.stderr.write(`Erro: ${msg}
|
|
23195
|
+
Se o problema continuar, rode: tostudy doctor
|
|
23196
|
+
`);
|
|
23197
|
+
process.exit(1);
|
|
23198
|
+
});
|
|
23138
23199
|
var program = createProgram2();
|
|
23139
23200
|
program.parse();
|
|
23140
23201
|
checkForUpdates2(CLI_VERSION2);
|