@michaelborck/honeyguide-cli 0.0.0-stage → 0.7.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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import { readFileSync } from 'node:fs';
4
+ import { readFile } from 'node:fs/promises';
5
+ import { Command } from 'commander';
6
+ import { suggestResources, suggestBatch, toBatchMarkdown, recheckResources, toRecheckMarkdown, configFromEnv, toMarkdown, toCitations, toLmsHtml, extract, toCollectionFile, resourcesFromSaved, parseOutcomes, } from '@michaelborck/honeyguide-core';
7
+ function cliVersion() {
8
+ try {
9
+ const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
10
+ return pkg.version ?? '0.0.0';
11
+ }
12
+ catch {
13
+ return '0.0.0';
14
+ }
15
+ }
16
+ const program = new Command();
17
+ async function readOutcomes(file) {
18
+ if (!file)
19
+ return [];
20
+ const outcomes = parseOutcomes(await readFile(file, 'utf8'));
21
+ if (!outcomes.length)
22
+ program.error('No outcomes found in file.');
23
+ return outcomes;
24
+ }
25
+ /** The scriptable subset of the interview brief (ADR-0018). */
26
+ function briefOptions(options) {
27
+ const constraints = {
28
+ ...(options.openAccess ? { openAccessOnly: true } : {}),
29
+ ...(options.noVideo ? { excludeFormats: ['video'] } : {}),
30
+ ...(options.since ? { minYear: Number(options.since) } : {}),
31
+ };
32
+ return {
33
+ ...(Object.keys(constraints).length ? { constraints } : {}),
34
+ ...(options.context ? { context: options.context } : {}),
35
+ };
36
+ }
37
+ program
38
+ .name('honeyguide')
39
+ .description('Finds and verifies supporting resources for your teaching.')
40
+ .version(cliVersion());
41
+ program
42
+ .command('suggest')
43
+ .description('List mode: verified, annotated resources for a topic or document')
44
+ .argument('[topic...]', 'topic to find supporting resources for')
45
+ .option('-f, --file <path>', 'read the topic from a document (PDF, DOCX, TXT, MD)')
46
+ .option('-n, --max-results <n>', 'maximum number of resources', '10')
47
+ .option('-o, --format <format>', 'output format: markdown, json, html (LMS-ready), apa, harvard', 'markdown')
48
+ .option('--json', 'shorthand for --format json')
49
+ .option('--collection', 'write a portable collection file (JSON) that can be reopened and shared')
50
+ .option('--outcomes <path>', 'align resources to unit outcomes (one per line)')
51
+ .option('--open-access', 'only freely readable papers (best effort)')
52
+ .option('--no-video', 'omit video results')
53
+ .option('--since <year>', 'only resources published since this year')
54
+ .option('--context <text>', 'teaching context for the rationale')
55
+ .option('-c, --counterpoint', 'also surface material disagreeing with the framing')
56
+ .action(async (topicWords, options) => {
57
+ let input = topicWords.join(' ');
58
+ let label = input;
59
+ if (options.file) {
60
+ const doc = await extract(options.file);
61
+ input = doc.text;
62
+ label = label || path.basename(options.file);
63
+ }
64
+ if (!input.trim()) {
65
+ program.error('Provide a topic or --file <path>.');
66
+ }
67
+ const outcomes = await readOutcomes(options.outcomes);
68
+ const result = await suggestResources({
69
+ input,
70
+ maxResults: Number(options.maxResults),
71
+ counterpoint: Boolean(options.counterpoint),
72
+ ...(outcomes.length ? { outcomes } : {}),
73
+ ...briefOptions(options),
74
+ }, configFromEnv());
75
+ const format = options.collection
76
+ ? 'collection'
77
+ : options.json
78
+ ? 'json'
79
+ : options.format;
80
+ let out;
81
+ switch (format) {
82
+ case 'collection':
83
+ out = JSON.stringify(toCollectionFile(label, result, outcomes), null, 2);
84
+ break;
85
+ case 'json':
86
+ out = JSON.stringify(result, null, 2);
87
+ break;
88
+ case 'html':
89
+ out = toLmsHtml(label, result);
90
+ break;
91
+ case 'apa':
92
+ case 'harvard':
93
+ out = toCitations(result, format);
94
+ break;
95
+ default:
96
+ out = toMarkdown(label, result);
97
+ }
98
+ process.stdout.write(out + '\n');
99
+ });
100
+ program
101
+ .command('batch')
102
+ .description('Batch mode: verified resources for many topics at once (one per line)')
103
+ .argument('<file>', 'text file with one topic per line')
104
+ .option('-n, --max-results <n>', 'maximum resources per topic', '8')
105
+ .option('--outcomes <path>', 'align each topic to unit outcomes (one per line)')
106
+ .option('--open-access', 'only freely readable papers (best effort)')
107
+ .option('--no-video', 'omit video results')
108
+ .option('--since <year>', 'only resources published since this year')
109
+ .option('--context <text>', 'teaching context for rationales')
110
+ .option('-c, --counterpoint', 'also surface disagreeing material per topic')
111
+ .option('--json', 'output JSON instead of markdown')
112
+ .action(async (file, options) => {
113
+ const topics = (await readFile(file, 'utf8'))
114
+ .split('\n')
115
+ .map((l) => l.trim())
116
+ .filter((l) => l && !l.startsWith('#'));
117
+ if (!topics.length)
118
+ program.error('No topics found in file.');
119
+ const outcomes = await readOutcomes(options.outcomes);
120
+ const entries = await suggestBatch(topics, configFromEnv(), {
121
+ maxResults: Number(options.maxResults),
122
+ counterpoint: Boolean(options.counterpoint),
123
+ ...(outcomes.length ? { outcomes } : {}),
124
+ ...briefOptions(options),
125
+ });
126
+ process.stdout.write((options.json ? JSON.stringify({ entries }, null, 2) : toBatchMarkdown(entries)) +
127
+ '\n');
128
+ });
129
+ program
130
+ .command('recheck')
131
+ .description('Link-rot re-run: re-verify a saved collection or JSON result list')
132
+ .argument('<file>', 'collection file, or JSON from `suggest --json` / `batch --json`')
133
+ .option('--json', 'output JSON instead of markdown')
134
+ .action(async (file, options) => {
135
+ const saved = JSON.parse(await readFile(file, 'utf8'));
136
+ const resources = resourcesFromSaved(saved);
137
+ if (!resources.length) {
138
+ program.error('No resources found in file — expected a collection, or suggest/batch JSON output.');
139
+ }
140
+ const entries = await recheckResources(resources);
141
+ process.stdout.write((options.json ? JSON.stringify({ entries }, null, 2) : toRecheckMarkdown(entries)) +
142
+ '\n');
143
+ });
144
+ program.parseAsync().catch((error) => {
145
+ console.error(error instanceof Error ? error.message : error);
146
+ process.exitCode = 1;
147
+ });
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,GACd,MAAM,+BAA+B,CAAC;AAEvC,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC1C,CAAC;QAC1B,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,KAAK,UAAU,YAAY,CAAC,IAAa;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+DAA+D;AAC/D,SAAS,YAAY,CAAC,OAKrB;IACC,MAAM,WAAW,GAAG;QAClB,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,OAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7D,CAAC;IACF,OAAO;QACL,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,kEAAkE,CAAC;KAC/E,QAAQ,CAAC,YAAY,EAAE,wCAAwC,CAAC;KAChE,MAAM,CAAC,mBAAmB,EAAE,qDAAqD,CAAC;KAClF,MAAM,CAAC,uBAAuB,EAAE,6BAA6B,EAAE,IAAI,CAAC;KACpE,MAAM,CACL,uBAAuB,EACvB,+DAA+D,EAC/D,UAAU,CACX;KACA,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC;KAC/C,MAAM,CAAC,cAAc,EAAE,yEAAyE,CAAC;KACjG,MAAM,CAAC,mBAAmB,EAAE,iDAAiD,CAAC;KAC9E,MAAM,CAAC,eAAe,EAAE,2CAA2C,CAAC;KACpE,MAAM,CAAC,YAAY,EAAE,oBAAoB,CAAC;KAC1C,MAAM,CAAC,gBAAgB,EAAE,0CAA0C,CAAC;KACpE,MAAM,CAAC,kBAAkB,EAAE,oCAAoC,CAAC;KAChE,MAAM,CAAC,oBAAoB,EAAE,oDAAoD,CAAC;KAClF,MAAM,CACL,KAAK,EACH,UAAoB,EACpB,OAYC,EACD,EAAE;IACF,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACxC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC;QACjB,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACrD,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC;QACE,KAAK;QACL,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QACtC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;QAC3C,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,GAAG,YAAY,CAAC,OAAO,CAAC;KACzB,EACD,aAAa,EAAE,CAChB,CAAC;IACF,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU;QAC/B,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,OAAO,CAAC,IAAI;YACZ,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACrB,IAAI,GAAW,CAAC;IAChB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,YAAY;YACf,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACzE,MAAM;QACR,KAAK,MAAM;YACT,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACtC,MAAM;QACR,KAAK,MAAM;YACT,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,KAAK,CAAC;QACX,KAAK,SAAS;YACZ,GAAG,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAClC,MAAM;QACR;YACE,GAAG,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;AACnC,CAAC,CACF,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,uEAAuE,CAAC;KACpF,QAAQ,CAAC,QAAQ,EAAE,mCAAmC,CAAC;KACvD,MAAM,CAAC,uBAAuB,EAAE,6BAA6B,EAAE,GAAG,CAAC;KACnE,MAAM,CAAC,mBAAmB,EAAE,kDAAkD,CAAC;KAC/E,MAAM,CAAC,eAAe,EAAE,2CAA2C,CAAC;KACpE,MAAM,CAAC,YAAY,EAAE,oBAAoB,CAAC;KAC1C,MAAM,CAAC,gBAAgB,EAAE,0CAA0C,CAAC;KACpE,MAAM,CAAC,kBAAkB,EAAE,iCAAiC,CAAC;KAC7D,MAAM,CAAC,oBAAoB,EAAE,6CAA6C,CAAC;KAC3E,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACnD,MAAM,CACL,KAAK,EACH,IAAY,EACZ,OASC,EACD,EAAE;IACF,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;SAC1C,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE;QAC1D,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QACtC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;QAC3C,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,GAAG,YAAY,CAAC,OAAO,CAAC;KACzB,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC9E,IAAI,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,mEAAmE,CAAC;KAChF,QAAQ,CAAC,QAAQ,EAAE,iEAAiE,CAAC;KACrF,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACnD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAA2B,EAAE,EAAE;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CACX,mFAAmF,CACpF,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAChF,IAAI,CACP,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "@michaelborck/honeyguide-cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.7.0",
4
+ "description": "Honeyguide CLI: verified teaching resources from your terminal.",
5
+ "license": "MIT",
6
+ "author": "Michael Borck",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/michael-borck/honeyguide.git",
10
+ "directory": "packages/cli"
11
+ },
12
+ "type": "module",
13
+ "bin": {
14
+ "honeyguide": "dist/index.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json"
21
+ },
22
+ "dependencies": {
23
+ "@michaelborck/honeyguide-core": "*",
24
+ "commander": "^12.1.0"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.5.0"
28
+ }
29
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.