@tostudy-ai/cli 0.16.7 → 0.16.9
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 +231 -185
- package/dist/cli.js.map +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1440,7 +1440,8 @@ async function saveSession(session, configDir) {
|
|
|
1440
1440
|
userName: session.userName,
|
|
1441
1441
|
expiresAt: session.expiresAt,
|
|
1442
1442
|
apiUrl: session.apiUrl,
|
|
1443
|
-
sessionId: session.sessionId
|
|
1443
|
+
sessionId: session.sessionId,
|
|
1444
|
+
...session.locale ? { locale: session.locale } : {}
|
|
1444
1445
|
};
|
|
1445
1446
|
fs2.writeFileSync(path3.join(dir, "config.json"), JSON.stringify(stored, null, 2), {
|
|
1446
1447
|
mode: 384
|
|
@@ -1460,7 +1461,8 @@ async function getSession(configDir) {
|
|
|
1460
1461
|
userName: stored.userName,
|
|
1461
1462
|
expiresAt: stored.expiresAt,
|
|
1462
1463
|
apiUrl: stored.apiUrl,
|
|
1463
|
-
sessionId: stored.sessionId
|
|
1464
|
+
sessionId: stored.sessionId,
|
|
1465
|
+
...stored.locale ? { locale: stored.locale } : {}
|
|
1464
1466
|
};
|
|
1465
1467
|
}
|
|
1466
1468
|
async function clearSessionArtifacts(configDir) {
|
|
@@ -2645,10 +2647,20 @@ var init_login = __esm({
|
|
|
2645
2647
|
const body = await res.json();
|
|
2646
2648
|
error(body.error ?? "Falha na autentica\xE7\xE3o");
|
|
2647
2649
|
}
|
|
2648
|
-
const { token, refreshToken, sessionId, userId, userName, expiresAt } = await res.json();
|
|
2649
|
-
await saveSession({
|
|
2650
|
+
const { token, refreshToken, sessionId, userId, userName, expiresAt, locale } = await res.json();
|
|
2651
|
+
await saveSession({
|
|
2652
|
+
token,
|
|
2653
|
+
refreshToken,
|
|
2654
|
+
sessionId,
|
|
2655
|
+
userId,
|
|
2656
|
+
userName,
|
|
2657
|
+
expiresAt,
|
|
2658
|
+
apiUrl,
|
|
2659
|
+
...locale === "pt-BR" || locale === "en-US" ? { locale } : {}
|
|
2660
|
+
});
|
|
2650
2661
|
console.log(`
|
|
2651
2662
|
\u2713 Logado como ${userName}`);
|
|
2663
|
+
const installedFiles = [];
|
|
2652
2664
|
try {
|
|
2653
2665
|
const { detectIDEs: detectIDEs2 } = await Promise.resolve().then(() => (init_ide_detector(), ide_detector_exports));
|
|
2654
2666
|
const { installUniversalCommand: installUniversalCommand2 } = await Promise.resolve().then(() => (init_instruction_files(), instruction_files_exports));
|
|
@@ -2664,7 +2676,6 @@ var init_login = __esm({
|
|
|
2664
2676
|
}
|
|
2665
2677
|
const cwd = process.cwd();
|
|
2666
2678
|
const home = homedir2();
|
|
2667
|
-
const installedFiles = [];
|
|
2668
2679
|
for (const runtime of RUNTIMES2) {
|
|
2669
2680
|
if (runtime.writeUniversal && runtime.detect(home, cwd)) {
|
|
2670
2681
|
installedFiles.push(...installUniversalCommand2(runtime.id, cwd));
|
|
@@ -2692,7 +2703,16 @@ var init_login = __esm({
|
|
|
2692
2703
|
}
|
|
2693
2704
|
console.log("");
|
|
2694
2705
|
console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
2695
|
-
console.log(" Pronto!
|
|
2706
|
+
console.log(" Pronto! Para estudar no terminal:");
|
|
2707
|
+
console.log("");
|
|
2708
|
+
console.log(" mkdir ~/meus-cursos && cd ~/meus-cursos");
|
|
2709
|
+
console.log(" tostudy courses lista seus cursos");
|
|
2710
|
+
console.log(" tostudy select <n> ativa um curso nesta pasta");
|
|
2711
|
+
console.log(" tostudy start abre a primeira aula");
|
|
2712
|
+
if (installedFiles.length > 0) {
|
|
2713
|
+
console.log("");
|
|
2714
|
+
console.log(" Ou, na sua IDE, digite /tostudy.");
|
|
2715
|
+
}
|
|
2696
2716
|
console.log("");
|
|
2697
2717
|
} catch (err) {
|
|
2698
2718
|
const msg = err instanceof Error ? err.message : "Login falhou";
|
|
@@ -2780,6 +2800,7 @@ var init_errors_pt_br = __esm({
|
|
|
2780
2800
|
insufficientCredits: "\u274C Voc\xEA est\xE1 sem cr\xE9ditos. Cada resposta do tutor de IA consome cr\xE9ditos para cobrir o processamento. Recarregue em https://tostudy.ai/student/credits para continuar de onde parou.\n",
|
|
2781
2801
|
workspaceRefusedAtHome: "N\xE3o d\xE1 para configurar o estudo direto na sua pasta pessoal.\nCrie uma pasta para o curso e entre nela antes de continuar:\n\n mkdir ~/meus-cursos && cd ~/meus-cursos\n",
|
|
2782
2802
|
courseArchived: "Este curso foi arquivado e est\xE1 dispon\xEDvel somente para leitura.\nUse `tostudy lesson` para revisar o conte\xFAdo j\xE1 estudado.\n",
|
|
2803
|
+
noActiveCourse: "Nenhum curso ativo nesta pasta.\nVeja seus cursos com `tostudy courses` e ative um com `tostudy select <n>`.\n",
|
|
2783
2804
|
enrollmentNotEntitled: "\u{1F6AB} Sua matr\xEDcula neste curso n\xE3o est\xE1 mais ativa (reembolso, cancelamento ou preview expirado).\nPara voltar a estudar, adquira o curso novamente em https://tostudy.ai.\n"
|
|
2784
2805
|
};
|
|
2785
2806
|
}
|
|
@@ -2801,12 +2822,25 @@ var init_errors_en_us = __esm({
|
|
|
2801
2822
|
insufficientCredits: "\u274C You're out of credits. Every reply from the AI tutor uses credits to cover processing. Top up at https://tostudy.ai/student/credits to continue from where you stopped.\n",
|
|
2802
2823
|
workspaceRefusedAtHome: "Study can't be set up directly in your home folder.\nCreate a folder for the course and switch into it first:\n\n mkdir ~/my-courses && cd ~/my-courses\n",
|
|
2803
2824
|
courseArchived: "This course has been archived and is available for reading only.\nUse `tostudy lesson` to review the content you've already studied.\n",
|
|
2825
|
+
noActiveCourse: "No active course in this folder.\nList your courses with `tostudy courses` and activate one with `tostudy select <n>`.\n",
|
|
2804
2826
|
enrollmentNotEntitled: "\u{1F6AB} Your enrollment in this course is no longer active (refund, cancellation, or expired preview).\nTo study again, purchase the course at https://tostudy.ai.\n"
|
|
2805
2827
|
};
|
|
2806
2828
|
}
|
|
2807
2829
|
});
|
|
2808
2830
|
|
|
2809
2831
|
// 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
|
+
}
|
|
2810
2844
|
function resolveLocale() {
|
|
2811
2845
|
if (_cachedLocale !== null) return _cachedLocale;
|
|
2812
2846
|
const argv = process.argv;
|
|
@@ -2818,6 +2852,11 @@ function resolveLocale() {
|
|
|
2818
2852
|
return val;
|
|
2819
2853
|
}
|
|
2820
2854
|
}
|
|
2855
|
+
const stored = readStoredLocale();
|
|
2856
|
+
if (stored) {
|
|
2857
|
+
_cachedLocale = stored;
|
|
2858
|
+
return stored;
|
|
2859
|
+
}
|
|
2821
2860
|
const lang = (process.env["LANG"] ?? "").toLowerCase();
|
|
2822
2861
|
if (lang.startsWith("en")) {
|
|
2823
2862
|
_cachedLocale = "en-US";
|
|
@@ -2849,6 +2888,7 @@ var BUNDLES, _cachedLocale;
|
|
|
2849
2888
|
var init_errors = __esm({
|
|
2850
2889
|
"src/errors/index.ts"() {
|
|
2851
2890
|
"use strict";
|
|
2891
|
+
init_config_dir();
|
|
2852
2892
|
init_errors_pt_br();
|
|
2853
2893
|
init_errors_en_us();
|
|
2854
2894
|
BUNDLES = {
|
|
@@ -2862,12 +2902,12 @@ var init_errors = __esm({
|
|
|
2862
2902
|
// src/workspace/workspace-marker.ts
|
|
2863
2903
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
2864
2904
|
import os4 from "node:os";
|
|
2865
|
-
import
|
|
2905
|
+
import path8 from "node:path";
|
|
2866
2906
|
function resolveMarkerPath(workspacePath) {
|
|
2867
|
-
if (
|
|
2868
|
-
return
|
|
2907
|
+
if (path8.basename(workspacePath) === ".tostudy") {
|
|
2908
|
+
return path8.join(workspacePath, "workspace.json");
|
|
2869
2909
|
}
|
|
2870
|
-
return
|
|
2910
|
+
return path8.join(workspacePath, ".tostudy", "workspace.json");
|
|
2871
2911
|
}
|
|
2872
2912
|
async function readWorkspaceMarker(workspacePath) {
|
|
2873
2913
|
const filePath = resolveMarkerPath(workspacePath);
|
|
@@ -2885,13 +2925,13 @@ async function readWorkspaceMarker(workspacePath) {
|
|
|
2885
2925
|
}
|
|
2886
2926
|
}
|
|
2887
2927
|
async function writeWorkspaceMarker(workspacePath, input2, options = {}) {
|
|
2888
|
-
const homeDir =
|
|
2889
|
-
const resolvedWorkspace =
|
|
2890
|
-
if (resolvedWorkspace === homeDir || homeDir.startsWith(resolvedWorkspace +
|
|
2928
|
+
const homeDir = path8.resolve(options.homeDir ?? os4.homedir());
|
|
2929
|
+
const resolvedWorkspace = path8.resolve(workspacePath);
|
|
2930
|
+
if (resolvedWorkspace === homeDir || homeDir.startsWith(resolvedWorkspace + path8.sep)) {
|
|
2891
2931
|
throw new Error(getErrors().workspaceRefusedAtHome);
|
|
2892
2932
|
}
|
|
2893
2933
|
const filePath = resolveMarkerPath(workspacePath);
|
|
2894
|
-
const dir =
|
|
2934
|
+
const dir = path8.dirname(filePath);
|
|
2895
2935
|
if (!existsSync3(dir)) {
|
|
2896
2936
|
mkdirSync3(dir, { recursive: true });
|
|
2897
2937
|
}
|
|
@@ -2928,7 +2968,7 @@ __export(workspace_state_exports, {
|
|
|
2928
2968
|
});
|
|
2929
2969
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2930
2970
|
import os5 from "node:os";
|
|
2931
|
-
import
|
|
2971
|
+
import path9 from "node:path";
|
|
2932
2972
|
async function readWorkspaceState(workspacePath) {
|
|
2933
2973
|
const marker = await readWorkspaceMarker(workspacePath);
|
|
2934
2974
|
if (!marker) return null;
|
|
@@ -2957,13 +2997,13 @@ async function readWorkspaceState(workspacePath) {
|
|
|
2957
2997
|
}
|
|
2958
2998
|
}
|
|
2959
2999
|
async function findWorkspaceState(startCwd = process.cwd(), homeDir = os5.homedir()) {
|
|
2960
|
-
const home =
|
|
2961
|
-
let current =
|
|
3000
|
+
const home = path9.resolve(homeDir);
|
|
3001
|
+
let current = path9.resolve(startCwd);
|
|
2962
3002
|
while (true) {
|
|
2963
3003
|
if (current === home) return null;
|
|
2964
3004
|
const state = await readWorkspaceState(current);
|
|
2965
3005
|
if (state) return { state, workspacePath: current };
|
|
2966
|
-
const parent =
|
|
3006
|
+
const parent = path9.dirname(current);
|
|
2967
3007
|
if (parent === current) return null;
|
|
2968
3008
|
current = parent;
|
|
2969
3009
|
}
|
|
@@ -3032,7 +3072,7 @@ __export(course_state_exports, {
|
|
|
3032
3072
|
setCourseWorkspacePath: () => setCourseWorkspacePath,
|
|
3033
3073
|
setLastInitCourseId: () => setLastInitCourseId
|
|
3034
3074
|
});
|
|
3035
|
-
import
|
|
3075
|
+
import fs7 from "node:fs";
|
|
3036
3076
|
async function getCourseOnboardingState(courseId, configDir) {
|
|
3037
3077
|
const state = readCourseOnboardingState(configDir);
|
|
3038
3078
|
return state[courseId] ?? null;
|
|
@@ -3054,7 +3094,7 @@ async function saveCourseLearnerProfile(course, learnerProfile, artifacts, confi
|
|
|
3054
3094
|
}
|
|
3055
3095
|
async function clearAllCourseOnboarding(configDir) {
|
|
3056
3096
|
const onboardingPath = getCourseOnboardingPath(configDir);
|
|
3057
|
-
if (
|
|
3097
|
+
if (fs7.existsSync(onboardingPath)) fs7.unlinkSync(onboardingPath);
|
|
3058
3098
|
}
|
|
3059
3099
|
var init_course_state = __esm({
|
|
3060
3100
|
"src/onboarding/course-state.ts"() {
|
|
@@ -3097,14 +3137,14 @@ __export(resolve_exports, {
|
|
|
3097
3137
|
resolveVaultPath: () => resolveVaultPath,
|
|
3098
3138
|
resolveWorkspace: () => resolveWorkspace
|
|
3099
3139
|
});
|
|
3100
|
-
import
|
|
3101
|
-
import
|
|
3140
|
+
import fs8 from "node:fs/promises";
|
|
3141
|
+
import path10 from "node:path";
|
|
3102
3142
|
import os6 from "node:os";
|
|
3103
3143
|
async function resolveWorkspace(courseTitle, basePath = DEFAULT_BASE) {
|
|
3104
3144
|
const slug = courseSlug(courseTitle);
|
|
3105
|
-
const candidate =
|
|
3145
|
+
const candidate = path10.join(basePath, slug);
|
|
3106
3146
|
try {
|
|
3107
|
-
await
|
|
3147
|
+
await fs8.access(path10.join(candidate, ".ana-config.json"));
|
|
3108
3148
|
return { found: true, workspacePath: candidate, source: "default" };
|
|
3109
3149
|
} catch {
|
|
3110
3150
|
return { found: false, workspacePath: null };
|
|
@@ -3114,49 +3154,49 @@ async function isCwdWorkspace(cwd = process.cwd()) {
|
|
|
3114
3154
|
return await resolveCwdWorkspacePath(cwd) !== null;
|
|
3115
3155
|
}
|
|
3116
3156
|
async function resolveCwdWorkspacePath(cwd = process.cwd()) {
|
|
3117
|
-
const tostudyDir =
|
|
3157
|
+
const tostudyDir = path10.join(cwd, ".tostudy");
|
|
3118
3158
|
try {
|
|
3119
|
-
const stat = await
|
|
3159
|
+
const stat = await fs8.stat(tostudyDir);
|
|
3120
3160
|
if (stat.isDirectory()) return tostudyDir;
|
|
3121
3161
|
} catch {
|
|
3122
3162
|
}
|
|
3123
3163
|
try {
|
|
3124
|
-
await
|
|
3164
|
+
await fs8.access(path10.join(cwd, ".ana-config.json"));
|
|
3125
3165
|
return cwd;
|
|
3126
3166
|
} catch {
|
|
3127
3167
|
return null;
|
|
3128
3168
|
}
|
|
3129
3169
|
}
|
|
3130
3170
|
async function findCwdWorkspaceUpwards(startCwd = process.cwd(), homeDir = os6.homedir()) {
|
|
3131
|
-
const home =
|
|
3132
|
-
let current =
|
|
3171
|
+
const home = path10.resolve(homeDir);
|
|
3172
|
+
let current = path10.resolve(startCwd);
|
|
3133
3173
|
while (true) {
|
|
3134
3174
|
if (current === home) return null;
|
|
3135
3175
|
const direct = await resolveCwdWorkspacePath(current);
|
|
3136
3176
|
if (direct) return direct;
|
|
3137
|
-
const parent =
|
|
3177
|
+
const parent = path10.dirname(current);
|
|
3138
3178
|
if (parent === current) return null;
|
|
3139
3179
|
current = parent;
|
|
3140
3180
|
}
|
|
3141
3181
|
}
|
|
3142
3182
|
function resolveVaultPath(workspacePath, slug) {
|
|
3143
|
-
const base =
|
|
3144
|
-
return
|
|
3183
|
+
const base = path10.basename(workspacePath) === ".tostudy" ? path10.dirname(workspacePath) : workspacePath;
|
|
3184
|
+
return path10.join(base, `vault-${slug}`);
|
|
3145
3185
|
}
|
|
3146
3186
|
function cliWorkspacePaths(workspacePath, courseTitle) {
|
|
3147
|
-
const base =
|
|
3187
|
+
const base = path10.basename(workspacePath) === ".tostudy" ? path10.dirname(workspacePath) : workspacePath;
|
|
3148
3188
|
return { workspace: base, vault: resolveVaultPath(workspacePath, courseSlug(courseTitle)) };
|
|
3149
3189
|
}
|
|
3150
3190
|
async function findExistingVault(workspacePath, slug) {
|
|
3151
3191
|
const slugged = resolveVaultPath(workspacePath, slug);
|
|
3152
3192
|
try {
|
|
3153
|
-
await
|
|
3193
|
+
await fs8.access(path10.join(slugged, ".ana-vault.json"));
|
|
3154
3194
|
return slugged;
|
|
3155
3195
|
} catch {
|
|
3156
3196
|
}
|
|
3157
|
-
const legacy =
|
|
3197
|
+
const legacy = path10.join(workspacePath, "vault");
|
|
3158
3198
|
try {
|
|
3159
|
-
await
|
|
3199
|
+
await fs8.access(path10.join(legacy, ".ana-vault.json"));
|
|
3160
3200
|
return legacy;
|
|
3161
3201
|
} catch {
|
|
3162
3202
|
return null;
|
|
@@ -3169,7 +3209,7 @@ async function resolveEffectiveWorkspace(courseTitle, storedPath, cwd = process.
|
|
|
3169
3209
|
}
|
|
3170
3210
|
if (storedPath) {
|
|
3171
3211
|
try {
|
|
3172
|
-
await
|
|
3212
|
+
await fs8.access(path10.join(storedPath, ".ana-config.json"));
|
|
3173
3213
|
return { found: true, workspacePath: storedPath, source: "stored" };
|
|
3174
3214
|
} catch {
|
|
3175
3215
|
}
|
|
@@ -3190,7 +3230,7 @@ var init_resolve = __esm({
|
|
|
3190
3230
|
"src/workspace/resolve.ts"() {
|
|
3191
3231
|
"use strict";
|
|
3192
3232
|
init_slug();
|
|
3193
|
-
DEFAULT_BASE =
|
|
3233
|
+
DEFAULT_BASE = path10.join(os6.homedir(), "study");
|
|
3194
3234
|
courseSlug = slugify;
|
|
3195
3235
|
resolveActiveCourseWithOverride = resolveActiveCourseFromWorkspace;
|
|
3196
3236
|
}
|
|
@@ -3246,7 +3286,7 @@ async function requireActiveCourse() {
|
|
|
3246
3286
|
await primeWorkspaceTokenPaths(result.state);
|
|
3247
3287
|
return result.state;
|
|
3248
3288
|
}
|
|
3249
|
-
process.stderr.write(
|
|
3289
|
+
process.stderr.write(`Erro: ${getErrors().noActiveCourse}`);
|
|
3250
3290
|
process.exit(3);
|
|
3251
3291
|
}
|
|
3252
3292
|
async function primeWorkspaceTokenPaths(state) {
|
|
@@ -3272,6 +3312,7 @@ var init_guards = __esm({
|
|
|
3272
3312
|
"src/auth/guards.ts"() {
|
|
3273
3313
|
"use strict";
|
|
3274
3314
|
init_session_store();
|
|
3315
|
+
init_errors();
|
|
3275
3316
|
}
|
|
3276
3317
|
});
|
|
3277
3318
|
|
|
@@ -3320,7 +3361,9 @@ var init_mcp_setup = __esm({
|
|
|
3320
3361
|
import { Command as Command3 } from "commander";
|
|
3321
3362
|
async function runSetup(_opts, deps = defaultDeps) {
|
|
3322
3363
|
deps.log("\n \u26A0\uFE0F `tostudy setup` foi incorporado ao `tostudy login`.");
|
|
3323
|
-
deps.log(
|
|
3364
|
+
deps.log(
|
|
3365
|
+
" Rode `tostudy login`, depois `tostudy courses` e `tostudy select <n>` para estudar no terminal.\n"
|
|
3366
|
+
);
|
|
3324
3367
|
}
|
|
3325
3368
|
async function runSetupMcpSubcommand() {
|
|
3326
3369
|
console.log("\n ToStudy MCP Setup\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
@@ -3383,7 +3426,7 @@ var CLI_VERSION;
|
|
|
3383
3426
|
var init_version = __esm({
|
|
3384
3427
|
"src/version.ts"() {
|
|
3385
3428
|
"use strict";
|
|
3386
|
-
CLI_VERSION = true ? "0.16.
|
|
3429
|
+
CLI_VERSION = true ? "0.16.9" : "0.7.1";
|
|
3387
3430
|
}
|
|
3388
3431
|
});
|
|
3389
3432
|
|
|
@@ -3397,13 +3440,13 @@ __export(update_checker_exports, {
|
|
|
3397
3440
|
readCache: () => readCache,
|
|
3398
3441
|
writeCache: () => writeCache
|
|
3399
3442
|
});
|
|
3400
|
-
import
|
|
3401
|
-
import
|
|
3443
|
+
import fs9 from "node:fs";
|
|
3444
|
+
import path11 from "node:path";
|
|
3402
3445
|
function readCache(configDir) {
|
|
3403
3446
|
try {
|
|
3404
|
-
const p =
|
|
3405
|
-
if (!
|
|
3406
|
-
return JSON.parse(
|
|
3447
|
+
const p = path11.join(configDir ?? getConfigDir(), CACHE_FILE);
|
|
3448
|
+
if (!fs9.existsSync(p)) return null;
|
|
3449
|
+
return JSON.parse(fs9.readFileSync(p, "utf-8"));
|
|
3407
3450
|
} catch {
|
|
3408
3451
|
return null;
|
|
3409
3452
|
}
|
|
@@ -3411,8 +3454,8 @@ function readCache(configDir) {
|
|
|
3411
3454
|
function writeCache(cache, configDir) {
|
|
3412
3455
|
try {
|
|
3413
3456
|
const dir = configDir ?? getConfigDir();
|
|
3414
|
-
|
|
3415
|
-
|
|
3457
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
3458
|
+
fs9.writeFileSync(path11.join(dir, CACHE_FILE), JSON.stringify(cache));
|
|
3416
3459
|
} catch {
|
|
3417
3460
|
}
|
|
3418
3461
|
}
|
|
@@ -3482,17 +3525,17 @@ var init_update_checker = __esm({
|
|
|
3482
3525
|
});
|
|
3483
3526
|
|
|
3484
3527
|
// src/learner-brief/cache.ts
|
|
3485
|
-
import
|
|
3486
|
-
import
|
|
3528
|
+
import fs10 from "node:fs";
|
|
3529
|
+
import path12 from "node:path";
|
|
3487
3530
|
function resolveCachePath(configDir) {
|
|
3488
|
-
return
|
|
3531
|
+
return path12.join(configDir, "student-brief.json");
|
|
3489
3532
|
}
|
|
3490
3533
|
async function readBriefCache(configDir) {
|
|
3491
3534
|
const dir = configDir ?? getConfigDir();
|
|
3492
3535
|
const p = resolveCachePath(dir);
|
|
3493
|
-
if (!
|
|
3536
|
+
if (!fs10.existsSync(p)) return null;
|
|
3494
3537
|
try {
|
|
3495
|
-
const raw =
|
|
3538
|
+
const raw = fs10.readFileSync(p, "utf-8");
|
|
3496
3539
|
return JSON.parse(raw);
|
|
3497
3540
|
} catch {
|
|
3498
3541
|
return null;
|
|
@@ -3500,8 +3543,8 @@ async function readBriefCache(configDir) {
|
|
|
3500
3543
|
}
|
|
3501
3544
|
async function writeBriefCache(configDir, cache) {
|
|
3502
3545
|
const dir = configDir ?? getConfigDir();
|
|
3503
|
-
|
|
3504
|
-
|
|
3546
|
+
fs10.mkdirSync(dir, { recursive: true });
|
|
3547
|
+
fs10.writeFileSync(resolveCachePath(dir), JSON.stringify(cache, null, 2), { mode: 384 });
|
|
3505
3548
|
}
|
|
3506
3549
|
var init_cache = __esm({
|
|
3507
3550
|
"src/learner-brief/cache.ts"() {
|
|
@@ -3511,23 +3554,23 @@ var init_cache = __esm({
|
|
|
3511
3554
|
});
|
|
3512
3555
|
|
|
3513
3556
|
// src/tutor-persona/cache.ts
|
|
3514
|
-
import
|
|
3515
|
-
import
|
|
3557
|
+
import fs11 from "node:fs";
|
|
3558
|
+
import path13 from "node:path";
|
|
3516
3559
|
function resolveCachePath2(configDir) {
|
|
3517
|
-
return
|
|
3560
|
+
return path13.join(configDir, "tutor-personalities.json");
|
|
3518
3561
|
}
|
|
3519
3562
|
function readAll(configDir) {
|
|
3520
3563
|
const p = resolveCachePath2(configDir);
|
|
3521
|
-
if (!
|
|
3564
|
+
if (!fs11.existsSync(p)) return {};
|
|
3522
3565
|
try {
|
|
3523
|
-
return JSON.parse(
|
|
3566
|
+
return JSON.parse(fs11.readFileSync(p, "utf-8"));
|
|
3524
3567
|
} catch {
|
|
3525
3568
|
return {};
|
|
3526
3569
|
}
|
|
3527
3570
|
}
|
|
3528
3571
|
function writeAll(configDir, cache) {
|
|
3529
|
-
|
|
3530
|
-
|
|
3572
|
+
fs11.mkdirSync(configDir, { recursive: true });
|
|
3573
|
+
fs11.writeFileSync(resolveCachePath2(configDir), JSON.stringify(cache, null, 2), { mode: 384 });
|
|
3531
3574
|
}
|
|
3532
3575
|
async function readPersonaCacheForCourse(configDir, courseId) {
|
|
3533
3576
|
const dir = configDir ?? getConfigDir();
|
|
@@ -4770,7 +4813,7 @@ var init_next = __esm({
|
|
|
4770
4813
|
|
|
4771
4814
|
// src/commands/lesson.ts
|
|
4772
4815
|
import { Command as Command11 } from "commander";
|
|
4773
|
-
import
|
|
4816
|
+
import path14 from "node:path";
|
|
4774
4817
|
function adjustTimeEstimate(type, baseMinutes) {
|
|
4775
4818
|
if (type === "exercise") return Math.max(baseMinutes, 30);
|
|
4776
4819
|
return baseMinutes;
|
|
@@ -4783,7 +4826,7 @@ function formatLessonContent(data, workspacePath, courseTitle) {
|
|
|
4783
4826
|
const isPractical = data.type === "exercise" || isCheckpoint(data.title);
|
|
4784
4827
|
const lines = [`\u2501\u2501\u2501 Li\xE7\xE3o: ${data.title} \u2501\u2501\u2501`];
|
|
4785
4828
|
if (isPractical && workspacePath) {
|
|
4786
|
-
const base =
|
|
4829
|
+
const base = path14.basename(workspacePath) === ".tostudy" ? path14.dirname(workspacePath) : workspacePath;
|
|
4787
4830
|
const slug = courseSlug(courseTitle);
|
|
4788
4831
|
const vaultPath = resolveVaultPath(workspacePath, slug);
|
|
4789
4832
|
lines.push(
|
|
@@ -5327,10 +5370,10 @@ function mergeDefs(...defs) {
|
|
|
5327
5370
|
function cloneDef(schema) {
|
|
5328
5371
|
return mergeDefs(schema._zod.def);
|
|
5329
5372
|
}
|
|
5330
|
-
function getElementAtPath(obj,
|
|
5331
|
-
if (!
|
|
5373
|
+
function getElementAtPath(obj, path25) {
|
|
5374
|
+
if (!path25)
|
|
5332
5375
|
return obj;
|
|
5333
|
-
return
|
|
5376
|
+
return path25.reduce((acc, key) => acc?.[key], obj);
|
|
5334
5377
|
}
|
|
5335
5378
|
function promiseAllObject(promisesObj) {
|
|
5336
5379
|
const keys = Object.keys(promisesObj);
|
|
@@ -5642,11 +5685,11 @@ function aborted(x, startIndex = 0) {
|
|
|
5642
5685
|
}
|
|
5643
5686
|
return false;
|
|
5644
5687
|
}
|
|
5645
|
-
function prefixIssues(
|
|
5688
|
+
function prefixIssues(path25, issues) {
|
|
5646
5689
|
return issues.map((iss) => {
|
|
5647
5690
|
var _a2;
|
|
5648
5691
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
5649
|
-
iss.path.unshift(
|
|
5692
|
+
iss.path.unshift(path25);
|
|
5650
5693
|
return iss;
|
|
5651
5694
|
});
|
|
5652
5695
|
}
|
|
@@ -5888,7 +5931,7 @@ function formatError(error49, mapper = (issue2) => issue2.message) {
|
|
|
5888
5931
|
}
|
|
5889
5932
|
function treeifyError(error49, mapper = (issue2) => issue2.message) {
|
|
5890
5933
|
const result = { errors: [] };
|
|
5891
|
-
const processError = (error50,
|
|
5934
|
+
const processError = (error50, path25 = []) => {
|
|
5892
5935
|
var _a2, _b;
|
|
5893
5936
|
for (const issue2 of error50.issues) {
|
|
5894
5937
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -5898,7 +5941,7 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
|
|
|
5898
5941
|
} else if (issue2.code === "invalid_element") {
|
|
5899
5942
|
processError({ issues: issue2.issues }, issue2.path);
|
|
5900
5943
|
} else {
|
|
5901
|
-
const fullpath = [...
|
|
5944
|
+
const fullpath = [...path25, ...issue2.path];
|
|
5902
5945
|
if (fullpath.length === 0) {
|
|
5903
5946
|
result.errors.push(mapper(issue2));
|
|
5904
5947
|
continue;
|
|
@@ -5930,8 +5973,8 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
|
|
|
5930
5973
|
}
|
|
5931
5974
|
function toDotPath(_path) {
|
|
5932
5975
|
const segs = [];
|
|
5933
|
-
const
|
|
5934
|
-
for (const seg of
|
|
5976
|
+
const path25 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5977
|
+
for (const seg of path25) {
|
|
5935
5978
|
if (typeof seg === "number")
|
|
5936
5979
|
segs.push(`[${seg}]`);
|
|
5937
5980
|
else if (typeof seg === "symbol")
|
|
@@ -18625,13 +18668,13 @@ function resolveRef(ref, ctx) {
|
|
|
18625
18668
|
if (!ref.startsWith("#")) {
|
|
18626
18669
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
18627
18670
|
}
|
|
18628
|
-
const
|
|
18629
|
-
if (
|
|
18671
|
+
const path25 = ref.slice(1).split("/").filter(Boolean);
|
|
18672
|
+
if (path25.length === 0) {
|
|
18630
18673
|
return ctx.rootSchema;
|
|
18631
18674
|
}
|
|
18632
18675
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
18633
|
-
if (
|
|
18634
|
-
const key =
|
|
18676
|
+
if (path25[0] === defsKey) {
|
|
18677
|
+
const key = path25[1];
|
|
18635
18678
|
if (!key || !ctx.defs[key]) {
|
|
18636
18679
|
throw new Error(`Reference not found: ${ref}`);
|
|
18637
18680
|
}
|
|
@@ -19963,8 +20006,8 @@ var init_init_template = __esm({
|
|
|
19963
20006
|
});
|
|
19964
20007
|
|
|
19965
20008
|
// src/commands/validate.ts
|
|
19966
|
-
import
|
|
19967
|
-
import
|
|
20009
|
+
import fs12 from "node:fs";
|
|
20010
|
+
import path15 from "node:path";
|
|
19968
20011
|
import { Command as Command14 } from "commander";
|
|
19969
20012
|
var logger16, validateCommand;
|
|
19970
20013
|
var init_validate = __esm({
|
|
@@ -20008,21 +20051,21 @@ var init_validate = __esm({
|
|
|
20008
20051
|
}
|
|
20009
20052
|
let solution;
|
|
20010
20053
|
if (opts.stdin) {
|
|
20011
|
-
solution =
|
|
20054
|
+
solution = fs12.readFileSync("/dev/stdin", "utf-8");
|
|
20012
20055
|
} else if (file2) {
|
|
20013
|
-
if (!
|
|
20056
|
+
if (!fs12.existsSync(file2)) {
|
|
20014
20057
|
if (opts.json)
|
|
20015
20058
|
jsonError("file_not_found", { message: `Arquivo n\xE3o encontrado: ${file2}` });
|
|
20016
20059
|
error(`Arquivo n\xE3o encontrado: ${file2}`);
|
|
20017
20060
|
}
|
|
20018
|
-
solution =
|
|
20061
|
+
solution = fs12.readFileSync(file2, "utf-8");
|
|
20019
20062
|
} else {
|
|
20020
20063
|
if (opts.json)
|
|
20021
20064
|
jsonError("no_solution_provided", { message: "Forne\xE7a um arquivo ou use --stdin" });
|
|
20022
20065
|
error("Forne\xE7a um arquivo ou use --stdin.\n\nExemplo: tostudy validate resposta.md");
|
|
20023
20066
|
}
|
|
20024
20067
|
if (file2 && activeCourse.courseTags?.length) {
|
|
20025
|
-
const ext =
|
|
20068
|
+
const ext = path15.extname(file2).toLowerCase();
|
|
20026
20069
|
const LANG_EXTENSIONS = {
|
|
20027
20070
|
".html": ["html", "html5"],
|
|
20028
20071
|
".css": ["css"],
|
|
@@ -20204,8 +20247,8 @@ async function collectLearnerContextProfileWithDeps(input2, deps) {
|
|
|
20204
20247
|
`- Regiao: ${existingProfile.region}`,
|
|
20205
20248
|
`- Equipe: ${existingProfile.team}`,
|
|
20206
20249
|
`- Objetivo: ${existingProfile.goal}`,
|
|
20207
|
-
`-
|
|
20208
|
-
`- Contexto real: ${existingProfile.adaptToRealContext ? "sim" : "
|
|
20250
|
+
`- N\xEDvel: ${existingProfile.learnerLevel}`,
|
|
20251
|
+
`- Contexto real: ${existingProfile.adaptToRealContext ? "sim" : "n\xE3o"}`,
|
|
20209
20252
|
""
|
|
20210
20253
|
].join("\n")
|
|
20211
20254
|
);
|
|
@@ -20248,7 +20291,7 @@ async function collectLearnerContextProfileWithDeps(input2, deps) {
|
|
|
20248
20291
|
baseProfile?.goal
|
|
20249
20292
|
);
|
|
20250
20293
|
const learnerLevel = action === "keep" && baseProfile ? baseProfile.learnerLevel : await askChoice(
|
|
20251
|
-
baseProfile ? `
|
|
20294
|
+
baseProfile ? `N\xEDvel do aluno (beginner/intermediate/advanced) [${baseProfile.learnerLevel}]: ` : "N\xEDvel do aluno (beginner/intermediate/advanced): ",
|
|
20252
20295
|
["beginner", "intermediate", "advanced"],
|
|
20253
20296
|
deps,
|
|
20254
20297
|
baseProfile?.learnerLevel
|
|
@@ -20294,7 +20337,7 @@ function isCompleteProfile(flags) {
|
|
|
20294
20337
|
async function runInit(deps = defaultDeps4, flags = {}) {
|
|
20295
20338
|
const session = await deps.getSession();
|
|
20296
20339
|
if (!session) {
|
|
20297
|
-
deps.output("
|
|
20340
|
+
deps.output("N\xE3o autenticado. Rode `tostudy login` para come\xE7ar.", { json: false });
|
|
20298
20341
|
return;
|
|
20299
20342
|
}
|
|
20300
20343
|
const data = deps.createHttpProvider(session.apiUrl, session.token);
|
|
@@ -20490,14 +20533,14 @@ var init_init = __esm({
|
|
|
20490
20533
|
});
|
|
20491
20534
|
|
|
20492
20535
|
// ../../packages/tostudy-core/src/workspace/setup-workspace.ts
|
|
20493
|
-
import
|
|
20494
|
-
import
|
|
20536
|
+
import fs13 from "node:fs/promises";
|
|
20537
|
+
import path16 from "node:path";
|
|
20495
20538
|
async function setupWorkspace(input2) {
|
|
20496
|
-
const workspacePath =
|
|
20539
|
+
const workspacePath = path16.join(input2.basePath, input2.courseSlug);
|
|
20497
20540
|
for (const dir of WORKSPACE_DIRS) {
|
|
20498
|
-
await
|
|
20541
|
+
await fs13.mkdir(path16.join(workspacePath, dir), { recursive: true });
|
|
20499
20542
|
}
|
|
20500
|
-
const configPath =
|
|
20543
|
+
const configPath = path16.join(workspacePath, ".ana-config.json");
|
|
20501
20544
|
const config2 = {
|
|
20502
20545
|
courseId: input2.courseId,
|
|
20503
20546
|
courseSlug: input2.courseSlug,
|
|
@@ -20507,7 +20550,7 @@ async function setupWorkspace(input2) {
|
|
|
20507
20550
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20508
20551
|
lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20509
20552
|
};
|
|
20510
|
-
await
|
|
20553
|
+
await fs13.writeFile(configPath, JSON.stringify(config2, null, 2), "utf-8");
|
|
20511
20554
|
const readme = [
|
|
20512
20555
|
`# ${input2.courseName}`,
|
|
20513
20556
|
"",
|
|
@@ -20532,7 +20575,7 @@ async function setupWorkspace(input2) {
|
|
|
20532
20575
|
"tostudy vault sync # Sincronizar progresso",
|
|
20533
20576
|
"```"
|
|
20534
20577
|
].join("\n");
|
|
20535
|
-
await
|
|
20578
|
+
await fs13.writeFile(path16.join(workspacePath, "README.md"), readme, "utf-8");
|
|
20536
20579
|
return { workspacePath, directories: WORKSPACE_DIRS, configPath };
|
|
20537
20580
|
}
|
|
20538
20581
|
var WORKSPACE_DIRS;
|
|
@@ -20633,8 +20676,8 @@ var init_templates = __esm({
|
|
|
20633
20676
|
});
|
|
20634
20677
|
|
|
20635
20678
|
// ../../packages/tostudy-core/src/workspace/extract-exercise.ts
|
|
20636
|
-
import
|
|
20637
|
-
import
|
|
20679
|
+
import fs14 from "node:fs/promises";
|
|
20680
|
+
import path17 from "node:path";
|
|
20638
20681
|
function padOrder(n) {
|
|
20639
20682
|
return String(n).padStart(2, "0");
|
|
20640
20683
|
}
|
|
@@ -20660,16 +20703,16 @@ async function extractExercise(input2) {
|
|
|
20660
20703
|
const lessonData = resolveWorkspaceTokens(input2.lessonData, paths);
|
|
20661
20704
|
const moduleDir = `${padOrder(lessonData.moduleOrder)}-${lessonData.moduleSlug}`;
|
|
20662
20705
|
const lessonDir = `${padOrder(lessonData.lessonOrder)}-${lessonData.lessonSlug}`;
|
|
20663
|
-
const exercisePath =
|
|
20664
|
-
await
|
|
20706
|
+
const exercisePath = path17.join(workspacePath, "exercises", moduleDir, lessonDir);
|
|
20707
|
+
await fs14.mkdir(exercisePath, { recursive: true });
|
|
20665
20708
|
const extractedFiles = [];
|
|
20666
20709
|
let hasStarterCode = false;
|
|
20667
20710
|
if (lessonData.sandpackConfig?.files) {
|
|
20668
20711
|
for (const [filePath, fileData] of Object.entries(lessonData.sandpackConfig.files)) {
|
|
20669
20712
|
const cleanPath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
20670
|
-
const fullPath =
|
|
20671
|
-
await
|
|
20672
|
-
await
|
|
20713
|
+
const fullPath = path17.join(exercisePath, cleanPath);
|
|
20714
|
+
await fs14.mkdir(path17.dirname(fullPath), { recursive: true });
|
|
20715
|
+
await fs14.writeFile(fullPath, fileData.code, "utf-8");
|
|
20673
20716
|
extractedFiles.push(cleanPath);
|
|
20674
20717
|
hasStarterCode = true;
|
|
20675
20718
|
}
|
|
@@ -20677,13 +20720,13 @@ async function extractExercise(input2) {
|
|
|
20677
20720
|
const tierData = getTierData(lessonData.structuredData, exerciseTier);
|
|
20678
20721
|
const tierCode = tierData?.code;
|
|
20679
20722
|
if (tierCode) {
|
|
20680
|
-
await
|
|
20723
|
+
await fs14.writeFile(path17.join(exercisePath, "exercise.js"), tierCode, "utf-8");
|
|
20681
20724
|
extractedFiles.push("exercise.js");
|
|
20682
20725
|
hasStarterCode = true;
|
|
20683
20726
|
} else {
|
|
20684
20727
|
const starter = getStarterCode(lessonData.structuredData);
|
|
20685
20728
|
if (starter) {
|
|
20686
|
-
await
|
|
20729
|
+
await fs14.writeFile(path17.join(exercisePath, "exercise.js"), starter, "utf-8");
|
|
20687
20730
|
extractedFiles.push("exercise.js");
|
|
20688
20731
|
hasStarterCode = true;
|
|
20689
20732
|
}
|
|
@@ -20701,8 +20744,8 @@ async function extractExercise(input2) {
|
|
|
20701
20744
|
...exerciseDeps
|
|
20702
20745
|
}
|
|
20703
20746
|
};
|
|
20704
|
-
await
|
|
20705
|
-
|
|
20747
|
+
await fs14.writeFile(
|
|
20748
|
+
path17.join(exercisePath, "package.json"),
|
|
20706
20749
|
JSON.stringify(pkgJson, null, 2),
|
|
20707
20750
|
"utf-8"
|
|
20708
20751
|
);
|
|
@@ -20714,20 +20757,20 @@ async function extractExercise(input2) {
|
|
|
20714
20757
|
);
|
|
20715
20758
|
for (const [configFile, configContent] of Object.entries(scaffold.configs)) {
|
|
20716
20759
|
if (!sandpackFileNames.has(configFile)) {
|
|
20717
|
-
await
|
|
20760
|
+
await fs14.writeFile(path17.join(exercisePath, configFile), configContent, "utf-8");
|
|
20718
20761
|
extractedFiles.push(configFile);
|
|
20719
20762
|
}
|
|
20720
20763
|
}
|
|
20721
20764
|
const setupSh = `#!/bin/sh
|
|
20722
20765
|
${scaffold.setupScript}
|
|
20723
20766
|
`;
|
|
20724
|
-
await
|
|
20767
|
+
await fs14.writeFile(path17.join(exercisePath, "setup.sh"), setupSh, "utf-8");
|
|
20725
20768
|
extractedFiles.push("setup.sh");
|
|
20726
20769
|
}
|
|
20727
20770
|
}
|
|
20728
20771
|
const readme = generateReadme(lessonData, exerciseTier);
|
|
20729
|
-
const readmePath =
|
|
20730
|
-
await
|
|
20772
|
+
const readmePath = path17.join(exercisePath, "README.md");
|
|
20773
|
+
await fs14.writeFile(readmePath, readme, "utf-8");
|
|
20731
20774
|
extractedFiles.push("README.md");
|
|
20732
20775
|
return {
|
|
20733
20776
|
exercisePath,
|
|
@@ -20809,9 +20852,9 @@ var init_workspace = __esm({
|
|
|
20809
20852
|
|
|
20810
20853
|
// src/commands/workspace.ts
|
|
20811
20854
|
import { Command as Command17 } from "commander";
|
|
20812
|
-
import
|
|
20855
|
+
import path18 from "node:path";
|
|
20813
20856
|
import os8 from "node:os";
|
|
20814
|
-
import
|
|
20857
|
+
import fs15 from "node:fs/promises";
|
|
20815
20858
|
var logger18, workspaceCommand;
|
|
20816
20859
|
var init_workspace2 = __esm({
|
|
20817
20860
|
"src/commands/workspace.ts"() {
|
|
@@ -20835,14 +20878,14 @@ var init_workspace2 = __esm({
|
|
|
20835
20878
|
let directories;
|
|
20836
20879
|
if (!opts.path && cwdIsWorkspace) {
|
|
20837
20880
|
const resolvedCwd = await resolveCwdWorkspacePath(process.cwd());
|
|
20838
|
-
workspacePath = resolvedCwd ??
|
|
20839
|
-
await
|
|
20881
|
+
workspacePath = resolvedCwd ?? path18.join(process.cwd(), ".tostudy");
|
|
20882
|
+
await fs15.mkdir(workspacePath, { recursive: true });
|
|
20840
20883
|
directories = ["exercises", "generated", "notes", "diagrams"];
|
|
20841
20884
|
for (const dir of directories) {
|
|
20842
|
-
await
|
|
20885
|
+
await fs15.mkdir(path18.join(workspacePath, dir), { recursive: true });
|
|
20843
20886
|
}
|
|
20844
|
-
const configPath =
|
|
20845
|
-
await
|
|
20887
|
+
const configPath = path18.join(workspacePath, ".ana-config.json");
|
|
20888
|
+
await fs15.writeFile(
|
|
20846
20889
|
configPath,
|
|
20847
20890
|
JSON.stringify(
|
|
20848
20891
|
{
|
|
@@ -20860,7 +20903,7 @@ var init_workspace2 = __esm({
|
|
|
20860
20903
|
"utf-8"
|
|
20861
20904
|
);
|
|
20862
20905
|
} else {
|
|
20863
|
-
const basePath = opts.path ??
|
|
20906
|
+
const basePath = opts.path ?? path18.join(os8.homedir(), "study");
|
|
20864
20907
|
const result2 = await setupWorkspace({
|
|
20865
20908
|
courseId: activeCourse.courseId,
|
|
20866
20909
|
courseSlug: courseSlug(activeCourse.courseTitle),
|
|
@@ -20894,7 +20937,7 @@ Pr\xF3ximo passo: tostudy export
|
|
|
20894
20937
|
process.exit(1);
|
|
20895
20938
|
}
|
|
20896
20939
|
});
|
|
20897
|
-
workspaceCommand.command("status").description("Mostrar status do workspace do curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
20940
|
+
workspaceCommand.command("status").description("Mostrar status do workspace do curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path18.join(os8.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
20898
20941
|
try {
|
|
20899
20942
|
const activeCourse = await requireActiveCourse();
|
|
20900
20943
|
const onboardingState = await getCourseOnboardingState(activeCourse.courseId);
|
|
@@ -20911,40 +20954,40 @@ Pr\xF3ximo passo: tostudy export
|
|
|
20911
20954
|
const workspacePath = ws.workspacePath;
|
|
20912
20955
|
let configData = null;
|
|
20913
20956
|
try {
|
|
20914
|
-
const raw = await
|
|
20957
|
+
const raw = await fs15.readFile(path18.join(workspacePath, ".ana-config.json"), "utf-8");
|
|
20915
20958
|
configData = JSON.parse(raw);
|
|
20916
20959
|
} catch {
|
|
20917
20960
|
configData = null;
|
|
20918
20961
|
}
|
|
20919
|
-
const exercisesDir =
|
|
20962
|
+
const exercisesDir = path18.join(workspacePath, "exercises");
|
|
20920
20963
|
let exerciseCount = 0;
|
|
20921
20964
|
try {
|
|
20922
|
-
const moduleDirs = await
|
|
20965
|
+
const moduleDirs = await fs15.readdir(exercisesDir);
|
|
20923
20966
|
for (const modDir of moduleDirs) {
|
|
20924
|
-
const modPath =
|
|
20925
|
-
const stat = await
|
|
20967
|
+
const modPath = path18.join(exercisesDir, modDir);
|
|
20968
|
+
const stat = await fs15.stat(modPath);
|
|
20926
20969
|
if (stat.isDirectory()) {
|
|
20927
|
-
const lessonDirs = await
|
|
20970
|
+
const lessonDirs = await fs15.readdir(modPath);
|
|
20928
20971
|
for (const lessonDir of lessonDirs) {
|
|
20929
|
-
const lessonPath =
|
|
20930
|
-
const lstat = await
|
|
20972
|
+
const lessonPath = path18.join(modPath, lessonDir);
|
|
20973
|
+
const lstat = await fs15.stat(lessonPath);
|
|
20931
20974
|
if (lstat.isDirectory()) exerciseCount++;
|
|
20932
20975
|
}
|
|
20933
20976
|
}
|
|
20934
20977
|
}
|
|
20935
20978
|
} catch {
|
|
20936
20979
|
}
|
|
20937
|
-
const generatedDir =
|
|
20980
|
+
const generatedDir = path18.join(workspacePath, "generated");
|
|
20938
20981
|
let artifactCount = 0;
|
|
20939
20982
|
try {
|
|
20940
|
-
const files = await
|
|
20983
|
+
const files = await fs15.readdir(generatedDir);
|
|
20941
20984
|
artifactCount = files.length;
|
|
20942
20985
|
} catch {
|
|
20943
20986
|
}
|
|
20944
|
-
const diagramsDir =
|
|
20987
|
+
const diagramsDir = path18.join(workspacePath, "diagrams");
|
|
20945
20988
|
let diagramCount = 0;
|
|
20946
20989
|
try {
|
|
20947
|
-
const files = await
|
|
20990
|
+
const files = await fs15.readdir(diagramsDir);
|
|
20948
20991
|
diagramCount = files.length;
|
|
20949
20992
|
} catch {
|
|
20950
20993
|
}
|
|
@@ -20993,9 +21036,9 @@ Pr\xF3ximo passo: tostudy export
|
|
|
20993
21036
|
|
|
20994
21037
|
// src/commands/export.ts
|
|
20995
21038
|
import { Command as Command18 } from "commander";
|
|
20996
|
-
import
|
|
21039
|
+
import path19 from "node:path";
|
|
20997
21040
|
import os9 from "node:os";
|
|
20998
|
-
import
|
|
21041
|
+
import fs16 from "node:fs/promises";
|
|
20999
21042
|
var logger19, exportCommand;
|
|
21000
21043
|
var init_export = __esm({
|
|
21001
21044
|
"src/commands/export.ts"() {
|
|
@@ -21008,7 +21051,7 @@ var init_export = __esm({
|
|
|
21008
21051
|
init_resolve();
|
|
21009
21052
|
init_errors();
|
|
21010
21053
|
logger19 = createLogger("cli:export");
|
|
21011
|
-
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",
|
|
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", path19.join(os9.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
21012
21055
|
try {
|
|
21013
21056
|
const session = await requireSession();
|
|
21014
21057
|
const activeCourse = await requireActiveCourse();
|
|
@@ -21026,21 +21069,21 @@ var init_export = __esm({
|
|
|
21026
21069
|
opts.path
|
|
21027
21070
|
);
|
|
21028
21071
|
if (ws.found && ws.source === "cwd" && ws.workspacePath) {
|
|
21029
|
-
const configPath =
|
|
21072
|
+
const configPath = path19.join(ws.workspacePath, ".ana-config.json");
|
|
21030
21073
|
let hasConfig = false;
|
|
21031
21074
|
try {
|
|
21032
|
-
await
|
|
21075
|
+
await fs16.access(configPath);
|
|
21033
21076
|
hasConfig = true;
|
|
21034
21077
|
} catch {
|
|
21035
21078
|
}
|
|
21036
21079
|
if (!hasConfig) {
|
|
21037
21080
|
const slug = courseSlug(activeCourse.courseTitle);
|
|
21038
21081
|
logger19.info("Auto-initializing workspace", { workspacePath: ws.workspacePath });
|
|
21039
|
-
await
|
|
21082
|
+
await fs16.mkdir(ws.workspacePath, { recursive: true });
|
|
21040
21083
|
for (const dir of ["exercises", "generated", "notes", "diagrams"]) {
|
|
21041
|
-
await
|
|
21084
|
+
await fs16.mkdir(path19.join(ws.workspacePath, dir), { recursive: true });
|
|
21042
21085
|
}
|
|
21043
|
-
await
|
|
21086
|
+
await fs16.writeFile(
|
|
21044
21087
|
configPath,
|
|
21045
21088
|
JSON.stringify(
|
|
21046
21089
|
{
|
|
@@ -21058,7 +21101,7 @@ var init_export = __esm({
|
|
|
21058
21101
|
"utf-8"
|
|
21059
21102
|
);
|
|
21060
21103
|
await setCourseWorkspacePath(activeCourse.courseId, ws.workspacePath);
|
|
21061
|
-
const isNamespaced = ws.workspacePath ===
|
|
21104
|
+
const isNamespaced = ws.workspacePath === path19.join(process.cwd(), ".tostudy");
|
|
21062
21105
|
process.stderr.write(
|
|
21063
21106
|
isNamespaced ? `\u2728 Workspace inicializado em .tostudy/ (isolado do projeto).
|
|
21064
21107
|
` : `\u2728 Workspace inicializado nesta pasta.
|
|
@@ -21112,7 +21155,7 @@ ${result.files.map((f) => ` \u{1F4C4} ${f}`).join("\n")}
|
|
|
21112
21155
|
// src/commands/open.ts
|
|
21113
21156
|
import { Command as Command19 } from "commander";
|
|
21114
21157
|
import { execFile as execFile3 } from "node:child_process";
|
|
21115
|
-
import
|
|
21158
|
+
import path20 from "node:path";
|
|
21116
21159
|
import os10 from "node:os";
|
|
21117
21160
|
var logger20, openCommand;
|
|
21118
21161
|
var init_open = __esm({
|
|
@@ -21124,7 +21167,7 @@ var init_open = __esm({
|
|
|
21124
21167
|
init_resolve();
|
|
21125
21168
|
init_errors();
|
|
21126
21169
|
logger20 = createLogger("cli:open");
|
|
21127
|
-
openCommand = new Command19("open").description("Abrir workspace do curso na IDE").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21170
|
+
openCommand = new Command19("open").description("Abrir workspace do curso na IDE").option("--path <dir>", "Diret\xF3rio base do workspace", path20.join(os10.homedir(), "study")).action(async (opts) => {
|
|
21128
21171
|
try {
|
|
21129
21172
|
const activeCourse = await requireActiveCourse();
|
|
21130
21173
|
const onboardingState = await getCourseOnboardingState(activeCourse.courseId);
|
|
@@ -21178,24 +21221,24 @@ var init_types = __esm({
|
|
|
21178
21221
|
});
|
|
21179
21222
|
|
|
21180
21223
|
// ../../packages/tostudy-core/src/vault/write-vault.ts
|
|
21181
|
-
import
|
|
21182
|
-
import
|
|
21224
|
+
import fs17 from "node:fs/promises";
|
|
21225
|
+
import path21 from "node:path";
|
|
21183
21226
|
async function writeVaultFiles(files, outputPath, courseId, courseSlug2) {
|
|
21184
21227
|
for (const file2 of files) {
|
|
21185
|
-
const fullPath =
|
|
21186
|
-
await
|
|
21187
|
-
await
|
|
21228
|
+
const fullPath = path21.join(outputPath, file2.relativePath);
|
|
21229
|
+
await fs17.mkdir(path21.dirname(fullPath), { recursive: true });
|
|
21230
|
+
await fs17.writeFile(fullPath, file2.content, "utf-8");
|
|
21188
21231
|
}
|
|
21189
|
-
const vaultPath =
|
|
21232
|
+
const vaultPath = path21.join(outputPath, courseSlug2);
|
|
21190
21233
|
const marker = {
|
|
21191
21234
|
courseId,
|
|
21192
21235
|
courseSlug: courseSlug2,
|
|
21193
21236
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21194
21237
|
version: VAULT_MARKER_VERSION
|
|
21195
21238
|
};
|
|
21196
|
-
await
|
|
21197
|
-
await
|
|
21198
|
-
|
|
21239
|
+
await fs17.mkdir(vaultPath, { recursive: true });
|
|
21240
|
+
await fs17.writeFile(
|
|
21241
|
+
path21.join(vaultPath, VAULT_MARKER_FILENAME),
|
|
21199
21242
|
JSON.stringify(marker, null, 2),
|
|
21200
21243
|
"utf-8"
|
|
21201
21244
|
);
|
|
@@ -21220,9 +21263,9 @@ var init_vault = __esm({
|
|
|
21220
21263
|
|
|
21221
21264
|
// src/commands/vault.ts
|
|
21222
21265
|
import { Command as Command20 } from "commander";
|
|
21223
|
-
import
|
|
21266
|
+
import path22 from "node:path";
|
|
21224
21267
|
import os11 from "node:os";
|
|
21225
|
-
import
|
|
21268
|
+
import fs18 from "node:fs/promises";
|
|
21226
21269
|
var logger21, vaultCommand;
|
|
21227
21270
|
var init_vault2 = __esm({
|
|
21228
21271
|
"src/commands/vault.ts"() {
|
|
@@ -21238,7 +21281,7 @@ var init_vault2 = __esm({
|
|
|
21238
21281
|
init_errors();
|
|
21239
21282
|
logger21 = createLogger("cli:vault");
|
|
21240
21283
|
vaultCommand = new Command20("vault").description("Gerenciar vault Obsidian do curso");
|
|
21241
|
-
vaultCommand.command("init").description("Gerar vault Obsidian para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21284
|
+
vaultCommand.command("init").description("Gerar vault Obsidian para o curso ativo").option("--path <dir>", "Diret\xF3rio base do workspace", path22.join(os11.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
21242
21285
|
try {
|
|
21243
21286
|
const session = await requireSession();
|
|
21244
21287
|
const activeCourse = await requireActiveCourse();
|
|
@@ -21319,7 +21362,7 @@ Para visualizar:
|
|
|
21319
21362
|
process.exit(1);
|
|
21320
21363
|
}
|
|
21321
21364
|
});
|
|
21322
|
-
vaultCommand.command("sync").description("Sincronizar progresso do curso com o vault local").option("--path <dir>", "Diret\xF3rio base do workspace",
|
|
21365
|
+
vaultCommand.command("sync").description("Sincronizar progresso do curso com o vault local").option("--path <dir>", "Diret\xF3rio base do workspace", path22.join(os11.homedir(), "study")).option("--json", "Output structured JSON").action(async (opts) => {
|
|
21323
21366
|
try {
|
|
21324
21367
|
const session = await requireSession();
|
|
21325
21368
|
const activeCourse = await requireActiveCourse();
|
|
@@ -21345,8 +21388,8 @@ Para visualizar:
|
|
|
21345
21388
|
const data = createHttpProvider(session.apiUrl, session.token);
|
|
21346
21389
|
const deps = { data, logger: logger21 };
|
|
21347
21390
|
const progress = await getProgress({ enrollmentId: activeCourse.enrollmentId }, deps);
|
|
21348
|
-
const markerPath =
|
|
21349
|
-
const markerRaw = await
|
|
21391
|
+
const markerPath = path22.join(vaultPath, ".ana-vault.json");
|
|
21392
|
+
const markerRaw = await fs18.readFile(markerPath, "utf-8");
|
|
21350
21393
|
const marker = JSON.parse(markerRaw);
|
|
21351
21394
|
marker.lastSyncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21352
21395
|
marker.progress = {
|
|
@@ -21354,10 +21397,10 @@ Para visualizar:
|
|
|
21354
21397
|
currentModule: progress.currentModule.title,
|
|
21355
21398
|
currentLesson: progress.currentLesson.title
|
|
21356
21399
|
};
|
|
21357
|
-
await
|
|
21358
|
-
const courseIndexPath =
|
|
21400
|
+
await fs18.writeFile(markerPath, JSON.stringify(marker, null, 2), "utf-8");
|
|
21401
|
+
const courseIndexPath = path22.join(vaultPath, slug, "index.md");
|
|
21359
21402
|
try {
|
|
21360
|
-
let indexContent = await
|
|
21403
|
+
let indexContent = await fs18.readFile(courseIndexPath, "utf-8");
|
|
21361
21404
|
indexContent = indexContent.replace(/\n---\n\n> 📊 Progresso:.*\n/g, "");
|
|
21362
21405
|
const titleEnd = indexContent.indexOf("\n");
|
|
21363
21406
|
if (titleEnd !== -1) {
|
|
@@ -21368,7 +21411,7 @@ Para visualizar:
|
|
|
21368
21411
|
`;
|
|
21369
21412
|
indexContent = indexContent.slice(0, titleEnd) + banner + indexContent.slice(titleEnd);
|
|
21370
21413
|
}
|
|
21371
|
-
await
|
|
21414
|
+
await fs18.writeFile(courseIndexPath, indexContent, "utf-8");
|
|
21372
21415
|
} catch {
|
|
21373
21416
|
}
|
|
21374
21417
|
const syncedAt = marker.lastSyncedAt;
|
|
@@ -21668,7 +21711,7 @@ function openUrl(url2) {
|
|
|
21668
21711
|
}
|
|
21669
21712
|
execFile4(cmd, args, (err) => {
|
|
21670
21713
|
if (err) {
|
|
21671
|
-
output(`
|
|
21714
|
+
output(`N\xE3o consegui abrir o navegador. Acesse manualmente: ${url2}`, { json: false });
|
|
21672
21715
|
}
|
|
21673
21716
|
});
|
|
21674
21717
|
}
|
|
@@ -21688,16 +21731,16 @@ var init_brief_open = __esm({
|
|
|
21688
21731
|
});
|
|
21689
21732
|
|
|
21690
21733
|
// src/sessions/storage.ts
|
|
21691
|
-
import
|
|
21692
|
-
import
|
|
21734
|
+
import fs19 from "node:fs";
|
|
21735
|
+
import path23 from "node:path";
|
|
21693
21736
|
function sessionsDir(workspacePath) {
|
|
21694
|
-
return
|
|
21737
|
+
return path23.join(workspacePath, ".tostudy", "sessions");
|
|
21695
21738
|
}
|
|
21696
21739
|
async function saveModuleSummary(workspacePath, input2) {
|
|
21697
21740
|
const dir = sessionsDir(workspacePath);
|
|
21698
|
-
|
|
21741
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
21699
21742
|
const filename = `module-${input2.moduleId}-summary.md`;
|
|
21700
|
-
const filePath =
|
|
21743
|
+
const filePath = path23.join(dir, filename);
|
|
21701
21744
|
const header = [
|
|
21702
21745
|
"---",
|
|
21703
21746
|
`moduleId: ${input2.moduleId}`,
|
|
@@ -21706,17 +21749,17 @@ async function saveModuleSummary(workspacePath, input2) {
|
|
|
21706
21749
|
"---",
|
|
21707
21750
|
""
|
|
21708
21751
|
].join("\n");
|
|
21709
|
-
|
|
21752
|
+
fs19.writeFileSync(filePath, header + input2.summary, { mode: 384 });
|
|
21710
21753
|
logger25.debug("Module summary saved", { moduleId: input2.moduleId, path: filePath });
|
|
21711
21754
|
return filePath;
|
|
21712
21755
|
}
|
|
21713
21756
|
async function loadSessionContext(workspacePath) {
|
|
21714
21757
|
const dir = sessionsDir(workspacePath);
|
|
21715
|
-
if (!
|
|
21716
|
-
const files =
|
|
21758
|
+
if (!fs19.existsSync(dir)) return { moduleSummaries: [] };
|
|
21759
|
+
const files = fs19.readdirSync(dir).filter((f) => f.startsWith("module-") && f.endsWith("-summary.md")).sort();
|
|
21717
21760
|
const summaries = [];
|
|
21718
21761
|
for (const file2 of files) {
|
|
21719
|
-
const content =
|
|
21762
|
+
const content = fs19.readFileSync(path23.join(dir, file2), "utf-8");
|
|
21720
21763
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
21721
21764
|
if (!frontmatterMatch) continue;
|
|
21722
21765
|
const meta3 = frontmatterMatch[1];
|
|
@@ -21738,7 +21781,7 @@ var init_storage = __esm({
|
|
|
21738
21781
|
});
|
|
21739
21782
|
|
|
21740
21783
|
// src/commands/compact.ts
|
|
21741
|
-
import
|
|
21784
|
+
import fs20 from "node:fs";
|
|
21742
21785
|
import { Command as Command26 } from "commander";
|
|
21743
21786
|
var logger26, compactCommand;
|
|
21744
21787
|
var init_compact = __esm({
|
|
@@ -21758,13 +21801,13 @@ var init_compact = __esm({
|
|
|
21758
21801
|
if (opts.json) jsonError("no_workspace");
|
|
21759
21802
|
error("Nenhum workspace encontrado.");
|
|
21760
21803
|
}
|
|
21761
|
-
const summary =
|
|
21804
|
+
const summary = fs20.readFileSync("/dev/stdin", "utf-8").trim();
|
|
21762
21805
|
if (!summary) {
|
|
21763
21806
|
if (opts.json) jsonError("empty_summary", { message: "Summary vazio" });
|
|
21764
|
-
error("Summary vazio. Envie o
|
|
21807
|
+
error("Summary vazio. Envie o conte\xFAdo via stdin.");
|
|
21765
21808
|
}
|
|
21766
21809
|
const moduleId = opts.moduleId ?? activeCourse.currentModuleId ?? "unknown";
|
|
21767
|
-
const moduleTitle = opts.moduleTitle ?? `
|
|
21810
|
+
const moduleTitle = opts.moduleTitle ?? `M\xF3dulo ${moduleId}`;
|
|
21768
21811
|
const filePath = await saveModuleSummary(ws.workspacePath, {
|
|
21769
21812
|
moduleId,
|
|
21770
21813
|
moduleTitle,
|
|
@@ -21797,13 +21840,14 @@ var init_context = __esm({
|
|
|
21797
21840
|
init_workspace_state();
|
|
21798
21841
|
init_storage();
|
|
21799
21842
|
init_formatter();
|
|
21843
|
+
init_errors();
|
|
21800
21844
|
logger27 = createLogger("cli:context");
|
|
21801
21845
|
contextCommand = new Command27("context").description("Load session context (workspace state + module summaries) for LLM consumption").option("--json", "Output structured JSON").action(async (opts) => {
|
|
21802
21846
|
try {
|
|
21803
21847
|
const ws = await findWorkspaceState();
|
|
21804
21848
|
if (!ws) {
|
|
21805
21849
|
if (opts.json) jsonError("no_workspace");
|
|
21806
|
-
error(
|
|
21850
|
+
error(getErrors().noActiveCourse.trimEnd());
|
|
21807
21851
|
}
|
|
21808
21852
|
const sessionCtx = await loadSessionContext(ws.workspacePath);
|
|
21809
21853
|
const result = {
|
|
@@ -21834,7 +21878,7 @@ var init_context = __esm({
|
|
|
21834
21878
|
} else {
|
|
21835
21879
|
output(`Workspace: ${ws.workspacePath}`, { json: false });
|
|
21836
21880
|
output(`Curso: ${ws.state.courseTitle}`, { json: false });
|
|
21837
|
-
output(`
|
|
21881
|
+
output(`M\xF3dulos resumidos: ${sessionCtx.moduleSummaries.length}`, { json: false });
|
|
21838
21882
|
}
|
|
21839
21883
|
} catch (err) {
|
|
21840
21884
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -21858,13 +21902,14 @@ var init_memory = __esm({
|
|
|
21858
21902
|
init_workspace_state();
|
|
21859
21903
|
init_guards();
|
|
21860
21904
|
init_formatter();
|
|
21905
|
+
init_errors();
|
|
21861
21906
|
logger28 = createLogger("cli:memory");
|
|
21862
21907
|
memoryCommand = new Command28("memory").description("Load accumulated student memory (learning profile + recent lessons) for the tutor").option("--json", "Output structured JSON").action(async (opts) => {
|
|
21863
21908
|
try {
|
|
21864
21909
|
const ws = await findWorkspaceState();
|
|
21865
21910
|
if (!ws) {
|
|
21866
21911
|
if (opts.json) return jsonError("no_workspace");
|
|
21867
|
-
return error(
|
|
21912
|
+
return error(getErrors().noActiveCourse.trimEnd());
|
|
21868
21913
|
}
|
|
21869
21914
|
const { courseId, enrollmentId } = ws.state;
|
|
21870
21915
|
if (!courseId || !enrollmentId) {
|
|
@@ -21901,6 +21946,7 @@ var init_insight = __esm({
|
|
|
21901
21946
|
init_workspace_state();
|
|
21902
21947
|
init_guards();
|
|
21903
21948
|
init_formatter();
|
|
21949
|
+
init_errors();
|
|
21904
21950
|
logger29 = createLogger("cli:insight");
|
|
21905
21951
|
VALID_TYPES = ["difficulty", "breakthrough", "question"];
|
|
21906
21952
|
insightCommand = new Command29("insight").description(
|
|
@@ -21919,7 +21965,7 @@ var init_insight = __esm({
|
|
|
21919
21965
|
const ws = await findWorkspaceState();
|
|
21920
21966
|
if (!ws) {
|
|
21921
21967
|
if (opts.json) return jsonError("no_workspace");
|
|
21922
|
-
return error(
|
|
21968
|
+
return error(getErrors().noActiveCourse.trimEnd());
|
|
21923
21969
|
}
|
|
21924
21970
|
const { courseId, enrollmentId } = ws.state;
|
|
21925
21971
|
if (!courseId || !enrollmentId) {
|
|
@@ -23009,11 +23055,11 @@ __export(auto_updater_exports, {
|
|
|
23009
23055
|
detectManager: () => detectManager,
|
|
23010
23056
|
maybeAutoUpdate: () => maybeAutoUpdate
|
|
23011
23057
|
});
|
|
23012
|
-
import
|
|
23013
|
-
import
|
|
23058
|
+
import fs21 from "node:fs";
|
|
23059
|
+
import path24 from "node:path";
|
|
23014
23060
|
import { spawn as spawn2 } from "node:child_process";
|
|
23015
23061
|
function detectManager(entryRealPath) {
|
|
23016
|
-
const p = entryRealPath.split(
|
|
23062
|
+
const p = entryRealPath.split(path24.sep).join("/");
|
|
23017
23063
|
if (p.includes("/pnpm/")) return { cmd: "pnpm", args: ["add", "-g", `${PACKAGE_NAME2}@latest`] };
|
|
23018
23064
|
if (p.includes("/.bun/")) return { cmd: "bun", args: ["add", "-g", `${PACKAGE_NAME2}@latest`] };
|
|
23019
23065
|
if (p.includes(`/node_modules/${PACKAGE_NAME2}/`))
|
|
@@ -23021,10 +23067,10 @@ function detectManager(entryRealPath) {
|
|
|
23021
23067
|
return null;
|
|
23022
23068
|
}
|
|
23023
23069
|
function installDir(entryRealPath) {
|
|
23024
|
-
const normalized = entryRealPath.split(
|
|
23070
|
+
const normalized = entryRealPath.split(path24.sep).join("/");
|
|
23025
23071
|
const marker = `/node_modules/${PACKAGE_NAME2}/`;
|
|
23026
23072
|
const idx = normalized.indexOf(marker);
|
|
23027
|
-
if (idx === -1) return
|
|
23073
|
+
if (idx === -1) return path24.dirname(entryRealPath);
|
|
23028
23074
|
return entryRealPath.slice(0, idx + marker.length - 1);
|
|
23029
23075
|
}
|
|
23030
23076
|
function maybeAutoUpdate(currentVersion, opts = {}) {
|
|
@@ -23040,10 +23086,10 @@ function maybeAutoUpdate(currentVersion, opts = {}) {
|
|
|
23040
23086
|
if (cache.attemptedVersion === cache.latest) return;
|
|
23041
23087
|
const entryPath = opts.entryPath ?? argv[1];
|
|
23042
23088
|
if (!entryPath) return;
|
|
23043
|
-
const real =
|
|
23089
|
+
const real = fs21.realpathSync(entryPath);
|
|
23044
23090
|
const mgr = detectManager(real);
|
|
23045
23091
|
if (!mgr) return;
|
|
23046
|
-
|
|
23092
|
+
fs21.accessSync(installDir(real), fs21.constants.W_OK);
|
|
23047
23093
|
writeCache({ ...cache, attemptedVersion: cache.latest }, configDir);
|
|
23048
23094
|
process.stderr.write(
|
|
23049
23095
|
`
|