paris-immersion 0.1.9 → 0.1.10
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/serve.js +40 -21
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/commands/serve.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { WebSocketServer } from 'ws';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { promises as fs, chmodSync, existsSync, statSync, readdirSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
4
5
|
import path from 'node:path';
|
|
5
6
|
import { readCredentials } from '../lib/credentials.js';
|
|
6
7
|
import { ensureWorkspace } from './install.js';
|
|
@@ -82,32 +83,50 @@ export function resolveKickoff(cwd) {
|
|
|
82
83
|
const override = process.env.PARIS_COACH_KICKOFF;
|
|
83
84
|
if (override)
|
|
84
85
|
return override;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
files.find((f) => f.toLowerCase().includes(slug));
|
|
98
|
-
if (match)
|
|
99
|
-
chosen = match;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
/* sem workspace.json legível — usa o primeiro */
|
|
86
|
+
// O Claude Code carrega slash-commands de DOIS lugares: o do projeto
|
|
87
|
+
// (workspace) e o global do usuário (~/.claude/commands). O `@tostudy-ai/cli`
|
|
88
|
+
// instala o comando do tutor em qualquer um deles (na prática, no global) —
|
|
89
|
+
// então varremos os DOIS. Sem isto, numa máquina onde o tostudy escreve só no
|
|
90
|
+
// global, o kickoff não acharia o comando e cairia em `/tostudy` (Unknown).
|
|
91
|
+
const dirs = [path.join(cwd, '.claude', 'commands'), path.join(homedir(), '.claude', 'commands')];
|
|
92
|
+
const names = new Set();
|
|
93
|
+
for (const d of dirs) {
|
|
94
|
+
try {
|
|
95
|
+
for (const f of readdirSync(d)) {
|
|
96
|
+
if (/^tostudy.*\.md$/i.test(f))
|
|
97
|
+
names.add(f.replace(/\.md$/i, ''));
|
|
104
98
|
}
|
|
105
99
|
}
|
|
106
|
-
|
|
100
|
+
catch {
|
|
101
|
+
/* diretório não existe — ok */
|
|
102
|
+
}
|
|
107
103
|
}
|
|
108
|
-
|
|
104
|
+
if (names.size === 0)
|
|
109
105
|
return '/tostudy';
|
|
106
|
+
const all = [...names];
|
|
107
|
+
// Curso ATIVO deste workspace = fonte da verdade pra escolher entre vários cursos.
|
|
108
|
+
let slug = '';
|
|
109
|
+
try {
|
|
110
|
+
const ws = JSON.parse(readFileSync(path.join(cwd, '.tostudy', 'workspace.json'), 'utf8'));
|
|
111
|
+
slug = (ws.slug ?? '').toLowerCase();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
/* sem workspace.json — segue sem slug */
|
|
115
|
+
}
|
|
116
|
+
if (slug) {
|
|
117
|
+
const exact = all.find((n) => n.toLowerCase() === `tostudy-${slug}`);
|
|
118
|
+
if (exact)
|
|
119
|
+
return '/' + exact;
|
|
120
|
+
const partial = all.find((n) => n.toLowerCase().includes(slug));
|
|
121
|
+
if (partial)
|
|
122
|
+
return '/' + partial;
|
|
110
123
|
}
|
|
124
|
+
// Sem match por slug: prefere um comando ESPECÍFICO de curso (`tostudy-<algo>`)
|
|
125
|
+
// ao genérico `tostudy`. Se só houver o genérico, usa `/tostudy`.
|
|
126
|
+
const courseSpecific = all.filter((n) => /^tostudy-.+/i.test(n)).sort();
|
|
127
|
+
if (courseSpecific.length)
|
|
128
|
+
return '/' + courseSpecific[0];
|
|
129
|
+
return '/tostudy';
|
|
111
130
|
}
|
|
112
131
|
/**
|
|
113
132
|
* Spawn the coached pty (`claude '/tostudy-<curso>'` inside the provisioned
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { daemonCommand } from './commands/daemon.js';
|
|
|
13
13
|
const program = new Command()
|
|
14
14
|
.name('paris')
|
|
15
15
|
.description('Paris Immersion — CLI do aluno (login, workspace, tarefas)')
|
|
16
|
-
.version('0.1.
|
|
16
|
+
.version('0.1.10');
|
|
17
17
|
program
|
|
18
18
|
.command('login')
|
|
19
19
|
.description('Autenticar com sua conta Paris (device-code OR --token direto)')
|
package/package.json
CHANGED