paris-immersion 0.1.26 → 0.1.28
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/commands/login.js +5 -2
- package/dist/index.js +1 -1
- package/dist/templates/claude-md.js +1 -0
- package/dist/templates/hook.js +39 -0
- package/package.json +1 -1
package/dist/commands/login.js
CHANGED
|
@@ -36,11 +36,14 @@ export async function loginCommand(opts) {
|
|
|
36
36
|
if (opts.token) {
|
|
37
37
|
process.stdout.write(c.dim(`Validando token via ${apiUrl}...\n`));
|
|
38
38
|
try {
|
|
39
|
-
|
|
39
|
+
// /auth/me devolve envelope { user: {...} } — sem o unwrap o installer
|
|
40
|
+
// dizia "Autenticado como undefined" (achado da simulação de 2026-08-13).
|
|
41
|
+
const meRes = await apiFetch('/auth/me', {
|
|
40
42
|
method: 'GET',
|
|
41
43
|
apiUrl,
|
|
42
44
|
token: opts.token,
|
|
43
45
|
});
|
|
46
|
+
const me = meRes.user ?? meRes;
|
|
44
47
|
await writeCredentials({
|
|
45
48
|
token: opts.token,
|
|
46
49
|
user_id: me.id,
|
|
@@ -48,7 +51,7 @@ export async function loginCommand(opts) {
|
|
|
48
51
|
api_url: apiUrl,
|
|
49
52
|
obtained_at: new Date().toISOString(),
|
|
50
53
|
});
|
|
51
|
-
console.log(c.green(`✓ Autenticado como ${me.email}.`));
|
|
54
|
+
console.log(c.green(`✓ Autenticado como ${me.name ?? me.email}.`));
|
|
52
55
|
console.log(c.dim(' Token salvo em ~/.paris/credentials.'));
|
|
53
56
|
await refreshDaemonAfterLogin();
|
|
54
57
|
return;
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { mentorCommand } from './commands/mentor.js';
|
|
|
15
15
|
const program = new Command()
|
|
16
16
|
.name('paris')
|
|
17
17
|
.description('Paris Immersion — CLI do aluno (login, workspace, tarefas)')
|
|
18
|
-
.version('0.1.
|
|
18
|
+
.version('0.1.28');
|
|
19
19
|
program
|
|
20
20
|
.command('login')
|
|
21
21
|
.description('Autenticar com sua conta Paris (device-code OR --token direto)')
|
|
@@ -21,6 +21,7 @@ export function renderClaudeMd(opts) {
|
|
|
21
21
|
3. **Transparência total.** Tudo aqui é gravado em audit_logs e o instrutor pode reabrir qualquer tarefa.
|
|
22
22
|
4. **Nunca invente progresso.** Só marque o que de fato foi feito nessa sessão.
|
|
23
23
|
5. **Inicie a sessão falando primeiro.** O hook SessionStart te entrega o cronograma + a tarefa atual antes do aluno digitar — abra o dia com um resumo claro (fase, tarefa, primeiro passo sugerido).
|
|
24
|
+
6. **O dossiê do projeto é sagrado.** \`produto/visao.md\` precisa SEMPRE refletir o que é o projeto, a dor, a ideia, como resolve e pra quem (o /visao do Prototipador escreve nesse formato). Toda decisão nova de escopo vai pro arquivo na hora. Ele sincroniza sozinho com a equipe no fim do turno e é pré-requisito pra concluir missões de entregável — sem dossiê, o mark_task_complete recusa.
|
|
24
25
|
|
|
25
26
|
## MCP tools que você tem
|
|
26
27
|
|
package/dist/templates/hook.js
CHANGED
|
@@ -211,6 +211,43 @@ async function refreshMarkerStatus(markerDir, marker, status) {
|
|
|
211
211
|
} catch { /* best-effort */ }
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
// Dossiê do projeto (produto/visao.md + roadmap.md do Prototipador) → Caso do
|
|
216
|
+
// aluno no servidor. DETERMINÍSTICO: roda em todo Stop/SessionStart e envia
|
|
217
|
+
// quando o arquivo mudou — o mentor sempre vê o que é o projeto, a dor e o
|
|
218
|
+
// plano, sem depender do modelo lembrar de anotar.
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
async function syncCaseDossier(apiUrl, token, markerDir) {
|
|
222
|
+
const statePath = path.join(markerDir, '.paris', 'case-sync.json')
|
|
223
|
+
let state = {}
|
|
224
|
+
try { state = JSON.parse(await fs.readFile(statePath, 'utf-8')) } catch {}
|
|
225
|
+
|
|
226
|
+
const files = {
|
|
227
|
+
visao: path.join(markerDir, 'produto', 'visao.md'),
|
|
228
|
+
roadmap: path.join(markerDir, 'produto', 'roadmap.md'),
|
|
229
|
+
}
|
|
230
|
+
const payload = {}
|
|
231
|
+
const newState = { ...state }
|
|
232
|
+
for (const [key, fp] of Object.entries(files)) {
|
|
233
|
+
try {
|
|
234
|
+
const st = await fs.stat(fp)
|
|
235
|
+
const mtime = st.mtimeMs
|
|
236
|
+
if (state[key] !== mtime) {
|
|
237
|
+
const content = await fs.readFile(fp, 'utf-8')
|
|
238
|
+
payload[key] = content.slice(0, 16384)
|
|
239
|
+
newState[key] = mtime
|
|
240
|
+
}
|
|
241
|
+
} catch { /* arquivo ainda não existe — normal antes do /visao */ }
|
|
242
|
+
}
|
|
243
|
+
if (Object.keys(payload).length === 0) return
|
|
244
|
+
|
|
245
|
+
const ok = await apiPost(apiUrl, '/immersion-app/v1/case/sync', token, payload)
|
|
246
|
+
if (ok) {
|
|
247
|
+
try { await fs.writeFile(statePath, JSON.stringify(newState)) } catch {}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
214
251
|
// Sincroniza o progresso REAL do curso da ToStudy pro nosso lado. O aluno faz o
|
|
215
252
|
// curso pela tostudy CLI no terminal embutido, e essa conclusão NÃO dispara o
|
|
216
253
|
// webhook do cursos — então é daqui que a gestão aprende o progresso. A ToStudy
|
|
@@ -266,6 +303,7 @@ async function main() {
|
|
|
266
303
|
if (PHASE === 'stop') {
|
|
267
304
|
await apiPost(apiUrl, '/immersion-app/v1/events', creds.token, { type: 'turn_ended' })
|
|
268
305
|
await flushActivityQueue(apiUrl, creds.token, marker.dir)
|
|
306
|
+
await syncCaseDossier(apiUrl, creds.token, marker.dir)
|
|
269
307
|
// Logo após cada interação é o melhor momento pra capturar uma lição que o
|
|
270
308
|
// aluno acabou de concluir no curso da ToStudy.
|
|
271
309
|
await syncTostudyProgress(apiUrl, creds.token, marker.dir)
|
|
@@ -341,6 +379,7 @@ async function main() {
|
|
|
341
379
|
await apiPost(apiUrl, '/immersion-app/v1/events', creds.token, { type: 'session_started' })
|
|
342
380
|
// Restos de fila de sessões anteriores (crash, rede) sobem agora.
|
|
343
381
|
await flushActivityQueue(apiUrl, creds.token, marker.dir)
|
|
382
|
+
await syncCaseDossier(apiUrl, creds.token, marker.dir)
|
|
344
383
|
}
|
|
345
384
|
|
|
346
385
|
// user-prompt-submit: dá ao mentor o "o que ele pediu" em tempo real.
|
package/package.json
CHANGED