@jpetit/toolkit 3.0.23 → 3.1.2
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/assets/prompts/creators/create-solution.tpl.txt +10 -0
- package/assets/prompts/creators/create-statement.tpl.txt +21 -0
- package/assets/prompts/creators/create-translation.tpl.txt +5 -0
- package/assets/prompts/creators/private-test-cases.txt +6 -0
- package/assets/prompts/creators/sample-test-cases.txt +6 -0
- package/assets/prompts/creators/system-prompt.txt +2 -0
- package/assets/prompts/examples/statement-coda.tex +7 -0
- package/assets/prompts/examples/statement.tex +19 -0
- package/assets/prompts/generators/efficiency.md +41 -0
- package/assets/prompts/generators/hard.md +47 -0
- package/assets/prompts/generators/random.md +39 -0
- package/assets/prompts/proglangs/cc.md +3 -0
- package/assets/prompts/proglangs/py.md +40 -0
- package/lib/ai.ts +60 -4
- package/lib/cleaner.ts +24 -13
- package/lib/compilers/base.ts +70 -14
- package/lib/compilers/clojure.ts +21 -10
- package/lib/compilers/gcc.ts +4 -33
- package/lib/compilers/ghc.ts +4 -40
- package/lib/compilers/gxx.ts +4 -33
- package/lib/compilers/index.ts +9 -0
- package/lib/compilers/java.ts +105 -0
- package/lib/compilers/python3.ts +44 -37
- package/lib/compilers/run-clojure.ts +101 -0
- package/lib/compilers/run-haskell.ts +26 -22
- package/lib/compilers/run-python.ts +29 -35
- package/lib/compilers/rust.ts +39 -0
- package/lib/create-with-jutgeai.ts +407 -0
- package/lib/create-with-template.ts +55 -0
- package/lib/data.ts +6 -0
- package/lib/doctor.ts +86 -6
- package/lib/generate.ts +132 -290
- package/lib/helpers.ts +48 -0
- package/lib/inspector.ts +253 -0
- package/lib/jutge_api_client.ts +4631 -0
- package/lib/maker.ts +202 -289
- package/lib/settings.ts +26 -17
- package/lib/tui.ts +25 -15
- package/lib/types.ts +40 -5
- package/lib/upload.ts +216 -0
- package/lib/utils.ts +82 -14
- package/lib/versions.ts +46 -0
- package/package.json +50 -11
- package/toolkit/about.ts +43 -0
- package/toolkit/ai.ts +44 -18
- package/toolkit/check.ts +16 -0
- package/toolkit/clean.ts +16 -26
- package/toolkit/compilers.ts +4 -4
- package/toolkit/config.ts +91 -0
- package/toolkit/create.ts +30 -58
- package/toolkit/doctor.ts +15 -11
- package/toolkit/generate.ts +195 -98
- package/toolkit/index.ts +32 -21
- package/toolkit/make.ts +12 -48
- package/toolkit/upgrade.ts +9 -0
- package/toolkit/upload.ts +19 -0
- package/toolkit/create-jutge-ai.ts +0 -101
- package/toolkit/create-template.ts +0 -55
- package/toolkit/create-wizard.ts +0 -6
- package/toolkit/init.ts +0 -56
- package/toolkit/verify.ts +0 -19
package/package.json
CHANGED
|
@@ -1,27 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jpetit/toolkit",
|
|
3
3
|
"description": "Toolkit to prepare problems for Jutge.org",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.1.2",
|
|
5
|
+
"homepage": "https://jutge.org",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Jutge.org",
|
|
8
|
+
"email": "info@jutge.org",
|
|
9
|
+
"url": "https://jutge.org"
|
|
10
|
+
},
|
|
11
|
+
"contributors": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Jordi Petit",
|
|
14
|
+
"url": "https://github.com/jordi-petit"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "Pau Fernández",
|
|
18
|
+
"url": "https://github.com/pauek"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/jutge-org/jutge-toolkit.git"
|
|
24
|
+
},
|
|
5
25
|
"publishConfig": {
|
|
6
26
|
"access": "public"
|
|
7
27
|
},
|
|
8
28
|
"module": "index.ts",
|
|
9
29
|
"type": "module",
|
|
10
|
-
"bin":
|
|
30
|
+
"bin": {
|
|
31
|
+
"jutge-toolkit": "toolkit/index.ts",
|
|
32
|
+
"jtk": "toolkit/index.ts"
|
|
33
|
+
},
|
|
11
34
|
"scripts": {
|
|
12
35
|
"lint": "eslint .",
|
|
13
36
|
"format": "bun prettier --write .",
|
|
14
|
-
"depcheck": "bunx depcheck"
|
|
37
|
+
"depcheck": "bunx depcheck",
|
|
38
|
+
"update-jutge-client": "(cd lib ; rm -f jutge_api_client.ts ; https --download https://api.jutge.org/clients/download/typescript)"
|
|
15
39
|
},
|
|
16
40
|
"files": [
|
|
41
|
+
"assets",
|
|
17
42
|
"lib",
|
|
18
|
-
"toolkit"
|
|
19
|
-
"assets"
|
|
43
|
+
"toolkit"
|
|
20
44
|
],
|
|
21
45
|
"dependencies": {
|
|
22
46
|
"@commander-js/extra-typings": "^14.0.0",
|
|
23
47
|
"@eslint/js": "^9.39.2",
|
|
24
48
|
"@inquirer/prompts": "^8.1.0",
|
|
49
|
+
"archiver": "^7.0.1",
|
|
25
50
|
"boxen": "^8.0.1",
|
|
26
51
|
"bun-types": "^1.3.5",
|
|
27
52
|
"chalk": "^5.6.2",
|
|
@@ -30,35 +55,49 @@
|
|
|
30
55
|
"eslint": "^9.39.2",
|
|
31
56
|
"execa": "^9.6.1",
|
|
32
57
|
"gpt-tokenizer": "^3.4.0",
|
|
58
|
+
"handlebars": "^4.7.8",
|
|
33
59
|
"human-id": "^4.1.3",
|
|
34
60
|
"image-size": "^2.0.2",
|
|
35
|
-
"
|
|
36
|
-
"jdenticon": "^3.3.0",
|
|
61
|
+
"inquirer-checkbox-plus-plus": "^1.1.1",
|
|
37
62
|
"marked": "^17.0.1",
|
|
38
63
|
"marked-terminal": "^7.3.0",
|
|
39
64
|
"multi-llm-ts": "^4.6.2",
|
|
40
65
|
"nanoid": "^5.1.6",
|
|
66
|
+
"openai": "^6.15.0",
|
|
41
67
|
"ora": "^9.0.0",
|
|
42
68
|
"prettier": "^3.7.4",
|
|
43
69
|
"pretty-bytes": "^7.1.0",
|
|
44
70
|
"pretty-ms": "^9.3.0",
|
|
45
71
|
"radash": "^12.1.1",
|
|
46
|
-
"
|
|
72
|
+
"semver": "^7.7.3",
|
|
73
|
+
"sharp": "^0.34.5",
|
|
47
74
|
"terminal-image": "^4.1.0",
|
|
48
75
|
"terminal-link": "^5.0.0",
|
|
49
|
-
"typescript-eslint": "^8.
|
|
76
|
+
"typescript-eslint": "^8.51.0",
|
|
50
77
|
"yaml": "^2.8.2",
|
|
51
|
-
"zod": "^4.
|
|
78
|
+
"zod": "^4.3.4",
|
|
79
|
+
"zod-package-json": "^2.1.0",
|
|
80
|
+
"zod-validation-error": "^5.0.0"
|
|
52
81
|
},
|
|
53
82
|
"devDependencies": {
|
|
83
|
+
"@types/archiver": "^7.0.0",
|
|
54
84
|
"@types/image-size": "^0.8.0",
|
|
55
85
|
"@types/marked": "^6.0.0",
|
|
56
86
|
"@types/marked-terminal": "^6.1.1",
|
|
57
87
|
"@types/node": "^25.0.3",
|
|
58
88
|
"@types/ora": "^3.2.0",
|
|
59
|
-
"@types/
|
|
89
|
+
"@types/semver": "^7.7.1"
|
|
60
90
|
},
|
|
61
91
|
"peerDependencies": {
|
|
62
92
|
"typescript": "^5.9.3"
|
|
93
|
+
},
|
|
94
|
+
"prettier": {
|
|
95
|
+
"semi": false,
|
|
96
|
+
"singleQuote": true,
|
|
97
|
+
"trailingComma": "all",
|
|
98
|
+
"tabWidth": 4,
|
|
99
|
+
"useTabs": false,
|
|
100
|
+
"arrowParens": "always",
|
|
101
|
+
"printWidth": 120
|
|
63
102
|
}
|
|
64
103
|
}
|
package/toolkit/about.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Command } from '@commander-js/extra-typings'
|
|
2
|
+
import chalk from 'chalk'
|
|
3
|
+
import { nothing, projectDir, readJson } from '../lib/utils.ts'
|
|
4
|
+
import { join } from 'path'
|
|
5
|
+
import { PackageJson } from 'zod-package-json'
|
|
6
|
+
import tui from '../lib/tui.ts'
|
|
7
|
+
|
|
8
|
+
const packageJson = PackageJson.parse(await readJson(join(projectDir(), 'package.json')))
|
|
9
|
+
|
|
10
|
+
export const aboutCmd = new Command('about')
|
|
11
|
+
.description('Get information about jutge-toolkit')
|
|
12
|
+
|
|
13
|
+
.action(async () => {
|
|
14
|
+
await nothing()
|
|
15
|
+
tui.print(chalk.bold(`jutge-toolkit ${packageJson.version}`))
|
|
16
|
+
tui.print(packageJson.description!)
|
|
17
|
+
tui.print('')
|
|
18
|
+
tui.url(packageJson.homepage!)
|
|
19
|
+
tui.print('')
|
|
20
|
+
tui.print('Author:')
|
|
21
|
+
showperson(packageJson.author!)
|
|
22
|
+
tui.print('')
|
|
23
|
+
tui.print('Contributors:')
|
|
24
|
+
for (const contributor of packageJson.contributors!) {
|
|
25
|
+
showperson(contributor)
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
function showperson(person: string | { name: string; email?: string; url?: string }) {
|
|
30
|
+
let line = ' - '
|
|
31
|
+
if (typeof person === 'string') {
|
|
32
|
+
line += person
|
|
33
|
+
} else {
|
|
34
|
+
line += person.name
|
|
35
|
+
if (person.email) {
|
|
36
|
+
line += ` <${tui.link('mailto://' + person.email, person.email)}>`
|
|
37
|
+
}
|
|
38
|
+
if (person.url) {
|
|
39
|
+
line += ` (${tui.link(person.url)})`
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
tui.print(line)
|
|
43
|
+
}
|
package/toolkit/ai.ts
CHANGED
|
@@ -1,30 +1,56 @@
|
|
|
1
1
|
import { Command } from '@commander-js/extra-typings'
|
|
2
|
-
import
|
|
2
|
+
import sharp from 'sharp'
|
|
3
|
+
import z from 'zod'
|
|
4
|
+
import { complete, generateImage, listModels } from '../lib/ai.ts'
|
|
5
|
+
import { settings } from '../lib/settings.ts'
|
|
6
|
+
import tui from '../lib/tui.ts'
|
|
7
|
+
import { convertStringToItsType } from '../lib/utils.ts'
|
|
3
8
|
|
|
4
|
-
export const
|
|
9
|
+
export const aiCmd = new Command('ai')
|
|
10
|
+
.description('Query AI models')
|
|
5
11
|
|
|
6
|
-
|
|
12
|
+
.action(() => {
|
|
13
|
+
aiCmd.help()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
aiCmd
|
|
17
|
+
.command('models')
|
|
18
|
+
.description('Show available AI models')
|
|
19
|
+
|
|
20
|
+
.action(async () => {
|
|
21
|
+
const models = await listModels()
|
|
22
|
+
tui.yaml(models)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
aiCmd
|
|
26
|
+
.command('complete')
|
|
7
27
|
.description('Complete a prompt using an AI model')
|
|
8
28
|
|
|
9
|
-
.argument('prompt', 'the user prompt to complete')
|
|
29
|
+
.argument('<prompt>', 'the user prompt to complete')
|
|
10
30
|
.option('-s, --system-prompt <system>', 'the system prompt to use', 'You are a helpful assistant.')
|
|
11
|
-
.option(
|
|
12
|
-
'-m, --model <model>',
|
|
13
|
-
'the AI model to use (eg: openai/gpt-5, google/gemini-2.5-pro, ...)',
|
|
14
|
-
'google/gemini-2.5-flash-lite',
|
|
15
|
-
)
|
|
31
|
+
.option('-m, --model <model>', 'the AI model to use', settings.defaultModel)
|
|
16
32
|
|
|
17
33
|
.action(async (prompt, { model, systemPrompt }) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
prompt = prompt.trim()
|
|
35
|
+
systemPrompt = systemPrompt.trim()
|
|
21
36
|
const answer = await complete(model, systemPrompt, prompt)
|
|
22
|
-
|
|
37
|
+
tui.print(answer)
|
|
23
38
|
})
|
|
24
39
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
// TODO: generate with different aspect ratios
|
|
41
|
+
aiCmd
|
|
42
|
+
.command('image')
|
|
43
|
+
.description('Generate a square image using an AI model')
|
|
44
|
+
|
|
45
|
+
.argument('<prompt>', 'description of the image to generate')
|
|
46
|
+
.option('-m, --model <model>', 'the graphic AI model to use', 'openai/dall-e-3')
|
|
47
|
+
.option('-s, --size <size>', 'the size of the image (in pixels)', '1024')
|
|
48
|
+
.option('-o, --output <path>', 'the output image path', 'image.png')
|
|
49
|
+
|
|
50
|
+
.action(async (prompt, { model, size, output }) => {
|
|
51
|
+
const sizeInt = z.int().min(16).max(2048).parse(convertStringToItsType(size))
|
|
52
|
+
const image = await generateImage(model, prompt)
|
|
53
|
+
await sharp(image).resize(sizeInt, sizeInt).toFile(output)
|
|
54
|
+
tui.success(`Generated image saved to ${output}`)
|
|
55
|
+
await tui.image(output, 20, 10)
|
|
30
56
|
})
|
package/toolkit/check.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@commander-js/extra-typings'
|
|
2
|
+
import { newMaker } from '../lib/maker'
|
|
3
|
+
|
|
4
|
+
export const checkCmd = new Command('check')
|
|
5
|
+
.alias('verify')
|
|
6
|
+
.description('Check candidate programs')
|
|
7
|
+
|
|
8
|
+
.argument('<programs...>', 'source programs to check')
|
|
9
|
+
.option('-d, --directory <path>', 'problem directory', '.')
|
|
10
|
+
|
|
11
|
+
.action(async (programs, { directory }) => {
|
|
12
|
+
const maker = await newMaker(directory)
|
|
13
|
+
for (const program of programs) {
|
|
14
|
+
await maker.checkCandidate(program)
|
|
15
|
+
}
|
|
16
|
+
})
|
package/toolkit/clean.ts
CHANGED
|
@@ -1,37 +1,27 @@
|
|
|
1
|
-
import { cleanFiles } from '../lib/cleaner'
|
|
2
|
-
import tui from '../lib/tui'
|
|
3
1
|
import { Command, Option } from '@commander-js/extra-typings'
|
|
4
|
-
import {
|
|
2
|
+
import { cleanDirectory } from '../lib/cleaner'
|
|
3
|
+
import tui from '../lib/tui'
|
|
4
|
+
import { findRealDirectories } from '../lib/helpers'
|
|
5
|
+
|
|
6
|
+
// TODO: usefindRealDirectories from lib/helpers.ts
|
|
5
7
|
|
|
6
|
-
export const
|
|
8
|
+
export const cleanCmd = new Command('clean')
|
|
7
9
|
.description('Clean generated files')
|
|
8
10
|
|
|
9
|
-
.
|
|
10
|
-
.option('-
|
|
11
|
+
.option('-d, --directories <directories...>', 'problem directories', ['.'])
|
|
12
|
+
.option('-a, --all', 'clean all generated files (including generated statement and correct files', false)
|
|
11
13
|
.addOption(new Option('-f, --force', 'force removal').conflicts('dryRun'))
|
|
12
14
|
.addOption(new Option('-n, --dry-run', 'show but do not remove files').conflicts('force'))
|
|
13
15
|
|
|
14
|
-
.action(async (directories,
|
|
15
|
-
//
|
|
16
|
-
const isForce = force || false
|
|
17
|
-
await tui.section('Cleaning generated files', async () => {
|
|
18
|
-
for (const directory of directories) {
|
|
19
|
-
try {
|
|
20
|
-
await tui.section(
|
|
21
|
-
`Cleaning directory ${tui.hyperlink(directory, resolve(directory))}`,
|
|
22
|
-
async () => {
|
|
23
|
-
await cleanFiles(isForce, directory)
|
|
24
|
-
},
|
|
25
|
-
)
|
|
26
|
-
} catch (error) {
|
|
27
|
-
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
16
|
+
.action(async ({ directories, all, force, dryRun }) => {
|
|
17
|
+
const isForce = force || false // default to dry-run if neither option is specified
|
|
28
18
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
19
|
+
await tui.section(`Cleaning generated files`, async () => {
|
|
20
|
+
const realDirectories = await findRealDirectories(directories)
|
|
21
|
+
for (const directory of realDirectories) {
|
|
22
|
+
await tui.section(`Cleaning directory ${tui.hyperlink(directory)}`, async () => {
|
|
23
|
+
await cleanDirectory(isForce, all, directory)
|
|
24
|
+
})
|
|
35
25
|
}
|
|
36
26
|
})
|
|
37
27
|
})
|
package/toolkit/compilers.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { getAvailableCompilers, getCompilersInfo, getDefinedCompilerIds } from '../lib/compilers'
|
|
2
2
|
import { Command } from '@commander-js/extra-typings'
|
|
3
3
|
|
|
4
|
-
export const
|
|
4
|
+
export const compilersCmd = new Command('compilers')
|
|
5
5
|
.description('Query compiler information')
|
|
6
|
-
// default action is to list all compilers
|
|
6
|
+
// default action is to list all compilers because of older compatibility
|
|
7
7
|
|
|
8
8
|
.action(async () => {
|
|
9
9
|
const info = await getCompilersInfo()
|
|
10
10
|
console.dir(info)
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
compilersCmd
|
|
14
14
|
.command('list-defined')
|
|
15
15
|
.description('List all defined compiler names')
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@ compilers
|
|
|
19
19
|
console.dir(items)
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
compilersCmd
|
|
23
23
|
.command('list-available')
|
|
24
24
|
.description('List all available compiler names')
|
|
25
25
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Command } from '@commander-js/extra-typings'
|
|
2
|
+
import { confirm } from '@inquirer/prompts'
|
|
3
|
+
import { editor } from '@inquirer/prompts'
|
|
4
|
+
import YAML from 'yaml'
|
|
5
|
+
import { ZodError } from 'zod'
|
|
6
|
+
import { fromError } from 'zod-validation-error'
|
|
7
|
+
import { configPath, loadSettings, saveSettings, settings } from '../lib/settings'
|
|
8
|
+
import { Settings } from '../lib/types.ts'
|
|
9
|
+
import tui from '../lib/tui.ts'
|
|
10
|
+
import { convertStringToItsType } from '../lib/utils.ts'
|
|
11
|
+
|
|
12
|
+
export const configCmd = new Command('config')
|
|
13
|
+
.summary('Manage configuration')
|
|
14
|
+
.description(
|
|
15
|
+
`Manage configuration
|
|
16
|
+
|
|
17
|
+
The actual configuration file is stored at ${configPath()}`,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
.action(() => {
|
|
21
|
+
configCmd.help()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
configCmd
|
|
25
|
+
.command('show')
|
|
26
|
+
.alias('list')
|
|
27
|
+
.description('Show configuration options')
|
|
28
|
+
|
|
29
|
+
.action(async () => {
|
|
30
|
+
const settings = await loadSettings()
|
|
31
|
+
tui.yaml(settings)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
configCmd
|
|
35
|
+
.command('get <key>')
|
|
36
|
+
.description('Get the value of a configuration option')
|
|
37
|
+
|
|
38
|
+
.action((key: string) => {
|
|
39
|
+
if (!(key in settings)) {
|
|
40
|
+
throw new Error(`Configuration key ${key} does not exist`)
|
|
41
|
+
}
|
|
42
|
+
console.log((settings as any)[key])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
configCmd
|
|
46
|
+
.command('set <key> <value>')
|
|
47
|
+
.description('Set the value of a configuration option')
|
|
48
|
+
|
|
49
|
+
.action(async (key: string, value: string) => {
|
|
50
|
+
if (!(key in settings)) {
|
|
51
|
+
throw new Error(`Configuration key ${key} does not exist`)
|
|
52
|
+
}
|
|
53
|
+
const convertedValue = convertStringToItsType(value)
|
|
54
|
+
const newSettings = Settings.parse({ ...settings, [key]: convertedValue })
|
|
55
|
+
await saveSettings(newSettings)
|
|
56
|
+
tui.success(`Configuration key ${key} updated successfully`)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
configCmd
|
|
60
|
+
.command('edit')
|
|
61
|
+
.description('Open an editor (uses $EDITOR or $VISUAL) to modify the configuration options')
|
|
62
|
+
|
|
63
|
+
.action(async () => {
|
|
64
|
+
let data = YAML.stringify(settings, null, 4)
|
|
65
|
+
while (true) {
|
|
66
|
+
const newData = await editor({
|
|
67
|
+
message: 'Edit configuration',
|
|
68
|
+
default: data,
|
|
69
|
+
postfix: '.yml',
|
|
70
|
+
waitForUserInput: false,
|
|
71
|
+
})
|
|
72
|
+
try {
|
|
73
|
+
const newSettings = Settings.parse(YAML.parse(newData))
|
|
74
|
+
await saveSettings(newSettings)
|
|
75
|
+
tui.success('Configuration options updated successfully')
|
|
76
|
+
return
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (error instanceof ZodError) {
|
|
79
|
+
console.error(fromError(error).toString())
|
|
80
|
+
} else {
|
|
81
|
+
console.error(error)
|
|
82
|
+
}
|
|
83
|
+
const again = await confirm({ message: 'Edit again?', default: true })
|
|
84
|
+
if (!again) {
|
|
85
|
+
tui.warning('No changes made to the configuration options')
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
data = newData
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
})
|
package/toolkit/create.ts
CHANGED
|
@@ -1,65 +1,37 @@
|
|
|
1
|
-
import tui from '../lib/tui'
|
|
2
1
|
import { Command } from '@commander-js/extra-typings'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { createProblemWithJutgeAI } from './create-jutge-ai'
|
|
7
|
-
import { createProblemWithTemplate } from './create-template'
|
|
8
|
-
import { createProblemWithWizard } from './create-wizard'
|
|
2
|
+
import { createProblemWithJutgeAI } from '../lib/create-with-jutgeai'
|
|
3
|
+
import { createProblemWithTemplate } from '../lib/create-with-template'
|
|
4
|
+
import { settings } from '../lib/settings'
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{ name: 'Use JutgeAI', value: 'jutgeAI' },
|
|
17
|
-
],
|
|
6
|
+
export const createCmd = new Command('create')
|
|
7
|
+
.alias('new')
|
|
8
|
+
.description('Create a new problem')
|
|
9
|
+
|
|
10
|
+
.action(() => {
|
|
11
|
+
createCmd.help()
|
|
18
12
|
})
|
|
19
|
-
}
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
dir = await input({
|
|
25
|
-
message: 'Output directory for the new problem:',
|
|
26
|
-
default: dir,
|
|
27
|
-
})
|
|
28
|
-
dir = normalize(dir)
|
|
29
|
-
if (await exists(dir)) {
|
|
30
|
-
tui.error(`Directory ${dir} already exists.`)
|
|
31
|
-
const remove = await confirm({
|
|
32
|
-
message: 'Remove it?',
|
|
33
|
-
default: false,
|
|
34
|
-
})
|
|
35
|
-
if (!remove) continue
|
|
36
|
-
tui.action(`Removing directory ${dir}`)
|
|
37
|
-
await rm(dir, { recursive: true, force: true })
|
|
38
|
-
tui.success(`Removed directory ${dir}`)
|
|
39
|
-
}
|
|
40
|
-
if (!dir.endsWith('.pbm')) {
|
|
41
|
-
tui.warning("The output directory must end with the '.pbm' extension. Please try again.")
|
|
42
|
-
dir += '.pbm'
|
|
43
|
-
continue
|
|
44
|
-
}
|
|
45
|
-
await mkdir(dir, { recursive: true })
|
|
46
|
-
tui.success(`Created directory ${dir}`)
|
|
47
|
-
return dir
|
|
48
|
-
}
|
|
49
|
-
}
|
|
14
|
+
createCmd
|
|
15
|
+
.command('with-template')
|
|
16
|
+
.description('Create a problem with a template')
|
|
50
17
|
|
|
51
|
-
|
|
52
|
-
.
|
|
18
|
+
.argument('[template]', 'template to use (empty to interactive selection)')
|
|
19
|
+
.option('-d, --directory <path>', 'output directory', 'new-problem.pbm')
|
|
20
|
+
|
|
21
|
+
.action(async (template, { directory }) => {
|
|
22
|
+
await createProblemWithTemplate(directory, template)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
createCmd
|
|
26
|
+
.command('with-ai')
|
|
27
|
+
.description('Create a problem with JutgeAI')
|
|
28
|
+
|
|
29
|
+
.option('-d, --directory <path>', 'output directory', 'new-problem.pbm')
|
|
30
|
+
.option('-i, --input <path>', 'input specification file')
|
|
31
|
+
.option('-o, --output <path>', 'output specification file')
|
|
32
|
+
.option('-n, --do-not-ask', 'do not ask interactively if --input given', false)
|
|
33
|
+
.option('-m, --model <model>', 'AI model to use', settings.defaultModel)
|
|
53
34
|
|
|
54
|
-
.action(async () => {
|
|
55
|
-
|
|
56
|
-
const outputDir = await selectOutputDir()
|
|
57
|
-
const method = await selectMethod()
|
|
58
|
-
if (method === 'template') {
|
|
59
|
-
await createProblemWithTemplate(outputDir)
|
|
60
|
-
} else if (method === 'wizard') {
|
|
61
|
-
await createProblemWithWizard(outputDir)
|
|
62
|
-
} else if (method === 'jutgeAI') {
|
|
63
|
-
await createProblemWithJutgeAI(outputDir)
|
|
64
|
-
}
|
|
35
|
+
.action(async ({ input, output, directory, model, doNotAsk }) => {
|
|
36
|
+
await createProblemWithJutgeAI(model, directory, input, output, doNotAsk)
|
|
65
37
|
})
|
package/toolkit/doctor.ts
CHANGED
|
@@ -2,17 +2,21 @@ import * as doc from '../lib/doctor'
|
|
|
2
2
|
import { Command } from '@commander-js/extra-typings'
|
|
3
3
|
import tui from '../lib/tui'
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
.description('Diagnose
|
|
5
|
+
export const doctorCmd = new Command('doctor')
|
|
6
|
+
.description('Diagnose status of the environment')
|
|
7
7
|
|
|
8
8
|
.action(async () => {
|
|
9
|
-
tui.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
await tui.section('Perform checks', async () => {
|
|
10
|
+
await tui.section('Checking Python3 installation', doc.checkPython3)
|
|
11
|
+
await tui.section('Checking C/C++ installation', doc.checkGCC)
|
|
12
|
+
await tui.section('Checking Haskell installation', doc.checkHaskell)
|
|
13
|
+
await tui.section('Checking Clojure installation', doc.checkClojure)
|
|
14
|
+
await tui.section('Checking Java installation', doc.checkJava)
|
|
15
|
+
await tui.section('Checking Rust installation', doc.checkRust)
|
|
16
|
+
await tui.section('Checking XeLaTeX installation', doc.checkXeLaTeX)
|
|
17
|
+
await tui.section('Checking Pandoc installation', doc.checkPandoc)
|
|
18
|
+
await tui.section('Checking ImageMagick installation', doc.checkImageMagick)
|
|
19
|
+
await tui.section('Checking AI models', doc.checkAIEnvVars)
|
|
20
|
+
await tui.section('Checking terminal', doc.checkTerminal)
|
|
21
|
+
})
|
|
18
22
|
})
|