@jutge.org/toolkit 4.4.9 → 4.4.16

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.
Files changed (23) hide show
  1. package/assets/prompts/funcs/creators/create-solution.tpl.txt +23 -0
  2. package/assets/prompts/funcs/creators/create-statement.tpl.txt +28 -0
  3. package/assets/prompts/funcs/creators/private-test-cases.tpl.txt +12 -0
  4. package/assets/prompts/funcs/creators/sample-test-cases.tpl.txt +16 -0
  5. package/assets/prompts/funcs/creators/sample.dt.tpl.txt +15 -0
  6. package/assets/prompts/funcs/examples/statement.tex +23 -0
  7. package/assets/prompts/funcs/proglangs/py.md +9 -0
  8. package/assets/prompts/io/examples/statement-coda.tex +7 -0
  9. package/dist/index.js +702 -466
  10. package/package.json +14 -11
  11. package/toolkit/generate.ts +73 -7
  12. /package/assets/prompts/{examples → funcs/examples}/statement-coda.tex +0 -0
  13. /package/assets/prompts/{creators → io/creators}/create-solution.tpl.txt +0 -0
  14. /package/assets/prompts/{creators → io/creators}/create-statement.tpl.txt +0 -0
  15. /package/assets/prompts/{creators → io/creators}/create-translation.tpl.txt +0 -0
  16. /package/assets/prompts/{creators → io/creators}/private-test-cases.txt +0 -0
  17. /package/assets/prompts/{creators → io/creators}/sample-test-cases.txt +0 -0
  18. /package/assets/prompts/{examples → io/examples}/statement.tex +0 -0
  19. /package/assets/prompts/{generators → io/generators}/efficiency.md +0 -0
  20. /package/assets/prompts/{generators → io/generators}/hard.md +0 -0
  21. /package/assets/prompts/{generators → io/generators}/random.md +0 -0
  22. /package/assets/prompts/{proglangs → io/proglangs}/cc.md +0 -0
  23. /package/assets/prompts/{proglangs → io/proglangs}/py.md +0 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jutge.org/toolkit",
3
3
  "description": "Toolkit to prepare problems for Jutge.org",
4
- "version": "4.4.9",
4
+ "version": "4.4.16",
5
5
  "homepage": "https://jutge.org",
6
6
  "author": {
7
7
  "name": "Jutge.org",
@@ -61,31 +61,33 @@
61
61
  ],
62
62
  "dependencies": {
63
63
  "@commander-js/extra-typings": "^14.0.0",
64
- "@dicebear/collection": "^9.3.1",
65
- "@dicebear/core": "^9.3.1",
66
- "@eslint/js": "^9.39.2",
67
- "@inquirer/prompts": "^8.2.0",
64
+ "@dicebear/collection": "^9.3.2",
65
+ "@dicebear/core": "^9.3.2",
66
+ "@eslint/js": "^10.0.1",
67
+ "@inquirer/prompts": "^8.3.0",
68
68
  "adm-zip": "^0.5.16",
69
69
  "archiver": "^7.0.1",
70
70
  "boxen": "^8.0.1",
71
- "bun-types": "^1.3.7",
71
+ "bun-types": "^1.3.9",
72
72
  "chalk": "^5.6.2",
73
73
  "chokidar": "^5.0.0",
74
74
  "cli-highlight": "^2.1.11",
75
- "commander": "^14.0.2",
75
+ "commander": "^14.0.3",
76
76
  "dayjs": "^1.11.19",
77
77
  "env-paths": "^4.0.0",
78
- "eslint": "^9.39.2",
78
+ "eslint": "^10.0.2",
79
79
  "execa": "^9.6.1",
80
80
  "handlebars": "^4.7.8",
81
81
  "image-size": "^2.0.2",
82
82
  "inquirer-checkbox-plus-plus": "^1.1.1",
83
+ "marked": "^17.0.3",
84
+ "marked-terminal": "^7.3.0",
83
85
  "nanoid": "^5.1.6",
84
86
  "open": "^11.0.0",
85
87
  "pretty-bytes": "^7.1.0",
86
88
  "pretty-ms": "^9.3.0",
87
89
  "radash": "^12.1.1",
88
- "semver": "^7.7.3",
90
+ "semver": "^7.7.4",
89
91
  "sharp": "^0.34.5",
90
92
  "terminal-link": "^5.0.0",
91
93
  "tree-node-cli": "^1.6.0",
@@ -98,10 +100,11 @@
98
100
  "@types/adm-zip": "^0.5.0",
99
101
  "@types/archiver": "^7.0.0",
100
102
  "@types/image-size": "^0.8.0",
101
- "@types/node": "^25.1.0",
103
+ "@types/marked-terminal": "^6.1.1",
104
+ "@types/node": "^25.3.0",
102
105
  "@types/semver": "^7.7.1",
103
106
  "prettier": "^3.8.1",
104
- "typescript-eslint": "^8.54.0"
107
+ "typescript-eslint": "^8.56.1"
105
108
  },
106
109
  "peerDependencies": {
107
110
  "typescript": "^5.9.3"
@@ -1,8 +1,10 @@
1
- import { Argument, Command } from '@commander-js/extra-typings'
1
+ import { Argument, Command, Option } from '@commander-js/extra-typings'
2
+ import { exists } from 'fs/promises'
2
3
  import { join } from 'path'
3
4
  import sharp from 'sharp'
4
- import { createProblemWithJutgeAI } from '../lib/create-with-jutgeai'
5
5
  import { complete } from '../lib/aiclient'
6
+ import { createFuncsProblem } from '../lib/create-funcs'
7
+ import { createIOProblem } from '../lib/create-io'
6
8
  import { languageKeys, languageNames, proglangKeys, proglangNames } from '../lib/data'
7
9
  import {
8
10
  addAlternativeSolution,
@@ -11,11 +13,11 @@ import {
11
13
  generateStatementFromSolution,
12
14
  generateTestCasesGenerator,
13
15
  } from '../lib/generate'
16
+ import { getLoggedInJutgeClient } from '../lib/login'
14
17
  import { newProblem } from '../lib/problem'
15
18
  import { settings } from '../lib/settings'
16
19
  import tui from '../lib/tui'
17
20
  import { writeText } from '../lib/utils'
18
- import { getLoggedInJutgeClient } from '../lib/login'
19
21
 
20
22
  export const generateCmd = new Command('generate')
21
23
  .description('Generate problem elements using JutgeAI')
@@ -28,16 +30,80 @@ generateCmd
28
30
  .command('problem')
29
31
  .description('Generate a problem with JutgeAI')
30
32
 
33
+ .summary(`Generate a problem with JutgeAI
34
+
35
+ Use this command to generate a problem with JutgeAI from a specification.
36
+
37
+ There are currently two types of problems that can be generated:
38
+
39
+ - io: The problem consists of reading input from standard input and writing output to standard output.
40
+
41
+ Current implementation supports C, C++, Python, Haskell, Java, Rust, R and Clojure programming languages.
42
+
43
+ The following items will be generated:
44
+ - problem statement in original language
45
+ - sample test cases
46
+ - private test cases
47
+ - golden solution
48
+ - translations of the problem statement into other languages
49
+ - alternative solutions in other programming languages
50
+ - test cases generators
51
+ - a README.md file describing the problem and LLM usage
52
+
53
+ - funcs: The problem consists of implementing one or more functions.
54
+
55
+ Current implementation supports Python, Haskell and Clojure programming languages (through RunPython, RunHaskell and RunClojure compilers).
56
+
57
+ The following items will be generated:
58
+ - problem statement in original language
59
+ - translations of the problem statement into other languages
60
+ - generate sample.dt for Python
61
+ - sample test cases
62
+ - private test cases for each function
63
+ - golden solution
64
+ - alternative solutions in other programming languages
65
+ - scores.yml file with the scores for each function (if there is more than one function)
66
+ - a README.md file describing the problem and LLM usage
67
+
68
+ Problem generation needs a problem specification:
69
+ - If --input is provided, the system will read the given input specification file.
70
+ - If --output is provided, the system will write the problem specification to the given output specification file.
71
+ - The system will ask interactively for the problem specification (using the values in the --input specification file if provided as defaults)
72
+ - unless the --do-not-ask flag is given.
73
+
74
+ Treat the generated problem as a starting draft. You should edit the problem directory manually after the generation.
75
+ `)
76
+
77
+ .addOption(
78
+ new Option
79
+ ('-k, --kind <kind>', 'problem kind')
80
+ .default('io')
81
+ .choices(['io', 'funcs'])
82
+ )
31
83
  .option('-d, --directory <path>', 'output directory', 'new-problem.pbm')
32
84
  .option('-i, --input <path>', 'input specification file')
33
85
  .option('-o, --output <path>', 'output specification file')
34
86
  .option('-n, --do-not-ask', 'do not ask interactively if --input given', false)
35
87
  .option('-m, --model <model>', 'AI model to use', settings.defaultModel)
36
88
 
37
- .action(async ({ input, output, directory, model, doNotAsk }) => {
89
+ .action(async ({ input, output, directory, model, doNotAsk, kind }) => {
38
90
  const jutge = await getLoggedInJutgeClient()
39
- await tui.section('Generating problem with JutgeAI', async () => {
40
- await createProblemWithJutgeAI(jutge, model, directory, input, output, doNotAsk)
91
+ await tui.section(`Generating ${kind} problem with JutgeAI`, async () => {
92
+
93
+ if (await exists(directory)) {
94
+ throw new Error(`Directory ${directory} already exists`)
95
+ }
96
+ if (!directory.endsWith('.pbm')) {
97
+ throw new Error('The output directory must end with .pbm')
98
+ }
99
+
100
+ if (kind === 'io') {
101
+ await createIOProblem(jutge, model, directory, input, output, doNotAsk)
102
+ } else if (kind === 'funcs') {
103
+ await createFuncsProblem(jutge, model, directory, input, output, doNotAsk)
104
+ } else {
105
+ throw new Error(`Invalid problem kind: ${kind as string}`)
106
+ }
41
107
  })
42
108
  })
43
109
 
@@ -211,7 +277,7 @@ The new image will be saved as award.png in the problem directory, overriding an
211
277
  .action(async (prompt, { directory, model }) => {
212
278
  const jutge = await getLoggedInJutgeClient()
213
279
  const output = join(directory, 'award.png')
214
- const problem = await newProblem(directory)
280
+ await newProblem(directory)
215
281
  let imagePrompt = prompt.trim()
216
282
  if (imagePrompt === '') {
217
283
  imagePrompt = 'A colorful award on a white background'