@tostudy-ai/cli 0.16.12 → 0.17.1
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 +142 -34
- package/dist/cli.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -281,7 +281,7 @@ var require_picocolors = __commonJS({
|
|
|
281
281
|
}
|
|
282
282
|
});
|
|
283
283
|
|
|
284
|
-
// ../../node_modules/@parisgroup-ai/logger/dist/logger.base-
|
|
284
|
+
// ../../node_modules/@parisgroup-ai/logger/dist/logger.base-Bznav79x.mjs
|
|
285
285
|
function formatJson(entry) {
|
|
286
286
|
const { timestamp, level, message, service, environment, context, data, error: error49 } = entry;
|
|
287
287
|
const output3 = {
|
|
@@ -385,8 +385,8 @@ function extractErrorInfo(error49, includeStack, visited = /* @__PURE__ */ new W
|
|
|
385
385
|
return info;
|
|
386
386
|
}
|
|
387
387
|
var import_picocolors, LOG_LEVELS, LEVEL_COLORS, LEVEL_WIDTH, BaseLogger;
|
|
388
|
-
var
|
|
389
|
-
"../../node_modules/@parisgroup-ai/logger/dist/logger.base-
|
|
388
|
+
var init_logger_base_Bznav79x = __esm({
|
|
389
|
+
"../../node_modules/@parisgroup-ai/logger/dist/logger.base-Bznav79x.mjs"() {
|
|
390
390
|
init_sanitize_DSkXy3jL();
|
|
391
391
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
392
392
|
LOG_LEVELS = {
|
|
@@ -708,7 +708,7 @@ function createLogger(module, options) {
|
|
|
708
708
|
var asyncLocalStorage, ConsoleTransport, FileTransport, HttpTransport, SINGLETON_KEY$1, SEVERITY, OtlpLogsTransport, SINGLETON_KEY, Logger, logger;
|
|
709
709
|
var init_dist = __esm({
|
|
710
710
|
"../../node_modules/@parisgroup-ai/logger/dist/index.mjs"() {
|
|
711
|
-
|
|
711
|
+
init_logger_base_Bznav79x();
|
|
712
712
|
init_sanitize_DSkXy3jL();
|
|
713
713
|
asyncLocalStorage = new AsyncLocalStorage();
|
|
714
714
|
ConsoleTransport = class {
|
|
@@ -1917,6 +1917,13 @@ var init_ide_detector = __esm({
|
|
|
1917
1917
|
});
|
|
1918
1918
|
|
|
1919
1919
|
// src/output/instruction-template-v3.ts
|
|
1920
|
+
var instruction_template_v3_exports = {};
|
|
1921
|
+
__export(instruction_template_v3_exports, {
|
|
1922
|
+
COURSE_TEMPLATE_VERSION: () => COURSE_TEMPLATE_VERSION,
|
|
1923
|
+
UNIVERSAL_TEMPLATE_VERSION: () => UNIVERSAL_TEMPLATE_VERSION,
|
|
1924
|
+
renderCourseInstruction: () => renderCourseInstruction,
|
|
1925
|
+
renderUniversalInstruction: () => renderUniversalInstruction
|
|
1926
|
+
});
|
|
1920
1927
|
function renderCourseInstruction(input2) {
|
|
1921
1928
|
const sections = [];
|
|
1922
1929
|
sections.push(renderTitle(input2));
|
|
@@ -1926,7 +1933,11 @@ function renderCourseInstruction(input2) {
|
|
|
1926
1933
|
sections.push(renderHowToAdapt(input2.enrollmentProfile));
|
|
1927
1934
|
sections.push(renderPrecedence());
|
|
1928
1935
|
sections.push(renderWhereStudentIs(input2.progress));
|
|
1936
|
+
sections.push(renderMemoryLoad());
|
|
1929
1937
|
sections.push(renderHowToConduct());
|
|
1938
|
+
sections.push(renderStudentAuthorship());
|
|
1939
|
+
sections.push(renderConceptBeforeApplication());
|
|
1940
|
+
sections.push(renderTrainingCaseFraming());
|
|
1930
1941
|
sections.push(renderSilentTools());
|
|
1931
1942
|
sections.push(renderHandlingSituations());
|
|
1932
1943
|
sections.push(renderTechnicalReference());
|
|
@@ -1967,6 +1978,9 @@ Rode \`tostudy context --json\` em sil\xEAncio para descobrir o estado do aluno.
|
|
|
1967
1978
|
3. Se houver summaries, mencione brevemente: "Da \xFAltima vez paramos em {ultimoModulo}. Pronto pra continuar?"
|
|
1968
1979
|
4. Siga "Como Conduzir a Aula" abaixo.`);
|
|
1969
1980
|
sections.push(renderHowToConduct());
|
|
1981
|
+
sections.push(renderStudentAuthorship());
|
|
1982
|
+
sections.push(renderConceptBeforeApplication());
|
|
1983
|
+
sections.push(renderTrainingCaseFraming());
|
|
1970
1984
|
sections.push(renderSilentTools());
|
|
1971
1985
|
sections.push(`## Compacta\xE7\xE3o de Contexto (Autom\xE1tico)
|
|
1972
1986
|
|
|
@@ -1983,7 +1997,7 @@ Quando \`tostudy next --json\` retornar \`MODULE_COMPLETE\`:
|
|
|
1983
1997
|
Isso garante continuidade entre sess\xF5es e evita estouro de contexto em sess\xF5es longas.`);
|
|
1984
1998
|
sections.push(renderHandlingSituations());
|
|
1985
1999
|
sections.push(renderTechnicalReference());
|
|
1986
|
-
sections.push(`<!-- tostudy-template-version:
|
|
2000
|
+
sections.push(`<!-- tostudy-template-version: ${UNIVERSAL_TEMPLATE_VERSION} -->`);
|
|
1987
2001
|
return sections.join("\n\n") + "\n";
|
|
1988
2002
|
}
|
|
1989
2003
|
function renderTitle(input2) {
|
|
@@ -2042,7 +2056,7 @@ function renderWhoIsStudent(brief, profile) {
|
|
|
2042
2056
|
if (brief && brief.text.trim().length > 0) {
|
|
2043
2057
|
parts.push(brief.text);
|
|
2044
2058
|
parts.push(
|
|
2045
|
-
|
|
2059
|
+
'_(Este \xE9 o brief que o aluno escreveu sobre si mesmo. Use como contexto principal \u2014 nomes, empresa, projetos reais, motiva\xE7\xF5es. Tudo que voc\xEA disser deve parecer que voc\xEA leu e entendeu quem ele \xE9. O brief descreve quem ele \xE9 profissionalmente \u2014 N\xC3O o n\xEDvel dele neste curso: "avan\xE7ado" em outra \xE1rea n\xE3o vale como avan\xE7ado aqui.)_'
|
|
2046
2060
|
);
|
|
2047
2061
|
} else {
|
|
2048
2062
|
parts.push(
|
|
@@ -2075,7 +2089,7 @@ function renderHowToAdapt(profile) {
|
|
|
2075
2089
|
if (!profile) {
|
|
2076
2090
|
return `### Como Adaptar
|
|
2077
2091
|
|
|
2078
|
-
Sem informa\xE7\xE3o de n\xEDvel espec\xEDfico deste curso \u2014
|
|
2092
|
+
Sem informa\xE7\xE3o de n\xEDvel espec\xEDfico deste curso \u2014 o brief base N\xC3O vale como n\xEDvel neste assunto. Comece explicativo mas breve; calibre pelo que o aluno demonstrar aqui. Na d\xFAvida, prefira "porqu\xEA antes do como".`;
|
|
2079
2093
|
}
|
|
2080
2094
|
if (profile.learnerLevel === "beginner") {
|
|
2081
2095
|
return `### Como Adaptar
|
|
@@ -2115,6 +2129,9 @@ Voc\xEA tem DUAS fontes que te orientam, e elas resolvem conflitos assim:
|
|
|
2115
2129
|
| ----------------------------- | ----------------------------- | ---------------------------------------------- |
|
|
2116
2130
|
| Sua **persona** (acima) | voz, tom, nome, express\xF5es | usar catchphrase do creator ao cumprimentar |
|
|
2117
2131
|
| **Contexto do aluno** (acima) | profundidade, ritmo, exemplos | "vou come\xE7ar pelo porqu\xEA" (iniciante) |
|
|
2132
|
+
| **Brief base (T1)** | quem ele \xE9 (nomes, projetos) | exemplos com o contexto real dele |
|
|
2133
|
+
|
|
2134
|
+
O brief base NUNCA define o n\xEDvel neste curso \u2014 o n\xEDvel vem do campo "Neste Curso" e do que o aluno demonstra nas respostas aqui.
|
|
2118
2135
|
|
|
2119
2136
|
**Se conflitam, ambos valem ao mesmo tempo.** Voc\xEA mant\xE9m sua voz E adapta a profundidade. Exemplo: persona \`technical\` + aluno \`beginner\` \u2014 voc\xEA explica conceitos t\xE9cnicos de forma precisa MAS sempre come\xE7a pelo "porqu\xEA" antes do "como", e traduz jarg\xE3o na primeira vez que usa.`;
|
|
2120
2137
|
}
|
|
@@ -2153,6 +2170,33 @@ Quando o aluno passou na li\xE7\xE3o:
|
|
|
2153
2170
|
- Pergunte se ele quer seguir ou pausar.
|
|
2154
2171
|
- Ao seguir \u2014 \`tostudy next\` (sil\xEAncio) \u2014 apresente a pr\xF3xima.`;
|
|
2155
2172
|
}
|
|
2173
|
+
function renderMemoryLoad() {
|
|
2174
|
+
return `## Mem\xF3ria do Aluno
|
|
2175
|
+
|
|
2176
|
+
No in\xEDcio de cada sess\xE3o, rode \`tostudy memory --json\` em sil\xEAncio. Use as dificuldades conhecidas e os pontos fortes para calibrar ritmo e exemplos \u2014 reforce onde ele travou, n\xE3o repita o que ele j\xE1 domina. NUNCA mostre esse bloco cru ao aluno.`;
|
|
2177
|
+
}
|
|
2178
|
+
function renderStudentAuthorship() {
|
|
2179
|
+
return `## Autoria do Aluno (OBRIGAT\xD3RIO)
|
|
2180
|
+
|
|
2181
|
+
Em li\xE7\xF5es de **exerc\xEDcio, quiz ou checkpoint**, a resposta \xE9 do ALUNO \u2014 nunca sua.
|
|
2182
|
+
|
|
2183
|
+
1. **Nunca redija a resposta sozinho.** Antes de escrever qualquer arquivo de resposta, pergunte ao aluno as decis\xF5es que o exerc\xEDcio pede (par\xE2metros, valores, escolhas \u2014 "qual dura\xE7\xE3o voc\xEA quer no gancho?", "qual curva voc\xEA escolhe para a aterrissagem?"). Rascunhe A PARTIR das respostas dele, com ele.
|
|
2184
|
+
2. **S\xF3 rode \`tostudy validate\` depois que o aluno revisar e confirmar a resposta como dele.** "Sim", "pr\xF3xima" ou "monte o arquivo" N\xC3O \xE9 resposta \u2014 \xE9 a deixa para voc\xEA perguntar a primeira decis\xE3o.
|
|
2185
|
+
3. **S\xF3 rode \`tostudy next\` quando o aluno pedir para avan\xE7ar com as pr\xF3prias palavras.** Nunca encadeie validate \u2192 next sem uma fala do aluno entre os dois.
|
|
2186
|
+
4. Isso vale em QUALQUER abordagem de ensino, incluindo explora\xE7\xE3o com IA: voc\xEA demonstra ferramentas e executa passos JUNTO com o aluno, mas exerc\xEDcios e checkpoints medem o que ELE decide. Sem as decis\xF5es dele, n\xE3o h\xE1 o que validar.`;
|
|
2187
|
+
}
|
|
2188
|
+
function renderConceptBeforeApplication() {
|
|
2189
|
+
return `## Conceito Antes da Aplica\xE7\xE3o (OBRIGAT\xD3RIO)
|
|
2190
|
+
|
|
2191
|
+
1. **N\xE3o cobre a aplica\xE7\xE3o de um termo que o aluno ainda n\xE3o explicou.** Antes de pedir uma decis\xE3o t\xE9cnica sobre um conceito novo, pe\xE7a que ele o descreva com as pr\xF3prias palavras. Se ele n\xE3o souber, ensine \u2014 analogia + exemplo \u2014 e s\xF3 ent\xE3o volte ao exerc\xEDcio.
|
|
2192
|
+
2. **"N\xE3o entendi" trava a aplica\xE7\xE3o.** Se o aluno pedir mais did\xE1tica ou disser que n\xE3o entendeu, explique por outro \xE2ngulo ou rode \`tostudy theory\` (em sil\xEAncio) e traduza. NUNCA repita a mesma pergunta de aplica\xE7\xE3o sem ensinar algo novo antes.
|
|
2193
|
+
3. **Dificuldade registrada = ritmo did\xE1tico.** Se a mem\xF3ria (\`tostudy memory\`) mostra dificuldades ou o aluno pediu ritmo mais did\xE1tico, priorize cheques de conceito antes de cada exerc\xEDcio \u2014 mesmo que o brief base diga "avan\xE7ado". O n\xEDvel dele NESTE curso \xE9 o que ele demonstra aqui.`;
|
|
2194
|
+
}
|
|
2195
|
+
function renderTrainingCaseFraming() {
|
|
2196
|
+
return `## Enquadramento de Caso de Treino (OBRIGAT\xD3RIO)
|
|
2197
|
+
|
|
2198
|
+
1. **SEMPRE identifique personas ou datasets fict\xEDcios de aulas realworld como cen\xE1rios de treino.** Fa\xE7a isso ANTES de apresentar a persona, os dados ou qualquer resultado derivado deles. **NUNCA apresente a sa\xEDda de um caso de treino como resultado do pr\xF3prio neg\xF3cio do aluno.** Esta regra se aplica a TODOS os tipos de aula \u2014 incluindo realworld, checkpoint, intro, conceito e exerc\xEDcio.`;
|
|
2199
|
+
}
|
|
2156
2200
|
function renderSilentTools() {
|
|
2157
2201
|
return `## Ferramentas Silenciosas
|
|
2158
2202
|
|
|
@@ -2164,6 +2208,8 @@ Estes comandos s\xE3o suas ferramentas. Rode em sil\xEAncio (sem anunciar), use
|
|
|
2164
2208
|
- \`tostudy next --json\` \u2014 avan\xE7a para a pr\xF3xima li\xE7\xE3o.
|
|
2165
2209
|
- \`tostudy hint --json\` \u2014 dica progressiva (3 n\xEDveis).
|
|
2166
2210
|
- \`tostudy validate <arquivo>\` \u2014 valida exerc\xEDcio (exit 0 = passou, 1 = falhou).
|
|
2211
|
+
- \`tostudy theory --json\` \u2014 micro-aula extra na li\xE7\xE3o atual (aceita \`--focus "<tema>"\`). Use quando o aluno disser "n\xE3o entendi" ou pedir mais did\xE1tica.
|
|
2212
|
+
- \`tostudy level --json\` \u2014 v\xEA/ajusta o n\xEDvel de scaffolding dos exerc\xEDcios (os n\xEDveis DISPON\xCDVEIS v\xEAm no \`--json\`; ofere\xE7a s\xF3 esses). Use quando o exerc\xEDcio est\xE1 acima ou abaixo do ponto do aluno.
|
|
2167
2213
|
|
|
2168
2214
|
- \`tostudy insight <tipo> "<descri\xE7\xE3o>" --json\` \u2014 registra na mem\xF3ria do curso um sinal cognitivo do aluno. Tipos: \`difficulty\` (travou ou confundiu um conceito), \`breakthrough\` (teve um clique, dominou algo), \`question\` (d\xFAvida recorrente).
|
|
2169
2215
|
|
|
@@ -2177,6 +2223,7 @@ function renderHandlingSituations() {
|
|
|
2177
2223
|
| Situa\xE7\xE3o | O que fazer |
|
|
2178
2224
|
| ------------------------------------- | ---------------------------------------------------------- |
|
|
2179
2225
|
| \`tostudy validate\` falhou | Mostrar feedback, sugerir \`tostudy hint\`, tentar de novo |
|
|
2226
|
+
| Aluno diz "n\xE3o entendi" / quer did\xE1tica | Explicar por outro \xE2ngulo, \`tostudy theory\` (em sil\xEAncio); n\xE3o repetir a pergunta de aplica\xE7\xE3o |
|
|
2180
2227
|
| "Nenhuma li\xE7\xE3o ativa" | Rodar \`tostudy start\` para carregar m\xF3dulo |
|
|
2181
2228
|
| Comando retorna erro | Verificar \`tostudy doctor\` para diagn\xF3stico |
|
|
2182
2229
|
| Aluno perdido / sem saber o que fazer | Rodar \`tostudy progress\` e resumir estado atual |
|
|
@@ -2195,12 +2242,14 @@ function renderTechnicalReference() {
|
|
|
2195
2242
|
}
|
|
2196
2243
|
function renderFooter(course) {
|
|
2197
2244
|
return `<!-- tostudy-course-id: ${course.courseId} -->
|
|
2198
|
-
<!-- tostudy-template-version:
|
|
2245
|
+
<!-- tostudy-template-version: ${COURSE_TEMPLATE_VERSION} -->`;
|
|
2199
2246
|
}
|
|
2200
|
-
var TONE_LABELS, LEVEL_LABELS;
|
|
2247
|
+
var COURSE_TEMPLATE_VERSION, UNIVERSAL_TEMPLATE_VERSION, TONE_LABELS, LEVEL_LABELS;
|
|
2201
2248
|
var init_instruction_template_v3 = __esm({
|
|
2202
2249
|
"src/output/instruction-template-v3.ts"() {
|
|
2203
2250
|
"use strict";
|
|
2251
|
+
COURSE_TEMPLATE_VERSION = 4;
|
|
2252
|
+
UNIVERSAL_TEMPLATE_VERSION = 5;
|
|
2204
2253
|
TONE_LABELS = {
|
|
2205
2254
|
formal: "formal",
|
|
2206
2255
|
casual: "casual",
|
|
@@ -2932,6 +2981,24 @@ async function writeWorkspaceMarker(workspacePath, input2, options = {}) {
|
|
|
2932
2981
|
}
|
|
2933
2982
|
const existing = await readWorkspaceMarker(workspacePath);
|
|
2934
2983
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2984
|
+
let carried = {};
|
|
2985
|
+
if (existing && existing.courseId === input2.courseId) {
|
|
2986
|
+
try {
|
|
2987
|
+
const raw = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
2988
|
+
for (const key of [
|
|
2989
|
+
"currentLessonId",
|
|
2990
|
+
"currentModuleId",
|
|
2991
|
+
"courseTags",
|
|
2992
|
+
"courseLevel",
|
|
2993
|
+
"lastInitCourseId",
|
|
2994
|
+
"templateVersion"
|
|
2995
|
+
]) {
|
|
2996
|
+
if (raw[key] !== void 0) carried[key] = raw[key];
|
|
2997
|
+
}
|
|
2998
|
+
} catch {
|
|
2999
|
+
carried = {};
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
2935
3002
|
const marker = {
|
|
2936
3003
|
version: CURRENT_VERSION,
|
|
2937
3004
|
courseId: input2.courseId,
|
|
@@ -2941,7 +3008,7 @@ async function writeWorkspaceMarker(workspacePath, input2, options = {}) {
|
|
|
2941
3008
|
createdAt: existing?.createdAt ?? now,
|
|
2942
3009
|
updatedAt: now
|
|
2943
3010
|
};
|
|
2944
|
-
writeFileSync3(filePath, JSON.stringify(marker, null, 2), { mode: 384 });
|
|
3011
|
+
writeFileSync3(filePath, JSON.stringify({ ...carried, ...marker }, null, 2), { mode: 384 });
|
|
2945
3012
|
return filePath;
|
|
2946
3013
|
}
|
|
2947
3014
|
var CURRENT_VERSION, SUPPORTED_VERSIONS;
|
|
@@ -2986,6 +3053,7 @@ async function readWorkspaceState(workspacePath) {
|
|
|
2986
3053
|
state.courseLevel = raw.courseLevel;
|
|
2987
3054
|
}
|
|
2988
3055
|
if (typeof raw.lastInitCourseId === "string") state.lastInitCourseId = raw.lastInitCourseId;
|
|
3056
|
+
if (typeof raw.templateVersion === "number") state.templateVersion = raw.templateVersion;
|
|
2989
3057
|
return state;
|
|
2990
3058
|
} catch {
|
|
2991
3059
|
return null;
|
|
@@ -3039,16 +3107,31 @@ async function setLastInitCourseId(courseId, _configDir) {
|
|
|
3039
3107
|
}
|
|
3040
3108
|
async function checkCourseDrift() {
|
|
3041
3109
|
const { findWorkspaceState: findWorkspaceState2 } = await Promise.resolve().then(() => (init_workspace_state(), workspace_state_exports));
|
|
3110
|
+
const { COURSE_TEMPLATE_VERSION: COURSE_TEMPLATE_VERSION2 } = await Promise.resolve().then(() => (init_instruction_template_v3(), instruction_template_v3_exports));
|
|
3042
3111
|
const result = await findWorkspaceState2();
|
|
3043
3112
|
if (!result) return null;
|
|
3044
3113
|
const state = result.state;
|
|
3045
|
-
|
|
3046
|
-
if (state.lastInitCourseId
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3114
|
+
const warnings = [];
|
|
3115
|
+
if (state.lastInitCourseId && state.lastInitCourseId !== state.courseId) {
|
|
3116
|
+
warnings.push(
|
|
3117
|
+
[
|
|
3118
|
+
`\u26A0\uFE0F Curso ativo mudou para "${state.courseTitle}".`,
|
|
3119
|
+
` Rode \`tostudy init\` para atualizar o contexto do assistente.`,
|
|
3120
|
+
""
|
|
3121
|
+
].join("\n")
|
|
3122
|
+
);
|
|
3123
|
+
}
|
|
3124
|
+
if ((state.templateVersion ?? 0) < COURSE_TEMPLATE_VERSION2) {
|
|
3125
|
+
const from = state.templateVersion ? `v${state.templateVersion}` : "vers\xE3o antiga";
|
|
3126
|
+
warnings.push(
|
|
3127
|
+
[
|
|
3128
|
+
`\u26A0\uFE0F As instru\xE7\xF5es do tutor neste workspace est\xE3o desatualizadas (${from} < v${COURSE_TEMPLATE_VERSION2}).`,
|
|
3129
|
+
` Rode \`tostudy sync\` para atualizar as regras do tutor.`,
|
|
3130
|
+
""
|
|
3131
|
+
].join("\n")
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
3134
|
+
return warnings.length > 0 ? warnings.join("\n") : null;
|
|
3052
3135
|
}
|
|
3053
3136
|
var init_course_drift = __esm({
|
|
3054
3137
|
"src/onboarding/course-drift.ts"() {
|
|
@@ -3439,7 +3522,7 @@ var CLI_VERSION;
|
|
|
3439
3522
|
var init_version = __esm({
|
|
3440
3523
|
"src/version.ts"() {
|
|
3441
3524
|
"use strict";
|
|
3442
|
-
CLI_VERSION = true ? "0.
|
|
3525
|
+
CLI_VERSION = true ? "0.17.1" : "0.7.1";
|
|
3443
3526
|
}
|
|
3444
3527
|
});
|
|
3445
3528
|
|
|
@@ -4155,13 +4238,18 @@ async function resolveAndGenerate(input2, options = {}, context) {
|
|
|
4155
4238
|
} catch (err) {
|
|
4156
4239
|
logger6.warn("Failed to write workspace marker", { err });
|
|
4157
4240
|
}
|
|
4241
|
+
let workspaceStateRecorded = false;
|
|
4158
4242
|
if (markerPath) {
|
|
4159
4243
|
try {
|
|
4160
4244
|
await updateWorkspaceState(context.cwd, {
|
|
4161
4245
|
courseTags: courseMeta.courseTags,
|
|
4162
4246
|
courseLevel: courseMeta.courseLevel,
|
|
4163
|
-
lastInitCourseId: input2.courseId
|
|
4247
|
+
lastInitCourseId: input2.courseId,
|
|
4248
|
+
// GH #1534: record which template generated the instruction files so
|
|
4249
|
+
// checkCourseDrift() can flag stale workspaces after a template bump.
|
|
4250
|
+
templateVersion: COURSE_TEMPLATE_VERSION
|
|
4164
4251
|
});
|
|
4252
|
+
workspaceStateRecorded = true;
|
|
4165
4253
|
} catch (err) {
|
|
4166
4254
|
logger6.warn("Failed to update workspace state v2 fields", {
|
|
4167
4255
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -4175,7 +4263,8 @@ async function resolveAndGenerate(input2, options = {}, context) {
|
|
|
4175
4263
|
usedT1: studentBrief !== null,
|
|
4176
4264
|
usedT2: enrollmentProfile !== null,
|
|
4177
4265
|
bootstrapped,
|
|
4178
|
-
renderedInstruction: content
|
|
4266
|
+
renderedInstruction: content,
|
|
4267
|
+
workspaceStateRecorded
|
|
4179
4268
|
};
|
|
4180
4269
|
}
|
|
4181
4270
|
var logger6, defaultDeps2;
|
|
@@ -19663,6 +19752,13 @@ var init_credit_payment_enums = __esm({
|
|
|
19663
19752
|
}
|
|
19664
19753
|
});
|
|
19665
19754
|
|
|
19755
|
+
// ../../packages/types/src/meeting-integrations.ts
|
|
19756
|
+
var init_meeting_integrations = __esm({
|
|
19757
|
+
"../../packages/types/src/meeting-integrations.ts"() {
|
|
19758
|
+
"use strict";
|
|
19759
|
+
}
|
|
19760
|
+
});
|
|
19761
|
+
|
|
19666
19762
|
// ../../packages/types/src/referral.ts
|
|
19667
19763
|
var init_referral = __esm({
|
|
19668
19764
|
"../../packages/types/src/referral.ts"() {
|
|
@@ -19686,6 +19782,7 @@ var init_src = __esm({
|
|
|
19686
19782
|
init_lesson_review();
|
|
19687
19783
|
init_errors4();
|
|
19688
19784
|
init_credit_payment_enums();
|
|
19785
|
+
init_meeting_integrations();
|
|
19689
19786
|
init_referral();
|
|
19690
19787
|
}
|
|
19691
19788
|
});
|
|
@@ -21561,6 +21658,7 @@ var init_sync = __esm({
|
|
|
21561
21658
|
init_guards();
|
|
21562
21659
|
init_formatter();
|
|
21563
21660
|
init_instruction_pipeline();
|
|
21661
|
+
init_workspace_state();
|
|
21564
21662
|
init_root_agents_consent();
|
|
21565
21663
|
init_pipeline_deps();
|
|
21566
21664
|
logger22 = createLogger("cli:sync");
|
|
@@ -21574,8 +21672,10 @@ var init_sync = __esm({
|
|
|
21574
21672
|
try {
|
|
21575
21673
|
await requireSession();
|
|
21576
21674
|
const activeCourse = await requireActiveCourse();
|
|
21675
|
+
const found = await findWorkspaceState();
|
|
21676
|
+
const workspaceCwd = found?.workspacePath ?? process.cwd();
|
|
21577
21677
|
const rootAgents = await resolveRootAgentsConsent({
|
|
21578
|
-
cwd:
|
|
21678
|
+
cwd: workspaceCwd,
|
|
21579
21679
|
flag: opts.rootAgents,
|
|
21580
21680
|
interactive: isInteractiveTerminal(opts.json)
|
|
21581
21681
|
});
|
|
@@ -21583,7 +21683,7 @@ var init_sync = __esm({
|
|
|
21583
21683
|
{ courseId: activeCourse.courseId, enrollmentId: activeCourse.enrollmentId },
|
|
21584
21684
|
{ forceRefresh: true, collectT1Interactive: false, collectT2Interactive: false },
|
|
21585
21685
|
{
|
|
21586
|
-
cwd:
|
|
21686
|
+
cwd: workspaceCwd,
|
|
21587
21687
|
deps: buildPipelineDeps({
|
|
21588
21688
|
allRuntimes: opts.allRuntimes,
|
|
21589
21689
|
rootAgentsConsent: rootAgents.consent
|
|
@@ -21603,21 +21703,25 @@ var init_sync = __esm({
|
|
|
21603
21703
|
markerPath: pipelineResult.markerPath,
|
|
21604
21704
|
usedT0: pipelineResult.usedT0,
|
|
21605
21705
|
usedT1: pipelineResult.usedT1,
|
|
21606
|
-
usedT2: pipelineResult.usedT2
|
|
21706
|
+
usedT2: pipelineResult.usedT2,
|
|
21707
|
+
workspaceStateRecorded: pipelineResult.workspaceStateRecorded
|
|
21607
21708
|
},
|
|
21608
21709
|
{ json: true }
|
|
21609
21710
|
);
|
|
21610
21711
|
} else {
|
|
21611
|
-
|
|
21612
|
-
|
|
21613
|
-
|
|
21614
|
-
|
|
21615
|
-
|
|
21616
|
-
|
|
21617
|
-
|
|
21618
|
-
|
|
21619
|
-
|
|
21620
|
-
|
|
21712
|
+
const lines = [
|
|
21713
|
+
`\u2713 Instru\xE7\xF5es sincronizadas para "${activeCourse.courseTitle}"`,
|
|
21714
|
+
` - T0 (persona): ${pipelineResult.usedT0 ? "presente" : "ausente"}`,
|
|
21715
|
+
` - T1 (brief base): ${pipelineResult.usedT1 ? "presente" : "ausente"}`,
|
|
21716
|
+
` - T2 (curso): ${pipelineResult.usedT2 ? "presente" : "ausente"}`,
|
|
21717
|
+
` - Arquivos: ${pipelineResult.wroteFiles.join(", ")}`
|
|
21718
|
+
];
|
|
21719
|
+
if (!pipelineResult.workspaceStateRecorded) {
|
|
21720
|
+
lines.push(
|
|
21721
|
+
`\u26A0 N\xE3o consegui gravar .tostudy/workspace.json \u2014 o aviso de template pode continuar aparecendo. Verifique as permiss\xF5es do diret\xF3rio do workspace.`
|
|
21722
|
+
);
|
|
21723
|
+
}
|
|
21724
|
+
output(lines.join("\n"), { json: false });
|
|
21621
21725
|
}
|
|
21622
21726
|
} catch (err) {
|
|
21623
21727
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -21872,6 +21976,7 @@ var init_context = __esm({
|
|
|
21872
21976
|
init_dist();
|
|
21873
21977
|
init_workspace_state();
|
|
21874
21978
|
init_storage();
|
|
21979
|
+
init_course_state();
|
|
21875
21980
|
init_formatter();
|
|
21876
21981
|
init_errors();
|
|
21877
21982
|
logger27 = createLogger("cli:context");
|
|
@@ -21882,6 +21987,8 @@ var init_context = __esm({
|
|
|
21882
21987
|
if (opts.json) jsonError("no_workspace");
|
|
21883
21988
|
error(getErrors().noActiveCourse.trimEnd());
|
|
21884
21989
|
}
|
|
21990
|
+
const driftWarning = await checkCourseDrift();
|
|
21991
|
+
if (driftWarning && !opts.json) process.stderr.write(driftWarning + "\n");
|
|
21885
21992
|
const sessionCtx = await loadSessionContext(ws.workspacePath);
|
|
21886
21993
|
const result = {
|
|
21887
21994
|
workspace: {
|
|
@@ -21900,7 +22007,8 @@ var init_context = __esm({
|
|
|
21900
22007
|
summary: s.summary,
|
|
21901
22008
|
savedAt: s.savedAt
|
|
21902
22009
|
})),
|
|
21903
|
-
totalModulesCompleted: sessionCtx.moduleSummaries.length
|
|
22010
|
+
totalModulesCompleted: sessionCtx.moduleSummaries.length,
|
|
22011
|
+
driftWarning: driftWarning ?? null
|
|
21904
22012
|
};
|
|
21905
22013
|
logger27.debug("Context loaded", {
|
|
21906
22014
|
courseId: ws.state.courseId,
|