ronin-skillforce 0.1.0 → 0.2.0-beta.0
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/CHANGELOG.md +48 -0
- package/LICENSE +202 -21
- package/NOTICE +19 -0
- package/README.md +38 -5
- package/bin/cli.js +15 -3
- package/bin/commands/archive.js +192 -0
- package/bin/commands/capstone-status.js +82 -0
- package/bin/commands/create.js +69 -12
- package/bin/commands/import.js +5 -5
- package/bin/commands/status.js +1 -1
- package/bin/commands/studio-autostart.js +414 -0
- package/bin/commands/studio-state.js +159 -0
- package/bin/commands/studio.js +351 -17
- package/bin/commands/trail.js +153 -3
- package/bin/commands/web.js +8 -10
- package/bin/course-reader.js +6 -15
- package/bin/platforms/_shared.js +154 -28
- package/bin/platforms/claude.js +23 -42
- package/bin/platforms/cursor.js +23 -20
- package/bin/platforms/gemini.js +18 -19
- package/bin/platforms/opencode.js +47 -28
- package/package.json +5 -4
- package/plugin.json +1 -1
- package/shared/SKILL.md +102 -72
- package/shared/agents/coach.md +19 -16
- package/shared/agents/navigator.md +27 -34
- package/shared/agents/professor.md +16 -34
- package/shared/agents/researcher.md +1 -1
- package/shared/agents/spotter.md +3 -4
- package/shared/commands/professor/archive.md +65 -72
- package/shared/commands/professor/capstone-review.md +5 -5
- package/shared/commands/professor/capstone.md +3 -3
- package/shared/commands/professor/done.md +59 -31
- package/shared/commands/professor/hint.md +14 -2
- package/shared/commands/professor/navigator.md +27 -1
- package/shared/commands/professor/new-topic.md +3 -3
- package/shared/commands/professor/next.md +9 -5
- package/shared/commands/professor/note.md +6 -6
- package/shared/commands/professor/progress.md +1 -1
- package/shared/commands/professor/publish.md +5 -5
- package/shared/commands/professor/quiz.md +2 -2
- package/shared/commands/professor/recall.md +1 -1
- package/shared/commands/professor/review.md +14 -0
- package/shared/commands/professor/skill-export.md +3 -4
- package/shared/commands/professor/spotter.md +21 -4
- package/shared/commands/professor/stuck.md +24 -0
- package/shared/commands/professor/switch.md +1 -1
- package/shared/commands/professor/syllabus.md +1 -1
- package/shared/commands/professor/template-export.md +2 -2
- package/shared/commands/professor/worktrees.md +3 -7
- package/shared/hooks/pre-compact.js +4 -15
- package/studio/dist/assets/BetaReportPanel-BJ9HIAnz.js +1 -0
- package/studio/dist/assets/{Capstone-Cv9kH6LY.js → Capstone-CoUU-jP7.js} +1 -1
- package/studio/dist/assets/{CodeWorkspace-BwCEINWo.js → CodeWorkspace-BNrL4qvR.js} +2 -2
- package/studio/dist/assets/{Course-BJ_hafUP.js → Course-BMGTXus_.js} +1 -1
- package/studio/dist/assets/{Editor-CV0mNhlz.js → Editor-Cw9j3cnp.js} +1 -1
- package/studio/dist/assets/{Home-C1ry89ak.js → Home-D2woITq5.js} +1 -1
- package/studio/dist/assets/{Lesson-2e9TD9yL.js → Lesson-CYQhrDCZ.js} +2 -2
- package/studio/dist/assets/{NewCourse-BZeOg2xn.js → NewCourse-CMpwVRQb.js} +1 -1
- package/studio/dist/assets/{Progress-CRc_xEWC.js → Progress-2rS19Fur.js} +1 -1
- package/studio/dist/assets/{Review-6QEbHEfk.js → Review-SlqK-hjp.js} +1 -1
- package/studio/dist/assets/{Settings-NFnqVQui.js → Settings-t42u7n9H.js} +1 -1
- package/studio/dist/assets/{TutorPanel-DXQ6Z3BY.js → TutorPanel-DQDWIU7f.js} +3 -3
- package/studio/dist/assets/{abnfDiagram-WEYOIA3C-qeSjKlGM.js → abnfDiagram-WEYOIA3C-jTUmGBuB.js} +1 -1
- package/studio/dist/assets/{anthropic-D7NiQCUH.js → anthropic-iIm2l85r.js} +3 -3
- package/studio/dist/assets/{architecture-WOLXFQ4H-COG-m35l.js → architecture-WOLXFQ4H-Ch9Ld_vv.js} +1 -1
- package/studio/dist/assets/{architectureDiagram-ZHVYKT53-VO7uKoeD.js → architectureDiagram-ZHVYKT53-Dy-z6wsy.js} +1 -1
- package/studio/dist/assets/{blockDiagram-RJAE7QA3-BGJF_qiL.js → blockDiagram-RJAE7QA3-2fHVrc6N.js} +1 -1
- package/studio/dist/assets/{bridge-BTh0AeNX.js → bridge-Cr0q4rLp.js} +1 -1
- package/studio/dist/assets/{c4Diagram-XDPPPE54-C-S10RgU.js → c4Diagram-XDPPPE54-BuuKlG4V.js} +1 -1
- package/studio/dist/assets/{capstone-Amn6Hztq.js → capstone-DhwBeNqk.js} +1 -1
- package/studio/dist/assets/{card-store-BrbrtX9w.js → card-store-CVMBc-Pv.js} +1 -1
- package/studio/dist/assets/channel-M_JkdHrL.js +1 -0
- package/studio/dist/assets/{chunk-2E7WHVMD-fv-iqTyC.js → chunk-2E7WHVMD-lZdQWttk.js} +1 -1
- package/studio/dist/assets/{chunk-4EMNKR2T-CY9IZrgv.js → chunk-4EMNKR2T-C6kbMwke.js} +1 -1
- package/studio/dist/assets/{chunk-55XCU76K-DyTZz7v_.js → chunk-55XCU76K-rkBzkZog.js} +1 -1
- package/studio/dist/assets/{chunk-7S6XSTFO-BNMzTLRW.js → chunk-7S6XSTFO-Skg347QF.js} +1 -1
- package/studio/dist/assets/{chunk-AQDTSKZB-CEYANohH.js → chunk-AQDTSKZB-0pSDBJ23.js} +1 -1
- package/studio/dist/assets/{chunk-DSNLSHJZ-CDk5EXjH.js → chunk-DSNLSHJZ-BaeQDl2i.js} +1 -1
- package/studio/dist/assets/{chunk-HAGFOTED-hNAi1zh_.js → chunk-HAGFOTED-BEm00juw.js} +1 -1
- package/studio/dist/assets/{chunk-HNE4Q36P-COJnSYoZ.js → chunk-HNE4Q36P-DyCR-LvS.js} +1 -1
- package/studio/dist/assets/{chunk-NQOKRVIF-BU6KVxRr.js → chunk-NQOKRVIF-BNJ9uMmB.js} +1 -1
- package/studio/dist/assets/{chunk-UHW7PFBP-DYvxL9JG.js → chunk-UHW7PFBP-DqJczBLs.js} +1 -1
- package/studio/dist/assets/{chunk-VQ5W62QI-CuRfk65j.js → chunk-VQ5W62QI-CVWYSP5Q.js} +1 -1
- package/studio/dist/assets/{chunk-WQQL4CDK-KaG7x-Mb.js → chunk-WQQL4CDK-DJf0Dx05.js} +1 -1
- package/studio/dist/assets/{chunk-YZO67HFG-DbuqIZmk.js → chunk-YZO67HFG-BFUm_JHA.js} +1 -1
- package/studio/dist/assets/{chunk-ZAUX2LTX-bk4ivUmc.js → chunk-ZAUX2LTX-C5ETkkSE.js} +1 -1
- package/studio/dist/assets/{chunk-ZCHMQSOR-B_LElfwh.js → chunk-ZCHMQSOR-WVX9r9PZ.js} +1 -1
- package/studio/dist/assets/{classDiagram-v2-4MYWR3UA-DtCJ6H_X.js → classDiagram-v2-4MYWR3UA-CI77SpuR.js} +1 -1
- package/studio/dist/assets/{course-export-DpaOTT3a.js → course-export-C8jSPuda.js} +1 -1
- package/studio/dist/assets/{cynefin-EF2NZ3EQ-D9btHJvU.js → cynefin-EF2NZ3EQ-CLffmM25.js} +1 -1
- package/studio/dist/assets/{cynefinDiagram-WF24UDRP-CsFJuv27.js → cynefinDiagram-WF24UDRP-BvLwocOb.js} +1 -1
- package/studio/dist/assets/{dagre-NK4GIZVX-Cg1Duec7.js → dagre-NK4GIZVX-C2nMAVdh.js} +1 -1
- package/studio/dist/assets/{diagram-CBK3MWTC-_KU2m5gd.js → diagram-CBK3MWTC-Bid-pdax.js} +1 -1
- package/studio/dist/assets/{diagram-I5XIIV2D-5RaBrwUA.js → diagram-I5XIIV2D-DYJeAvzl.js} +1 -1
- package/studio/dist/assets/{diagram-ODIL2UCW-C0VKxoD3.js → diagram-ODIL2UCW-B06X2r_F.js} +1 -1
- package/studio/dist/assets/{diagram-PFBEJUXE-BaHcZEP2.js → diagram-PFBEJUXE-CwY--5Rz.js} +1 -1
- package/studio/dist/assets/{diagram-RJA3I4VV-cwSAZ90p.js → diagram-RJA3I4VV-4SqhH8zw.js} +1 -1
- package/studio/dist/assets/{diagram-TYUNFSNR-BJImxCEN.js → diagram-TYUNFSNR-CrW4AIM9.js} +1 -1
- package/studio/dist/assets/{ebnfDiagram-V4P3TTPT-OQQLRXcm.js → ebnfDiagram-V4P3TTPT-xeoCmH-d.js} +1 -1
- package/studio/dist/assets/{elk-QONTBCTQ-BJGhQHxQ.js → elk-QONTBCTQ-Dadmz6iS.js} +1 -1
- package/studio/dist/assets/{erDiagram-KYQIGQAA-D91EKSep.js → erDiagram-KYQIGQAA-CSuH0bbF.js} +1 -1
- package/studio/dist/assets/{eventmodeling-K75KTNOO-DgdTRgnw.js → eventmodeling-K75KTNOO-CciVfx3I.js} +1 -1
- package/studio/dist/assets/flowDiagram-IUGLLWBU-DgNR54qK.js +1 -0
- package/studio/dist/assets/{ganttDiagram-R7GPNTJY-CSYLPWEI.js → ganttDiagram-R7GPNTJY-C0wtA-2y.js} +1 -1
- package/studio/dist/assets/{gitGraph-VSP46ZUC-D6GWaV9y.js → gitGraph-VSP46ZUC-BXoDzaA3.js} +1 -1
- package/studio/dist/assets/{gitGraphDiagram-PDYL7XHY-CaV31bvT.js → gitGraphDiagram-PDYL7XHY-vZBlNRPe.js} +1 -1
- package/studio/dist/assets/{index-DioXTZVc.js → index-CS8XPYbB.js} +2 -2
- package/studio/dist/assets/{info-OHQRW6UA-BN-x8GoN.js → info-OHQRW6UA-bs2Qpf7P.js} +1 -1
- package/studio/dist/assets/{infoDiagram-MVDRKAX5-CIose_cy.js → infoDiagram-MVDRKAX5-rPJio6-1.js} +1 -1
- package/studio/dist/assets/{ishikawaDiagram-HPEHV2GE-DCihSNBw.js → ishikawaDiagram-HPEHV2GE-CXf9XFff.js} +1 -1
- package/studio/dist/assets/{journeyDiagram-BOSHW7O7-Bz3o3RIX.js → journeyDiagram-BOSHW7O7-C3MSH79o.js} +1 -1
- package/studio/dist/assets/{kanban-definition-FNSA4HC5-BUyqvlFE.js → kanban-definition-FNSA4HC5-Bdh7SB4n.js} +1 -1
- package/studio/dist/assets/{line-B08T8KlK.js → line-CHkoQXJF.js} +1 -1
- package/studio/dist/assets/{mermaid-parser.core-BYwreSUy.js → mermaid-parser.core-Do1oxD1S.js} +3 -3
- package/studio/dist/assets/{mermaid.core-DTO1oDmq.js → mermaid.core-DgZUD0sU.js} +4 -4
- package/studio/dist/assets/{mindmap-definition-6OY57UG3-BGLwKheY.js → mindmap-definition-6OY57UG3-PUaK6oE_.js} +1 -1
- package/studio/dist/assets/{node.browser-BISniYn8.js → node.browser-DkpMze_r.js} +1 -1
- package/studio/dist/assets/{ollama-De5w84tG.js → ollama-bJNp3jaD.js} +1 -1
- package/studio/dist/assets/{openai-compatible-Joy1oK3L.js → openai-compatible-0tmAyMlN.js} +1 -1
- package/studio/dist/assets/{packet-JDAUHWVQ-CDIMjHS_.js → packet-JDAUHWVQ-vf2FtqFr.js} +1 -1
- package/studio/dist/assets/{pegDiagram-ECIUJNBX-DWXm4mwS.js → pegDiagram-ECIUJNBX-NEVrgPTY.js} +1 -1
- package/studio/dist/assets/{pie-XZMESJXO-CY3QQiKZ.js → pie-XZMESJXO-BIWydVNZ.js} +1 -1
- package/studio/dist/assets/{pieDiagram-GNMPY74T-M1aCnI7W.js → pieDiagram-GNMPY74T-BI9_u6rT.js} +1 -1
- package/studio/dist/assets/{quadrantDiagram-D57K4MC3-BFFtO7U5.js → quadrantDiagram-D57K4MC3-ryNpoBC5.js} +1 -1
- package/studio/dist/assets/{radar-ABXABTNO-DT0W4_Xn.js → radar-ABXABTNO-D8TjnvBB.js} +1 -1
- package/studio/dist/assets/{railroad-I3PHUGI6-_VCpgZR5.js → railroad-I3PHUGI6-BmEDV5kf.js} +1 -1
- package/studio/dist/assets/{railroad-abnf-LNEFI6M7-DkSpQ5YY.js → railroad-abnf-LNEFI6M7-Cs_sArMc.js} +1 -1
- package/studio/dist/assets/{railroad-ebnf-DWYD2UWJ-BqWILdGb.js → railroad-ebnf-DWYD2UWJ-DYuCq46d.js} +1 -1
- package/studio/dist/assets/{railroad-peg-JR7BVNR7-BB0bQL-Z.js → railroad-peg-JR7BVNR7-BcXSgdMy.js} +1 -1
- package/studio/dist/assets/{railroadDiagram-Y72NRBL7-CjLKjIdJ.js → railroadDiagram-Y72NRBL7-DBcc8b2c.js} +1 -1
- package/studio/dist/assets/{rehype-katex-C-sKddsH.js → rehype-katex-BfUIq5As.js} +1 -1
- package/studio/dist/assets/{remark-math-C-ox67hE.js → remark-math-XvZOjmDO.js} +1 -1
- package/studio/dist/assets/{requirementDiagram-EQYSW5RA-CnwzZqR8.js → requirementDiagram-EQYSW5RA-CVcBgM1L.js} +1 -1
- package/studio/dist/assets/{sankeyDiagram-SY24JHO5-CPDugTUl.js → sankeyDiagram-SY24JHO5-DjZ81hDs.js} +1 -1
- package/studio/dist/assets/{sequenceDiagram-BLEHNHQU-1dLfeU9Y.js → sequenceDiagram-BLEHNHQU-BNwOa2S7.js} +1 -1
- package/studio/dist/assets/{stateDiagram-v2-A6IESKWZ-DR7CmEjj.js → stateDiagram-v2-A6IESKWZ-BFWa5lEx.js} +1 -1
- package/studio/dist/assets/{swimlanes-B3ENRKFQ-BAWB9omQ.js → swimlanes-B3ENRKFQ-LfM_Jg6Z.js} +1 -1
- package/studio/dist/assets/swimlanesDiagram-AYQRV4AK-BDmpoiGp.js +8 -0
- package/studio/dist/assets/{timeline-definition-JXYKGLGB-DNkj8z77.js → timeline-definition-JXYKGLGB-BwGzkWgZ.js} +1 -1
- package/studio/dist/assets/{treeView-D4JQ5SDB-BA-ouhMb.js → treeView-D4JQ5SDB-MLk3VuRt.js} +1 -1
- package/studio/dist/assets/{treemap-SAJKECNS-BrrGxsAb.js → treemap-SAJKECNS-D8iSjp7L.js} +1 -1
- package/studio/dist/assets/{usecaseDiagram-WPOLBNNX-BB3D0Dt_.js → usecaseDiagram-WPOLBNNX-BqxpaNlT.js} +1 -1
- package/studio/dist/assets/{vennDiagram-Q3Y3IDCW-BrtqtKTE.js → vennDiagram-Q3Y3IDCW-CpeUDMhQ.js} +1 -1
- package/studio/dist/assets/{wardley-7MLQ67FV-BKkemDql.js → wardley-7MLQ67FV-tAMbCZAj.js} +1 -1
- package/studio/dist/assets/{wardleyDiagram-IVAIDKWA-DFnI3P5z.js → wardleyDiagram-IVAIDKWA-CDJViWzt.js} +1 -1
- package/studio/dist/assets/{xychartDiagram-4URNHDU4-Da0DZG_q.js → xychartDiagram-4URNHDU4-CwaQrd3_.js} +1 -1
- package/studio/dist/index.html +1 -1
- package/templates/claude/plugin.json +1 -1
- package/templates/gemini/GEMINI.md +18 -16
- package/web/server.js +3 -3
- package/studio/dist/assets/BetaReportPanel-8NrDLiPm.js +0 -1
- package/studio/dist/assets/channel-SJiUQu_N.js +0 -1
- package/studio/dist/assets/flowDiagram-IUGLLWBU-CVnJYMum.js +0 -1
- package/studio/dist/assets/swimlanesDiagram-AYQRV4AK-qeuHru16.js +0 -8
package/bin/platforms/cursor.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
substituteTokens,
|
|
6
|
+
createInstallRun,
|
|
7
|
+
writeManagedFile,
|
|
8
|
+
printInstallSummary,
|
|
9
|
+
} from './_shared.js';
|
|
5
10
|
|
|
6
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
12
|
const PLUGIN_DIR = join(__dirname, '..', '..');
|
|
@@ -15,29 +20,27 @@ export function detect() {
|
|
|
15
20
|
export async function install(scope = 'local') {
|
|
16
21
|
const base = scope === 'global' ? (process.env.HOME || '') : process.cwd();
|
|
17
22
|
const rulesDir = join(base, '.cursor', 'rules');
|
|
23
|
+
const run = createInstallRun();
|
|
24
|
+
|
|
18
25
|
if (!existsSync(rulesDir)) {
|
|
19
26
|
mkdirSync(rulesDir, { recursive: true });
|
|
20
27
|
console.log('✓ Created .cursor/rules/ directory');
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const adapted = substituteTokens(combined, 'cursor');
|
|
38
|
-
writeFileSync(mdcPath, adapted);
|
|
39
|
-
console.log(' + .cursor/rules/professor.mdc');
|
|
40
|
-
}
|
|
30
|
+
const frontmatterPath = join(PLUGIN_DIR, 'templates', 'cursor', 'professor.mdc');
|
|
31
|
+
const frontmatter = existsSync(frontmatterPath)
|
|
32
|
+
? readFileSync(frontmatterPath, 'utf-8')
|
|
33
|
+
: '---\ndescription: Socratic learning assistant - professor mode\nalwaysApply: true\n---\n';
|
|
34
|
+
const rawSkill = readFileSync(join(PLUGIN_DIR, 'shared', 'SKILL.md'), 'utf-8');
|
|
35
|
+
// Strip YAML frontmatter from SKILL.md so the .mdc file has only one frontmatter block
|
|
36
|
+
const skill = rawSkill.startsWith('---')
|
|
37
|
+
? rawSkill.replace(/^---[\s\S]*?---\n*/, '')
|
|
38
|
+
: rawSkill;
|
|
39
|
+
const adapted = substituteTokens(`${frontmatter}\n${skill}`, 'cursor');
|
|
40
|
+
|
|
41
|
+
writeManagedFile(join(rulesDir, 'professor.mdc'), adapted, run, '.cursor/rules/professor.mdc');
|
|
42
|
+
|
|
43
|
+
printInstallSummary('Cursor', run);
|
|
41
44
|
|
|
42
45
|
console.log(`
|
|
43
46
|
✅ Setup complete for Cursor!
|
package/bin/platforms/gemini.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
substituteTokens,
|
|
6
|
+
generateCommandFiles,
|
|
7
|
+
createInstallRun,
|
|
8
|
+
writeManagedBlock,
|
|
9
|
+
printInstallSummary,
|
|
10
|
+
} from './_shared.js';
|
|
5
11
|
|
|
6
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
13
|
const PLUGIN_DIR = join(__dirname, '..', '..');
|
|
@@ -18,6 +24,8 @@ export function detect() {
|
|
|
18
24
|
/** Install professor for Gemini CLI. scope = 'global' → ~/, 'local' → cwd/ */
|
|
19
25
|
export async function install(scope = 'local') {
|
|
20
26
|
const base = scope === 'global' ? (process.env.HOME || '') : process.cwd();
|
|
27
|
+
const run = createInstallRun();
|
|
28
|
+
|
|
21
29
|
// 1. Create .gemini/ directory
|
|
22
30
|
const geminiDir = join(base, '.gemini');
|
|
23
31
|
if (!existsSync(geminiDir)) {
|
|
@@ -25,35 +33,26 @@ export async function install(scope = 'local') {
|
|
|
25
33
|
console.log('✓ Created .gemini/ directory');
|
|
26
34
|
}
|
|
27
35
|
|
|
28
|
-
// 2.
|
|
36
|
+
// 2. Refresh the Professor block in GEMINI.md (preamble + shared/SKILL.md), ask_user substituted
|
|
29
37
|
const preamblePath = join(PLUGIN_DIR, 'templates', 'gemini', 'GEMINI.md');
|
|
30
38
|
const skillPath = join(PLUGIN_DIR, 'shared', 'SKILL.md');
|
|
31
39
|
const preamble = existsSync(preamblePath) ? readFileSync(preamblePath, 'utf-8') : '';
|
|
32
40
|
const skill = readFileSync(skillPath, 'utf-8');
|
|
33
|
-
const
|
|
34
|
-
`<!-- professor:start -->\n${preamble}\n${skill}\n<!-- professor:end -->`;
|
|
35
|
-
const adapted = substituteTokens(professorBlock, 'gemini');
|
|
41
|
+
const adapted = substituteTokens(`${preamble}\n${skill}`, 'gemini');
|
|
36
42
|
|
|
37
43
|
// Global: GEMINI.md lives inside ~/.gemini/; local: GEMINI.md lives at cwd/ (Gemini CLI walks upward)
|
|
38
44
|
const geminiMdPath = scope === 'global' ? join(geminiDir, 'GEMINI.md') : join(base, 'GEMINI.md');
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (existing.includes('<!-- professor:start -->')) {
|
|
42
|
-
console.log(' ↔ GEMINI.md (professor block already present, skipping)');
|
|
43
|
-
} else {
|
|
44
|
-
writeFileSync(geminiMdPath, existing + '\n\n' + adapted);
|
|
45
|
-
console.log(' + GEMINI.md (professor block appended to existing file)');
|
|
46
|
-
}
|
|
47
|
-
} else {
|
|
48
|
-
writeFileSync(geminiMdPath, adapted);
|
|
49
|
-
console.log(' + GEMINI.md');
|
|
50
|
-
}
|
|
45
|
+
const geminiLabel = scope === 'global' ? '~/.gemini/GEMINI.md' : 'GEMINI.md';
|
|
46
|
+
writeManagedBlock(geminiMdPath, adapted, run, geminiLabel);
|
|
51
47
|
|
|
52
48
|
// 3. Generate .toml command files for Gemini CLI
|
|
49
|
+
console.log('✓ Generating command files...');
|
|
53
50
|
const commandsDir = scope === 'global'
|
|
54
51
|
? join(geminiDir, 'commands', 'professor')
|
|
55
52
|
: join(base, '.gemini', 'commands', 'professor');
|
|
56
|
-
generateCommandFiles(commandsDir, 'gemini');
|
|
53
|
+
generateCommandFiles(commandsDir, 'gemini', run);
|
|
54
|
+
|
|
55
|
+
printInstallSummary('Gemini CLI', run);
|
|
57
56
|
|
|
58
57
|
console.log(`
|
|
59
58
|
✅ Setup complete for Gemini CLI!
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
substituteTokens,
|
|
6
|
+
generateCommandFiles,
|
|
7
|
+
adaptAgentFrontmatter,
|
|
8
|
+
createInstallRun,
|
|
9
|
+
writeManagedFile,
|
|
10
|
+
writeManagedBlock,
|
|
11
|
+
isLegacySkillDocument,
|
|
12
|
+
printInstallSummary,
|
|
13
|
+
BLOCK_START,
|
|
14
|
+
BLOCK_END,
|
|
15
|
+
} from './_shared.js';
|
|
5
16
|
|
|
6
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
18
|
const PLUGIN_DIR = join(__dirname, '..', '..');
|
|
@@ -25,51 +36,49 @@ export async function install(scope = 'local') {
|
|
|
25
36
|
? join(process.env.HOME || '', '.config', 'opencode')
|
|
26
37
|
: join(process.cwd(), '.opencode');
|
|
27
38
|
|
|
39
|
+
const run = createInstallRun();
|
|
40
|
+
|
|
28
41
|
if (!existsSync(configBase)) {
|
|
29
42
|
mkdirSync(configBase, { recursive: true });
|
|
30
43
|
console.log(`✓ Created ${scope === 'global' ? '~/.config/opencode/' : '.opencode/'} directory`);
|
|
31
44
|
}
|
|
32
45
|
|
|
33
|
-
// 1.
|
|
46
|
+
// 1. Refresh the Professor block in AGENTS.md (OpenCode auto-loads it — no config entry needed)
|
|
34
47
|
const agentsMdPath = scope === 'global'
|
|
35
48
|
? join(configBase, 'AGENTS.md')
|
|
36
49
|
: join(process.cwd(), 'AGENTS.md');
|
|
50
|
+
const agentsLabel = scope === 'global' ? '~/.config/opencode/AGENTS.md' : 'AGENTS.md';
|
|
51
|
+
const skillDoc = readFileSync(join(PLUGIN_DIR, 'shared', 'SKILL.md'), 'utf-8');
|
|
52
|
+
const skill = substituteTokens(skillDoc, 'opencode');
|
|
53
|
+
|
|
54
|
+
const existingAgentsMd = existsSync(agentsMdPath) ? readFileSync(agentsMdPath, 'utf-8') : null;
|
|
55
|
+
const isLegacyWholeFile = existingAgentsMd !== null
|
|
56
|
+
&& !existingAgentsMd.includes(BLOCK_START)
|
|
57
|
+
&& isLegacySkillDocument(existingAgentsMd);
|
|
37
58
|
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
const adapted = substituteTokens(skill, 'opencode');
|
|
41
|
-
writeFileSync(agentsMdPath, adapted);
|
|
42
|
-
console.log(` + ${scope === 'global' ? '~/.config/opencode/AGENTS.md' : 'AGENTS.md'}`);
|
|
59
|
+
if (isLegacyWholeFile) {
|
|
60
|
+
writeManagedFile(agentsMdPath, `${BLOCK_START}\n${skill}\n${BLOCK_END}\n`, run, agentsLabel);
|
|
43
61
|
} else {
|
|
44
|
-
|
|
62
|
+
writeManagedBlock(agentsMdPath, skill, run, agentsLabel);
|
|
45
63
|
}
|
|
46
64
|
|
|
47
65
|
// 2. Write command files into commands/ dir
|
|
66
|
+
console.log('✓ Generating command files...');
|
|
48
67
|
const commandsDir = scope === 'global'
|
|
49
68
|
? join(configBase, 'commands')
|
|
50
69
|
: join(process.cwd(), '.opencode', 'commands');
|
|
51
|
-
|
|
52
|
-
console.log('✓ Generating command files...');
|
|
53
|
-
generateCommandFiles(commandsDir, 'opencode');
|
|
70
|
+
generateCommandFiles(commandsDir, 'opencode', run);
|
|
54
71
|
|
|
55
72
|
// 3. Write agents/professor.md
|
|
56
73
|
const agentsDir = join(configBase, 'agents');
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
let agentSrc = readFileSync(join(PLUGIN_DIR, 'shared', 'agents', 'professor.md'), 'utf-8');
|
|
63
|
-
agentSrc = substituteTokens(agentSrc, 'opencode');
|
|
64
|
-
agentSrc = adaptAgentFrontmatter(agentSrc, 'opencode');
|
|
65
|
-
writeFileSync(agentFilePath, agentSrc);
|
|
66
|
-
const displayPath = scope === 'global' ? '~/.config/opencode/agents/professor.md' : '.opencode/agents/professor.md';
|
|
67
|
-
console.log(` + ${displayPath}`);
|
|
68
|
-
} else {
|
|
69
|
-
console.log(' ↔ agents/professor.md (already exists)');
|
|
70
|
-
}
|
|
74
|
+
let agentSrc = readFileSync(join(PLUGIN_DIR, 'shared', 'agents', 'professor.md'), 'utf-8');
|
|
75
|
+
agentSrc = substituteTokens(agentSrc, 'opencode');
|
|
76
|
+
agentSrc = adaptAgentFrontmatter(agentSrc, 'opencode');
|
|
77
|
+
const displayPath = scope === 'global' ? '~/.config/opencode/agents/professor.md' : '.opencode/agents/professor.md';
|
|
78
|
+
writeManagedFile(join(agentsDir, 'professor.md'), agentSrc, run, displayPath);
|
|
71
79
|
|
|
72
|
-
// 4.
|
|
80
|
+
// 4. Merge opencode.json — $schema only, no instructions[] field. Not plugin-owned content,
|
|
81
|
+
// so it is counted but never backed up.
|
|
73
82
|
const opencodeJsonPath = join(configBase, 'opencode.json');
|
|
74
83
|
let config = {};
|
|
75
84
|
if (existsSync(opencodeJsonPath)) {
|
|
@@ -81,9 +90,19 @@ export async function install(scope = 'local') {
|
|
|
81
90
|
|
|
82
91
|
if (!config.$schema) config.$schema = 'https://opencode.ai/config.json';
|
|
83
92
|
|
|
84
|
-
writeFileSync(opencodeJsonPath, JSON.stringify(config, null, 2) + '\n');
|
|
85
93
|
const configDisplayPath = scope === 'global' ? '~/.config/opencode/opencode.json' : '.opencode/opencode.json';
|
|
86
|
-
|
|
94
|
+
const json = JSON.stringify(config, null, 2) + '\n';
|
|
95
|
+
const previous = existsSync(opencodeJsonPath) ? readFileSync(opencodeJsonPath, 'utf-8') : null;
|
|
96
|
+
if (previous === json) {
|
|
97
|
+
run.unchanged++;
|
|
98
|
+
console.log(` = ${configDisplayPath} (unchanged)`);
|
|
99
|
+
} else {
|
|
100
|
+
writeFileSync(opencodeJsonPath, json);
|
|
101
|
+
run.updated++;
|
|
102
|
+
console.log(` ${previous === null ? '+' : '~'} ${configDisplayPath}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
printInstallSummary('OpenCode', run);
|
|
87
106
|
|
|
88
107
|
console.log(`
|
|
89
108
|
✅ Setup complete for OpenCode!
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ronin-skillforce",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-beta.0",
|
|
4
4
|
"description": "Ronin SkillForce — a Socratic learning coach for AI agents and a local Studio. It teaches by asking questions, grounds lectures in real sources and keeps your progress on disk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"studio/src/lib/",
|
|
51
51
|
"README.md",
|
|
52
52
|
"CHANGELOG.md",
|
|
53
|
-
"LICENSE"
|
|
53
|
+
"LICENSE",
|
|
54
|
+
"NOTICE"
|
|
54
55
|
],
|
|
55
56
|
"keywords": [
|
|
56
57
|
"learning",
|
|
@@ -81,8 +82,8 @@
|
|
|
81
82
|
"engines": {
|
|
82
83
|
"node": ">=18.0.0"
|
|
83
84
|
},
|
|
84
|
-
"author": "ronnie
|
|
85
|
-
"license": "
|
|
85
|
+
"author": "Tuấn Khuất (ronnie)",
|
|
86
|
+
"license": "Apache-2.0",
|
|
86
87
|
"packageManager": "npm@11.19.0",
|
|
87
88
|
"devDependencies": {
|
|
88
89
|
"@playwright/test": "^1.50.0",
|
package/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "course-learning-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-beta.0",
|
|
4
4
|
"description": "A Socratic learning plugin for Claude Code. The professor agent guides learners through courses using the Socratic method — asking questions rather than giving answers.",
|
|
5
5
|
"agents": [
|
|
6
6
|
{
|