@exercode/problem-utils 1.17.8 → 1.18.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.
Files changed (85) hide show
  1. package/README.md +1 -1
  2. package/dist/_virtual/_rolldown/runtime.cjs +1 -1
  3. package/dist/helpers/checkProblemDirIsolation.cjs +1 -1
  4. package/dist/helpers/checkProblemDirIsolation.js +1 -1
  5. package/dist/helpers/checkProblemDirIsolation.js.map +1 -1
  6. package/dist/helpers/cleanWorkingDirectory.cjs +1 -1
  7. package/dist/helpers/cleanWorkingDirectory.cjs.map +1 -1
  8. package/dist/helpers/cleanWorkingDirectory.d.ts +6 -2
  9. package/dist/helpers/cleanWorkingDirectory.js +1 -1
  10. package/dist/helpers/cleanWorkingDirectory.js.map +1 -1
  11. package/dist/helpers/copyTestCaseFileInput.cjs +1 -1
  12. package/dist/helpers/copyTestCaseFileInput.cjs.map +1 -1
  13. package/dist/helpers/copyTestCaseFileInput.js +1 -1
  14. package/dist/helpers/copyTestCaseFileInput.js.map +1 -1
  15. package/dist/helpers/judgeByStaticAnalysis.cjs +1 -1
  16. package/dist/helpers/judgeByStaticAnalysis.js +1 -1
  17. package/dist/helpers/readOutputFiles.cjs +1 -1
  18. package/dist/helpers/readOutputFiles.cjs.map +1 -1
  19. package/dist/helpers/readOutputFiles.d.ts +9 -0
  20. package/dist/helpers/readOutputFiles.js +1 -1
  21. package/dist/helpers/readOutputFiles.js.map +1 -1
  22. package/dist/helpers/readProblemMarkdownFrontMatter.cjs +1 -1
  23. package/dist/helpers/readProblemMarkdownFrontMatter.cjs.map +1 -1
  24. package/dist/helpers/readProblemMarkdownFrontMatter.js +1 -1
  25. package/dist/helpers/readProblemMarkdownFrontMatter.js.map +1 -1
  26. package/dist/helpers/readTestCases.cjs +1 -1
  27. package/dist/helpers/readTestCases.js +1 -1
  28. package/dist/helpers/resolveCwds.cjs +1 -1
  29. package/dist/helpers/resolveCwds.cjs.map +1 -1
  30. package/dist/helpers/resolveCwds.js +1 -1
  31. package/dist/helpers/resolveCwds.js.map +1 -1
  32. package/dist/helpers/runCommandInTemporaryPackageManagerProject.cjs +1 -1
  33. package/dist/helpers/runCommandInTemporaryPackageManagerProject.cjs.map +1 -1
  34. package/dist/helpers/runCommandInTemporaryPackageManagerProject.d.ts +3 -0
  35. package/dist/helpers/runCommandInTemporaryPackageManagerProject.js +1 -1
  36. package/dist/helpers/runCommandInTemporaryPackageManagerProject.js.map +1 -1
  37. package/dist/helpers/runCustomRunner.cjs +2 -0
  38. package/dist/helpers/runCustomRunner.cjs.map +1 -0
  39. package/dist/helpers/runCustomRunner.d.ts +8 -0
  40. package/dist/helpers/runCustomRunner.js +2 -0
  41. package/dist/helpers/runCustomRunner.js.map +1 -0
  42. package/dist/helpers/safeFs.cjs +2 -0
  43. package/dist/helpers/safeFs.cjs.map +1 -0
  44. package/dist/helpers/safeFs.d.ts +29 -0
  45. package/dist/helpers/safeFs.js +2 -0
  46. package/dist/helpers/safeFs.js.map +1 -0
  47. package/dist/helpers/sandboxUser.cjs +2 -0
  48. package/dist/helpers/sandboxUser.cjs.map +1 -0
  49. package/dist/helpers/sandboxUser.d.ts +136 -0
  50. package/dist/helpers/sandboxUser.js +2 -0
  51. package/dist/helpers/sandboxUser.js.map +1 -0
  52. package/dist/helpers/spawnSyncWithTimeout.cjs +1 -1
  53. package/dist/helpers/spawnSyncWithTimeout.cjs.map +1 -1
  54. package/dist/helpers/spawnSyncWithTimeout.d.ts +7 -0
  55. package/dist/helpers/spawnSyncWithTimeout.js +1 -1
  56. package/dist/helpers/spawnSyncWithTimeout.js.map +1 -1
  57. package/dist/helpers/startHttpServer.cjs +1 -1
  58. package/dist/helpers/startHttpServer.cjs.map +1 -1
  59. package/dist/helpers/startHttpServer.js +1 -1
  60. package/dist/helpers/startHttpServer.js.map +1 -1
  61. package/dist/index.cjs +1 -1
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.js +1 -1
  64. package/dist/presets/command.cjs +1 -1
  65. package/dist/presets/command.cjs.map +1 -1
  66. package/dist/presets/command.d.ts +16 -0
  67. package/dist/presets/command.js +1 -1
  68. package/dist/presets/command.js.map +1 -1
  69. package/dist/presets/guiCommand.cjs +3 -3
  70. package/dist/presets/guiCommand.cjs.map +1 -1
  71. package/dist/presets/guiCommand.d.ts +24 -0
  72. package/dist/presets/guiCommand.js +3 -3
  73. package/dist/presets/guiCommand.js.map +1 -1
  74. package/dist/presets/llm.cjs +1 -1
  75. package/dist/presets/llm.cjs.map +1 -1
  76. package/dist/presets/llm.js +1 -1
  77. package/dist/presets/stdio.cjs +1 -1
  78. package/dist/presets/stdio.cjs.map +1 -1
  79. package/dist/presets/stdio.js +1 -1
  80. package/dist/presets/stdio.js.map +1 -1
  81. package/dist/types/language.cjs +2 -2
  82. package/dist/types/language.cjs.map +1 -1
  83. package/dist/types/language.js +2 -2
  84. package/dist/types/language.js.map +1 -1
  85. package/package.json +3 -3
package/README.md CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  [![Test](https://github.com/WillBooster/exercode-problem-utils/actions/workflows/test.yml/badge.svg)](https://github.com/WillBooster/exercode-problem-utils/actions/workflows/test.yml)
4
4
  [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
5
- [![wbfy](https://img.shields.io/badge/wbfy-12.5.2-1e90ff.svg)](https://github.com/WillBooster/shared/tree/main/packages/wbfy)
5
+ [![wbfy](https://img.shields.io/badge/wbfy-18.3.0-1e90ff.svg)](https://github.com/WillBooster/shared/tree/main/packages/wbfy)
6
6
 
7
7
  :100: A set of utilities for judging programs on Exercode (https://exercode.willbooster.com/).
@@ -1 +1 @@
1
- "use strict";var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));exports.__toESM=s;
1
+ "use strict";var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../types/testCaseResult.cjs"),n=require("../types/decisionCode.cjs"),r=require("./printDebugBanner.cjs");let i=require("node:child_process");i=e.__toESM(i,1);let a=require("node:os");a=e.__toESM(a,1);let o=require("node:path");o=e.__toESM(o,1);let s=require("node:fs");s=e.__toESM(s,1);async function c(e,t,n){let c;try{c=await s.default.promises.mkdtemp(o.default.join(a.default.tmpdir(),`problem-utils-isolation_`));let g=o.default.resolve(e),_=o.default.join(c,p(g));await s.default.promises.mkdir(o.default.dirname(_),{recursive:!0}),await s.default.promises.cp(g,_,{recursive:!0,filter:l}),await f(c,g);let v=o.default.relative(g,o.default.resolve(t.cwd)),y=o.default.join(_,v),b=m(g);if(b.startsWith(`..`)||o.default.isAbsolute(b))return r.printDebugBanner([`[DEBUG MODE] isolated problem directory check skipped`,``,`The invoked judge script is located outside the problem directory.`,`Script path: ${b}`]),{passed:!0};let x=process.execArgv.filter(u),S=JSON.stringify(d(n)?n:{}),C=i.default.spawnSync(process.execPath,[...x,b,y,S],{cwd:_,encoding:`utf8`,env:process.env,timeout:3e4}),w=C.stdout??``,T=C.stderr??``;return C.status===0&&h(w)?(r.printDebugBanner([`[DEBUG MODE] isolated problem directory check passed`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`]),{passed:!0}):(r.printDebugBanner([`[DEBUG MODE] isolated problem directory check failed`,``,`The judge did not complete successfully after copying only the problem directory to a temporary location.`,`Make sure judge.ts imports only files included in the problem directory.`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`,`Exit status : ${C.status??C.signal??`unknown`}`,`Spawn error : ${C.error?.message??`<none>`}`,``,`stdout:`,w.trimEnd()||`<empty>`,``,`stderr:`,T.trimEnd()||`<empty>`]),{passed:!1})}catch(e){return r.printDebugBanner([`[DEBUG MODE] isolated problem directory check failed due to an unexpected error`,``,e instanceof Error?e.message:String(e)]),{passed:!1}}finally{if(c)try{await s.default.promises.rm(c,{recursive:!0,force:!0})}catch{}}}function l(e){let t=o.default.basename(e);return t!==`node_modules`&&t!==`.git`}function u(e){return!e.startsWith(`--inspect`)&&!e.startsWith(`--watch`)&&!e.startsWith(`--hot`)}function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function f(e,t){let n=o.default.resolve(t);for(;;){let t=o.default.join(n,`node_modules`);if(s.default.existsSync(t)){let r=o.default.join(e,p(n),`node_modules`);try{await s.default.promises.symlink(t,r,process.platform===`win32`?`junction`:`dir`)}catch{}}let r=o.default.dirname(n);if(r===n)break;n=r}}function p(e){let{root:t}=o.default.parse(e);return o.default.relative(t,e)}function m(e){let t=process.argv[1];if(!t)return`.${o.default.sep}judge.ts`;let n=o.default.relative(e,o.default.resolve(t));return o.default.isAbsolute(n)||n.startsWith(`.`)?n:`.${o.default.sep}${n}`}function h(e){let r=e.split(/\r?\n/).filter(e=>e.startsWith(t.TEST_CASE_RESULT_PREFIX));return r.length!==0&&r.every(e=>{try{let r=t.testCaseResultSchema.safeParse(JSON.parse(e.slice(t.TEST_CASE_RESULT_PREFIX.length)));return r.success&&r.data.decisionCode===n.DecisionCode.ACCEPTED}catch{return!1}})}exports.checkProblemDirIsolation=c;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../types/testCaseResult.cjs"),n=require("../types/decisionCode.cjs"),r=require("./printDebugBanner.cjs");let i=require("node:child_process");i=e.__toESM(i,1);let a=require("node:fs");a=e.__toESM(a,1);let o=require("node:os");o=e.__toESM(o,1);let s=require("node:path");s=e.__toESM(s,1);async function c(e,t,n){let c;try{c=await a.default.promises.mkdtemp(s.default.join(o.default.tmpdir(),`problem-utils-isolation_`));let g=s.default.resolve(e),_=s.default.join(c,p(g));await a.default.promises.mkdir(s.default.dirname(_),{recursive:!0}),await a.default.promises.cp(g,_,{recursive:!0,filter:l}),await f(c,g);let v=s.default.relative(g,s.default.resolve(t.cwd)),y=s.default.join(_,v),b=m(g);if(b.startsWith(`..`)||s.default.isAbsolute(b))return r.printDebugBanner([`[DEBUG MODE] isolated problem directory check skipped`,``,`The invoked judge script is located outside the problem directory.`,`Script path: ${b}`]),{passed:!0};let x=process.execArgv.filter(u),S=JSON.stringify(d(n)?n:{}),C=i.default.spawnSync(process.execPath,[...x,b,y,S],{cwd:_,encoding:`utf8`,env:process.env,timeout:3e4}),w=C.stdout??``,T=C.stderr??``;return C.status===0&&h(w)?(r.printDebugBanner([`[DEBUG MODE] isolated problem directory check passed`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`]),{passed:!0}):(r.printDebugBanner([`[DEBUG MODE] isolated problem directory check failed`,``,`The judge did not complete successfully after copying only the problem directory to a temporary location.`,`Make sure judge.ts imports only files included in the problem directory.`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`,`Exit status : ${C.status??C.signal??`unknown`}`,`Spawn error : ${C.error?.message??`<none>`}`,``,`stdout:`,w.trimEnd()||`<empty>`,``,`stderr:`,T.trimEnd()||`<empty>`]),{passed:!1})}catch(e){return r.printDebugBanner([`[DEBUG MODE] isolated problem directory check failed due to an unexpected error`,``,e instanceof Error?e.message:String(e)]),{passed:!1}}finally{if(c)try{await a.default.promises.rm(c,{recursive:!0,force:!0})}catch{}}}function l(e){let t=s.default.basename(e);return t!==`node_modules`&&t!==`.git`}function u(e){return!e.startsWith(`--inspect`)&&!e.startsWith(`--watch`)&&!e.startsWith(`--hot`)}function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function f(e,t){let n=s.default.resolve(t);for(;;){let t=s.default.join(n,`node_modules`);if(a.default.existsSync(t)){let r=s.default.join(e,p(n),`node_modules`);try{await a.default.promises.symlink(t,r,process.platform===`win32`?`junction`:`dir`)}catch{}}let r=s.default.dirname(n);if(r===n)break;n=r}}function p(e){let{root:t}=s.default.parse(e);return s.default.relative(t,e)}function m(e){let t=process.argv[1];if(!t)return`.${s.default.sep}judge.ts`;let n=s.default.relative(e,s.default.resolve(t));return s.default.isAbsolute(n)||n.startsWith(`.`)?n:`.${s.default.sep}${n}`}function h(e){let r=e.split(/\r?\n/).filter(e=>e.startsWith(t.TEST_CASE_RESULT_PREFIX));return r.length!==0&&r.every(e=>{try{let r=t.testCaseResultSchema.safeParse(JSON.parse(e.slice(t.TEST_CASE_RESULT_PREFIX.length)));return r.success&&r.data.decisionCode===n.DecisionCode.ACCEPTED}catch{return!1}})}exports.checkProblemDirIsolation=c;
2
2
  //# sourceMappingURL=checkProblemDirIsolation.cjs.map
@@ -1,2 +1,2 @@
1
- import{TEST_CASE_RESULT_PREFIX as e,testCaseResultSchema as t}from"../types/testCaseResult.js";import{DecisionCode as n}from"../types/decisionCode.js";import{printDebugBanner as r}from"./printDebugBanner.js";import i from"node:child_process";import a from"node:os";import o from"node:path";import s from"node:fs";async function c(e,t,n){let c;try{c=await s.promises.mkdtemp(o.join(a.tmpdir(),`problem-utils-isolation_`));let g=o.resolve(e),_=o.join(c,p(g));await s.promises.mkdir(o.dirname(_),{recursive:!0}),await s.promises.cp(g,_,{recursive:!0,filter:l}),await f(c,g);let v=o.relative(g,o.resolve(t.cwd)),y=o.join(_,v),b=m(g);if(b.startsWith(`..`)||o.isAbsolute(b))return r([`[DEBUG MODE] isolated problem directory check skipped`,``,`The invoked judge script is located outside the problem directory.`,`Script path: ${b}`]),{passed:!0};let x=process.execArgv.filter(u),S=JSON.stringify(d(n)?n:{}),C=i.spawnSync(process.execPath,[...x,b,y,S],{cwd:_,encoding:`utf8`,env:process.env,timeout:3e4}),w=C.stdout??``,T=C.stderr??``;return C.status===0&&h(w)?(r([`[DEBUG MODE] isolated problem directory check passed`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`]),{passed:!0}):(r([`[DEBUG MODE] isolated problem directory check failed`,``,`The judge did not complete successfully after copying only the problem directory to a temporary location.`,`Make sure judge.ts imports only files included in the problem directory.`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`,`Exit status : ${C.status??C.signal??`unknown`}`,`Spawn error : ${C.error?.message??`<none>`}`,``,`stdout:`,w.trimEnd()||`<empty>`,``,`stderr:`,T.trimEnd()||`<empty>`]),{passed:!1})}catch(e){return r([`[DEBUG MODE] isolated problem directory check failed due to an unexpected error`,``,e instanceof Error?e.message:String(e)]),{passed:!1}}finally{if(c)try{await s.promises.rm(c,{recursive:!0,force:!0})}catch{}}}function l(e){let t=o.basename(e);return t!==`node_modules`&&t!==`.git`}function u(e){return!e.startsWith(`--inspect`)&&!e.startsWith(`--watch`)&&!e.startsWith(`--hot`)}function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function f(e,t){let n=o.resolve(t);for(;;){let t=o.join(n,`node_modules`);if(s.existsSync(t)){let r=o.join(e,p(n),`node_modules`);try{await s.promises.symlink(t,r,process.platform===`win32`?`junction`:`dir`)}catch{}}let r=o.dirname(n);if(r===n)break;n=r}}function p(e){let{root:t}=o.parse(e);return o.relative(t,e)}function m(e){let t=process.argv[1];if(!t)return`.${o.sep}judge.ts`;let n=o.relative(e,o.resolve(t));return o.isAbsolute(n)||n.startsWith(`.`)?n:`.${o.sep}${n}`}function h(r){let i=r.split(/\r?\n/).filter(t=>t.startsWith(e));return i.length!==0&&i.every(r=>{try{let i=t.safeParse(JSON.parse(r.slice(e.length)));return i.success&&i.data.decisionCode===n.ACCEPTED}catch{return!1}})}export{c as checkProblemDirIsolation};
1
+ import{TEST_CASE_RESULT_PREFIX as e,testCaseResultSchema as t}from"../types/testCaseResult.js";import{DecisionCode as n}from"../types/decisionCode.js";import{printDebugBanner as r}from"./printDebugBanner.js";import i from"node:child_process";import a from"node:fs";import o from"node:os";import s from"node:path";async function c(e,t,n){let c;try{c=await a.promises.mkdtemp(s.join(o.tmpdir(),`problem-utils-isolation_`));let g=s.resolve(e),_=s.join(c,p(g));await a.promises.mkdir(s.dirname(_),{recursive:!0}),await a.promises.cp(g,_,{recursive:!0,filter:l}),await f(c,g);let v=s.relative(g,s.resolve(t.cwd)),y=s.join(_,v),b=m(g);if(b.startsWith(`..`)||s.isAbsolute(b))return r([`[DEBUG MODE] isolated problem directory check skipped`,``,`The invoked judge script is located outside the problem directory.`,`Script path: ${b}`]),{passed:!0};let x=process.execArgv.filter(u),S=JSON.stringify(d(n)?n:{}),C=i.spawnSync(process.execPath,[...x,b,y,S],{cwd:_,encoding:`utf8`,env:process.env,timeout:3e4}),w=C.stdout??``,T=C.stderr??``;return C.status===0&&h(w)?(r([`[DEBUG MODE] isolated problem directory check passed`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`]),{passed:!0}):(r([`[DEBUG MODE] isolated problem directory check failed`,``,`The judge did not complete successfully after copying only the problem directory to a temporary location.`,`Make sure judge.ts imports only files included in the problem directory.`,``,`Copied problem dir : ${_}`,`Checked cwd : ${v}`,`Exit status : ${C.status??C.signal??`unknown`}`,`Spawn error : ${C.error?.message??`<none>`}`,``,`stdout:`,w.trimEnd()||`<empty>`,``,`stderr:`,T.trimEnd()||`<empty>`]),{passed:!1})}catch(e){return r([`[DEBUG MODE] isolated problem directory check failed due to an unexpected error`,``,e instanceof Error?e.message:String(e)]),{passed:!1}}finally{if(c)try{await a.promises.rm(c,{recursive:!0,force:!0})}catch{}}}function l(e){let t=s.basename(e);return t!==`node_modules`&&t!==`.git`}function u(e){return!e.startsWith(`--inspect`)&&!e.startsWith(`--watch`)&&!e.startsWith(`--hot`)}function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function f(e,t){let n=s.resolve(t);for(;;){let t=s.join(n,`node_modules`);if(a.existsSync(t)){let r=s.join(e,p(n),`node_modules`);try{await a.promises.symlink(t,r,process.platform===`win32`?`junction`:`dir`)}catch{}}let r=s.dirname(n);if(r===n)break;n=r}}function p(e){let{root:t}=s.parse(e);return s.relative(t,e)}function m(e){let t=process.argv[1];if(!t)return`.${s.sep}judge.ts`;let n=s.relative(e,s.resolve(t));return s.isAbsolute(n)||n.startsWith(`.`)?n:`.${s.sep}${n}`}function h(r){let i=r.split(/\r?\n/).filter(t=>t.startsWith(e));return i.length!==0&&i.every(r=>{try{let i=t.safeParse(JSON.parse(r.slice(e.length)));return i.success&&i.data.decisionCode===n.ACCEPTED}catch{return!1}})}export{c as checkProblemDirIsolation};
2
2
  //# sourceMappingURL=checkProblemDirIsolation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkProblemDirIsolation.js","names":["child_process"],"sources":["../../src/helpers/checkProblemDirIsolation.ts"],"sourcesContent":["import child_process from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { DecisionCode } from '../types/decisionCode.js';\nimport { TEST_CASE_RESULT_PREFIX, testCaseResultSchema } from '../types/testCaseResult.js';\n\nimport { printDebugBanner } from './printDebugBanner.js';\nimport type { ResolvedCwd } from './resolveCwds.js';\n\nconst ISOLATION_CHECK_TIMEOUT_MS = 30_000;\n\nexport interface ProblemDirIsolationCheckResult {\n passed: boolean;\n}\n\n/**\n * Check that a judge can run after only the problem directory is copied elsewhere.\n */\nexport async function checkProblemDirIsolation(\n problemDir: string,\n resolvedCwd: ResolvedCwd,\n params: unknown\n): Promise<ProblemDirIsolationCheckResult> {\n let tempRoot: string | undefined;\n try {\n tempRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'problem-utils-isolation_'));\n const absoluteProblemDir = path.resolve(problemDir);\n const copiedProblemDir = path.join(tempRoot, toTempRelativePath(absoluteProblemDir));\n await fs.promises.mkdir(path.dirname(copiedProblemDir), { recursive: true });\n await fs.promises.cp(absoluteProblemDir, copiedProblemDir, {\n recursive: true,\n filter: isCopiedProblemPath,\n });\n await symlinkAllAncestorNodeModules(tempRoot, absoluteProblemDir);\n\n const relativeCwd = path.relative(absoluteProblemDir, path.resolve(resolvedCwd.cwd));\n const copiedCwd = path.join(copiedProblemDir, relativeCwd);\n const scriptPath = getInvokedScriptPath(absoluteProblemDir);\n if (scriptPath.startsWith('..') || path.isAbsolute(scriptPath)) {\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check skipped',\n '',\n 'The invoked judge script is located outside the problem directory.',\n `Script path: ${scriptPath}`,\n ]);\n return { passed: true };\n }\n const execArgv = process.execArgv.filter(isIsolationExecArg);\n const paramsJson = JSON.stringify(isJudgeParamsObject(params) ? params : {});\n const spawnResult = child_process.spawnSync(process.execPath, [...execArgv, scriptPath, copiedCwd, paramsJson], {\n cwd: copiedProblemDir,\n encoding: 'utf8',\n env: process.env,\n timeout: ISOLATION_CHECK_TIMEOUT_MS,\n });\n const stdout = spawnResult.stdout ?? '';\n const stderr = spawnResult.stderr ?? '';\n\n if (spawnResult.status === 0 && isAcceptedJudgeOutput(stdout)) {\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check passed',\n '',\n `Copied problem dir : ${copiedProblemDir}`,\n `Checked cwd : ${relativeCwd}`,\n ]);\n return { passed: true };\n }\n\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check failed',\n '',\n 'The judge did not complete successfully after copying only the problem directory to a temporary location.',\n 'Make sure judge.ts imports only files included in the problem directory.',\n '',\n `Copied problem dir : ${copiedProblemDir}`,\n `Checked cwd : ${relativeCwd}`,\n `Exit status : ${spawnResult.status ?? spawnResult.signal ?? 'unknown'}`,\n `Spawn error : ${spawnResult.error?.message ?? '<none>'}`,\n '',\n 'stdout:',\n stdout.trimEnd() || '<empty>',\n '',\n 'stderr:',\n stderr.trimEnd() || '<empty>',\n ]);\n return { passed: false };\n } catch (error) {\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check failed due to an unexpected error',\n '',\n error instanceof Error ? error.message : String(error),\n ]);\n return { passed: false };\n } finally {\n if (tempRoot) {\n try {\n await fs.promises.rm(tempRoot, { recursive: true, force: true });\n } catch {\n // Cleanup errors should not mask the primary isolation check result.\n }\n }\n }\n}\n\nfunction isCopiedProblemPath(src: string): boolean {\n const name = path.basename(src);\n return name !== 'node_modules' && name !== '.git';\n}\n\nfunction isIsolationExecArg(arg: string): boolean {\n return !arg.startsWith('--inspect') && !arg.startsWith('--watch') && !arg.startsWith('--hot');\n}\n\nfunction isJudgeParamsObject(params: unknown): params is object {\n return params !== undefined && params !== null && typeof params === 'object' && !Array.isArray(params);\n}\n\nasync function symlinkAllAncestorNodeModules(tempRoot: string, problemDir: string): Promise<void> {\n let currentDir = path.resolve(problemDir);\n while (true) {\n const nodeModulesPath = path.join(currentDir, 'node_modules');\n if (fs.existsSync(nodeModulesPath)) {\n const targetSymlinkPath = path.join(tempRoot, toTempRelativePath(currentDir), 'node_modules');\n try {\n await fs.promises.symlink(\n nodeModulesPath,\n targetSymlinkPath,\n process.platform === 'win32' ? 'junction' : 'dir'\n );\n } catch {\n // Package resolution is best-effort; the isolation check still reports a clear spawn failure if imports break.\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) break;\n currentDir = parentDir;\n }\n}\n\nfunction toTempRelativePath(absolutePath: string): string {\n const { root } = path.parse(absolutePath);\n return path.relative(root, absolutePath);\n}\n\nfunction getInvokedScriptPath(problemDir: string): string {\n const scriptPath = process.argv[1];\n if (!scriptPath) return `.${path.sep}judge.ts`;\n const relativeScriptPath = path.relative(problemDir, path.resolve(scriptPath));\n if (path.isAbsolute(relativeScriptPath)) return relativeScriptPath;\n return relativeScriptPath.startsWith('.') ? relativeScriptPath : `.${path.sep}${relativeScriptPath}`;\n}\n\nfunction isAcceptedJudgeOutput(stdout: string): boolean {\n const resultLines = stdout.split(/\\r?\\n/).filter((line) => line.startsWith(TEST_CASE_RESULT_PREFIX));\n if (resultLines.length === 0) return false;\n\n return resultLines.every((line) => {\n try {\n const parsedResult = testCaseResultSchema.safeParse(JSON.parse(line.slice(TEST_CASE_RESULT_PREFIX.length)));\n return parsedResult.success && parsedResult.data.decisionCode === DecisionCode.ACCEPTED;\n } catch {\n return false;\n }\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"checkProblemDirIsolation.js","names":[],"sources":["../../src/helpers/checkProblemDirIsolation.ts"],"sourcesContent":["import child_process from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { DecisionCode } from '../types/decisionCode.js';\nimport { TEST_CASE_RESULT_PREFIX, testCaseResultSchema } from '../types/testCaseResult.js';\n\nimport { printDebugBanner } from './printDebugBanner.js';\nimport type { ResolvedCwd } from './resolveCwds.js';\n\nconst ISOLATION_CHECK_TIMEOUT_MS = 30_000;\n\nexport interface ProblemDirIsolationCheckResult {\n passed: boolean;\n}\n\n/**\n * Check that a judge can run after only the problem directory is copied elsewhere.\n */\nexport async function checkProblemDirIsolation(\n problemDir: string,\n resolvedCwd: ResolvedCwd,\n params: unknown\n): Promise<ProblemDirIsolationCheckResult> {\n let tempRoot: string | undefined;\n try {\n tempRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'problem-utils-isolation_'));\n const absoluteProblemDir = path.resolve(problemDir);\n const copiedProblemDir = path.join(tempRoot, toTempRelativePath(absoluteProblemDir));\n await fs.promises.mkdir(path.dirname(copiedProblemDir), { recursive: true });\n await fs.promises.cp(absoluteProblemDir, copiedProblemDir, {\n recursive: true,\n filter: isCopiedProblemPath,\n });\n await symlinkAllAncestorNodeModules(tempRoot, absoluteProblemDir);\n\n const relativeCwd = path.relative(absoluteProblemDir, path.resolve(resolvedCwd.cwd));\n const copiedCwd = path.join(copiedProblemDir, relativeCwd);\n const scriptPath = getInvokedScriptPath(absoluteProblemDir);\n if (scriptPath.startsWith('..') || path.isAbsolute(scriptPath)) {\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check skipped',\n '',\n 'The invoked judge script is located outside the problem directory.',\n `Script path: ${scriptPath}`,\n ]);\n return { passed: true };\n }\n const execArgv = process.execArgv.filter(isIsolationExecArg);\n const paramsJson = JSON.stringify(isJudgeParamsObject(params) ? params : {});\n const spawnResult = child_process.spawnSync(process.execPath, [...execArgv, scriptPath, copiedCwd, paramsJson], {\n cwd: copiedProblemDir,\n encoding: 'utf8',\n env: process.env,\n timeout: ISOLATION_CHECK_TIMEOUT_MS,\n });\n const stdout = spawnResult.stdout ?? '';\n const stderr = spawnResult.stderr ?? '';\n\n if (spawnResult.status === 0 && isAcceptedJudgeOutput(stdout)) {\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check passed',\n '',\n `Copied problem dir : ${copiedProblemDir}`,\n `Checked cwd : ${relativeCwd}`,\n ]);\n return { passed: true };\n }\n\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check failed',\n '',\n 'The judge did not complete successfully after copying only the problem directory to a temporary location.',\n 'Make sure judge.ts imports only files included in the problem directory.',\n '',\n `Copied problem dir : ${copiedProblemDir}`,\n `Checked cwd : ${relativeCwd}`,\n `Exit status : ${spawnResult.status ?? spawnResult.signal ?? 'unknown'}`,\n `Spawn error : ${spawnResult.error?.message ?? '<none>'}`,\n '',\n 'stdout:',\n stdout.trimEnd() || '<empty>',\n '',\n 'stderr:',\n stderr.trimEnd() || '<empty>',\n ]);\n return { passed: false };\n } catch (error) {\n printDebugBanner([\n '[DEBUG MODE] isolated problem directory check failed due to an unexpected error',\n '',\n error instanceof Error ? error.message : String(error),\n ]);\n return { passed: false };\n } finally {\n if (tempRoot) {\n try {\n await fs.promises.rm(tempRoot, { recursive: true, force: true });\n } catch {\n // Cleanup errors should not mask the primary isolation check result.\n }\n }\n }\n}\n\nfunction isCopiedProblemPath(src: string): boolean {\n const name = path.basename(src);\n return name !== 'node_modules' && name !== '.git';\n}\n\nfunction isIsolationExecArg(arg: string): boolean {\n return !arg.startsWith('--inspect') && !arg.startsWith('--watch') && !arg.startsWith('--hot');\n}\n\nfunction isJudgeParamsObject(params: unknown): params is object {\n return params !== undefined && params !== null && typeof params === 'object' && !Array.isArray(params);\n}\n\nasync function symlinkAllAncestorNodeModules(tempRoot: string, problemDir: string): Promise<void> {\n let currentDir = path.resolve(problemDir);\n while (true) {\n const nodeModulesPath = path.join(currentDir, 'node_modules');\n if (fs.existsSync(nodeModulesPath)) {\n const targetSymlinkPath = path.join(tempRoot, toTempRelativePath(currentDir), 'node_modules');\n try {\n await fs.promises.symlink(\n nodeModulesPath,\n targetSymlinkPath,\n process.platform === 'win32' ? 'junction' : 'dir'\n );\n } catch {\n // Package resolution is best-effort; the isolation check still reports a clear spawn failure if imports break.\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) break;\n currentDir = parentDir;\n }\n}\n\nfunction toTempRelativePath(absolutePath: string): string {\n const { root } = path.parse(absolutePath);\n return path.relative(root, absolutePath);\n}\n\nfunction getInvokedScriptPath(problemDir: string): string {\n const scriptPath = process.argv[1];\n if (!scriptPath) return `.${path.sep}judge.ts`;\n const relativeScriptPath = path.relative(problemDir, path.resolve(scriptPath));\n if (path.isAbsolute(relativeScriptPath)) return relativeScriptPath;\n return relativeScriptPath.startsWith('.') ? relativeScriptPath : `.${path.sep}${relativeScriptPath}`;\n}\n\nfunction isAcceptedJudgeOutput(stdout: string): boolean {\n const resultLines = stdout.split(/\\r?\\n/).filter((line) => line.startsWith(TEST_CASE_RESULT_PREFIX));\n if (resultLines.length === 0) return false;\n\n return resultLines.every((line) => {\n try {\n const parsedResult = testCaseResultSchema.safeParse(JSON.parse(line.slice(TEST_CASE_RESULT_PREFIX.length)));\n return parsedResult.success && parsedResult.data.decisionCode === DecisionCode.ACCEPTED;\n } catch {\n return false;\n }\n });\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:path");t=e.__toESM(t,1);let n=require("node:fs");n=e.__toESM(n,1);async function r(e){let t=await n.default.promises.readdir(e,{recursive:!0});return new Set(t)}async function i(e,r){for(let i of await n.default.promises.readdir(e,{recursive:!0}))r.has(i)||await n.default.promises.rm(t.default.join(e,i),{force:!0,recursive:!0})}exports.cleanWorkingDirectory=i,exports.snapshotWorkingDirectory=r;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./sandboxUser.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:path");r=e.__toESM(r,1);async function i(e){let t=new Map;return await o(e,e,t),t}async function a(e,t){await s(e,e,t)}async function o(e,t,n){for(let i of await l(t)){let a=r.default.join(t,i.name);n.set(r.default.relative(e,a),c(i)),i.isDirectory()&&await o(e,a,n)}}async function s(e,n,i){for(let a of await l(n)){let o=r.default.join(n,a.name),l=i.get(r.default.relative(e,o));if(l===void 0||l!==c(a)){await t.forceRemove(o);continue}a.isDirectory()&&await s(e,o,i)}}function c(e){return e.isSymbolicLink()?`symlink`:e.isDirectory()?`directory`:e.isFile()?`file`:`other`}async function l(e){try{return await n.default.promises.readdir(e,{withFileTypes:!0})}catch(r){if(!t.sandboxUserName)throw r;return t.relaxPermissionsAsSandboxUser(e),await n.default.promises.readdir(e,{withFileTypes:!0})}}exports.cleanWorkingDirectory=a,exports.snapshotWorkingDirectory=i;
2
2
  //# sourceMappingURL=cleanWorkingDirectory.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanWorkingDirectory.cjs","names":["fs","path"],"sources":["../../src/helpers/cleanWorkingDirectory.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\n// Currently, it does not support changing file contents and deleting files.\nexport async function snapshotWorkingDirectory(cwd: string): Promise<ReadonlySet<string>> {\n const paths = await fs.promises.readdir(cwd, { recursive: true });\n return new Set(paths);\n}\n\nexport async function cleanWorkingDirectory(cwd: string, snapshot: ReadonlySet<string>): Promise<void> {\n for (const p of await fs.promises.readdir(cwd, { recursive: true })) {\n if (snapshot.has(p)) continue;\n await fs.promises.rm(path.join(cwd, p), { force: true, recursive: true });\n }\n}\n"],"mappings":"wJAIA,eAAsB,EAAyB,EAA2C,CACxF,IAAM,EAAQ,MAAMA,EAAAA,QAAG,SAAS,QAAQ,EAAK,CAAE,UAAW,EAAK,CAAC,EAChE,OAAO,IAAI,IAAI,CAAK,CACtB,CAEA,eAAsB,EAAsB,EAAa,EAA8C,CACrG,IAAK,IAAM,KAAK,MAAMA,EAAAA,QAAG,SAAS,QAAQ,EAAK,CAAE,UAAW,EAAK,CAAC,EAC5D,EAAS,IAAI,CAAC,GAClB,MAAMA,EAAAA,QAAG,SAAS,GAAGC,EAAAA,QAAK,KAAK,EAAK,CAAC,EAAG,CAAE,MAAO,GAAM,UAAW,EAAK,CAAC,CAE5E"}
1
+ {"version":3,"file":"cleanWorkingDirectory.cjs","names":["path","forceRemove","fs","sandboxUserName"],"sources":["../../src/helpers/cleanWorkingDirectory.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { forceRemove, relaxPermissionsAsSandboxUser, sandboxUserName } from './sandboxUser.js';\n\n/** Snapshot of the working directory: each entry's relative path and the kind of entry it was. */\nexport type WorkingDirectorySnapshot = ReadonlyMap<string, WorkingDirectoryEntryKind>;\n\ntype WorkingDirectoryEntryKind = 'directory' | 'file' | 'symlink' | 'other';\n\n// Currently, it does not support changing file contents and deleting files.\nexport async function snapshotWorkingDirectory(cwd: string): Promise<WorkingDirectorySnapshot> {\n const snapshot = new Map<string, WorkingDirectoryEntryKind>();\n await collectEntries(cwd, cwd, snapshot);\n return snapshot;\n}\n\nexport async function cleanWorkingDirectory(cwd: string, snapshot: WorkingDirectorySnapshot): Promise<void> {\n await removeUnsnapshotted(cwd, cwd, snapshot);\n}\n\nasync function collectEntries(root: string, dir: string, into: Map<string, WorkingDirectoryEntryKind>): Promise<void> {\n for (const entry of await readdirWithTypes(dir)) {\n const absolutePath = path.join(dir, entry.name);\n into.set(path.relative(root, absolutePath), toEntryKind(entry));\n // Never descend into a symlink: a sandboxed submission could point it outside the directory.\n if (entry.isDirectory()) await collectEntries(root, absolutePath, into);\n }\n}\n\nasync function removeUnsnapshotted(root: string, dir: string, snapshot: WorkingDirectorySnapshot): Promise<void> {\n for (const entry of await readdirWithTypes(dir)) {\n const absolutePath = path.join(dir, entry.name);\n const snapshottedKind = snapshot.get(path.relative(root, absolutePath));\n // The kind must still match: a sandboxed submission can replace one of its own snapshotted\n // entries with a symlink, and matching by path alone would preserve it across test cases.\n if (snapshottedKind === undefined || snapshottedKind !== toEntryKind(entry)) {\n // `absolutePath` has no symlink ancestor (we only recurse into real directories), and\n // `forceRemove`/`fs.rm` unlinks a leaf symlink instead of following it, so this cannot delete\n // outside the working directory even if the submission planted symlinks.\n await forceRemove(absolutePath);\n continue;\n }\n if (entry.isDirectory()) await removeUnsnapshotted(root, absolutePath, snapshot);\n }\n}\n\nfunction toEntryKind(entry: fs.Dirent): WorkingDirectoryEntryKind {\n if (entry.isSymbolicLink()) return 'symlink';\n if (entry.isDirectory()) return 'directory';\n if (entry.isFile()) return 'file';\n return 'other';\n}\n\n/**\n * `readdir` with entry types (which reflect `lstat`, so a symlink reads as a symlink, not a\n * directory), with a fallback for directories a sandboxed process made untraversable.\n */\nasync function readdirWithTypes(dir: string): Promise<fs.Dirent[]> {\n try {\n return await fs.promises.readdir(dir, { withFileTypes: true });\n } catch (error) {\n if (!sandboxUserName) throw error;\n relaxPermissionsAsSandboxUser(dir);\n return await fs.promises.readdir(dir, { withFileTypes: true });\n }\n}\n"],"mappings":"uLAWA,eAAsB,EAAyB,EAAgD,CAC7F,IAAM,EAAW,IAAI,IAErB,OADA,MAAM,EAAe,EAAK,EAAK,CAAQ,EAChC,CACT,CAEA,eAAsB,EAAsB,EAAa,EAAmD,CAC1G,MAAM,EAAoB,EAAK,EAAK,CAAQ,CAC9C,CAEA,eAAe,EAAe,EAAc,EAAa,EAA6D,CACpH,IAAK,IAAM,KAAS,MAAM,EAAiB,CAAG,EAAG,CAC/C,IAAM,EAAeA,EAAAA,QAAK,KAAK,EAAK,EAAM,IAAI,EAC9C,EAAK,IAAIA,EAAAA,QAAK,SAAS,EAAM,CAAY,EAAG,EAAY,CAAK,CAAC,EAE1D,EAAM,YAAY,GAAG,MAAM,EAAe,EAAM,EAAc,CAAI,CACxE,CACF,CAEA,eAAe,EAAoB,EAAc,EAAa,EAAmD,CAC/G,IAAK,IAAM,KAAS,MAAM,EAAiB,CAAG,EAAG,CAC/C,IAAM,EAAeA,EAAAA,QAAK,KAAK,EAAK,EAAM,IAAI,EACxC,EAAkB,EAAS,IAAIA,EAAAA,QAAK,SAAS,EAAM,CAAY,CAAC,EAGtE,GAAI,IAAoB,IAAA,IAAa,IAAoB,EAAY,CAAK,EAAG,CAI3E,MAAMC,EAAAA,YAAY,CAAY,EAC9B,QACF,CACI,EAAM,YAAY,GAAG,MAAM,EAAoB,EAAM,EAAc,CAAQ,CACjF,CACF,CAEA,SAAS,EAAY,EAA6C,CAIhE,OAHI,EAAM,eAAe,EAAU,UAC/B,EAAM,YAAY,EAAU,YAC5B,EAAM,OAAO,EAAU,OACpB,OACT,CAMA,eAAe,EAAiB,EAAmC,CACjE,GAAI,CACF,OAAO,MAAMC,EAAAA,QAAG,SAAS,QAAQ,EAAK,CAAE,cAAe,EAAK,CAAC,CAC/D,OAAS,EAAO,CACd,GAAI,CAACC,EAAAA,gBAAiB,MAAM,EAE5B,OADA,EAAA,8BAA8B,CAAG,EAC1B,MAAMD,EAAAA,QAAG,SAAS,QAAQ,EAAK,CAAE,cAAe,EAAK,CAAC,CAC/D,CACF"}
@@ -1,2 +1,6 @@
1
- export declare function snapshotWorkingDirectory(cwd: string): Promise<ReadonlySet<string>>;
2
- export declare function cleanWorkingDirectory(cwd: string, snapshot: ReadonlySet<string>): Promise<void>;
1
+ /** Snapshot of the working directory: each entry's relative path and the kind of entry it was. */
2
+ export type WorkingDirectorySnapshot = ReadonlyMap<string, WorkingDirectoryEntryKind>;
3
+ type WorkingDirectoryEntryKind = 'directory' | 'file' | 'symlink' | 'other';
4
+ export declare function snapshotWorkingDirectory(cwd: string): Promise<WorkingDirectorySnapshot>;
5
+ export declare function cleanWorkingDirectory(cwd: string, snapshot: WorkingDirectorySnapshot): Promise<void>;
6
+ export {};
@@ -1,2 +1,2 @@
1
- import e from"node:path";import t from"node:fs";async function n(e){let n=await t.promises.readdir(e,{recursive:!0});return new Set(n)}async function r(n,r){for(let i of await t.promises.readdir(n,{recursive:!0}))r.has(i)||await t.promises.rm(e.join(n,i),{force:!0,recursive:!0})}export{r as cleanWorkingDirectory,n as snapshotWorkingDirectory};
1
+ import{forceRemove as e,relaxPermissionsAsSandboxUser as t,sandboxUserName as n}from"./sandboxUser.js";import r from"node:fs";import i from"node:path";async function a(e){let t=new Map;return await s(e,e,t),t}async function o(e,t){await c(e,e,t)}async function s(e,t,n){for(let r of await u(t)){let a=i.join(t,r.name);n.set(i.relative(e,a),l(r)),r.isDirectory()&&await s(e,a,n)}}async function c(t,n,r){for(let a of await u(n)){let o=i.join(n,a.name),s=r.get(i.relative(t,o));if(s===void 0||s!==l(a)){await e(o);continue}a.isDirectory()&&await c(t,o,r)}}function l(e){return e.isSymbolicLink()?`symlink`:e.isDirectory()?`directory`:e.isFile()?`file`:`other`}async function u(e){try{return await r.promises.readdir(e,{withFileTypes:!0})}catch(i){if(!n)throw i;return t(e),await r.promises.readdir(e,{withFileTypes:!0})}}export{o as cleanWorkingDirectory,a as snapshotWorkingDirectory};
2
2
  //# sourceMappingURL=cleanWorkingDirectory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanWorkingDirectory.js","names":[],"sources":["../../src/helpers/cleanWorkingDirectory.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\n// Currently, it does not support changing file contents and deleting files.\nexport async function snapshotWorkingDirectory(cwd: string): Promise<ReadonlySet<string>> {\n const paths = await fs.promises.readdir(cwd, { recursive: true });\n return new Set(paths);\n}\n\nexport async function cleanWorkingDirectory(cwd: string, snapshot: ReadonlySet<string>): Promise<void> {\n for (const p of await fs.promises.readdir(cwd, { recursive: true })) {\n if (snapshot.has(p)) continue;\n await fs.promises.rm(path.join(cwd, p), { force: true, recursive: true });\n }\n}\n"],"mappings":"gDAIA,eAAsB,EAAyB,EAA2C,CACxF,IAAM,EAAQ,MAAM,EAAG,SAAS,QAAQ,EAAK,CAAE,UAAW,EAAK,CAAC,EAChE,OAAO,IAAI,IAAI,CAAK,CACtB,CAEA,eAAsB,EAAsB,EAAa,EAA8C,CACrG,IAAK,IAAM,KAAK,MAAM,EAAG,SAAS,QAAQ,EAAK,CAAE,UAAW,EAAK,CAAC,EAC5D,EAAS,IAAI,CAAC,GAClB,MAAM,EAAG,SAAS,GAAG,EAAK,KAAK,EAAK,CAAC,EAAG,CAAE,MAAO,GAAM,UAAW,EAAK,CAAC,CAE5E"}
1
+ {"version":3,"file":"cleanWorkingDirectory.js","names":[],"sources":["../../src/helpers/cleanWorkingDirectory.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { forceRemove, relaxPermissionsAsSandboxUser, sandboxUserName } from './sandboxUser.js';\n\n/** Snapshot of the working directory: each entry's relative path and the kind of entry it was. */\nexport type WorkingDirectorySnapshot = ReadonlyMap<string, WorkingDirectoryEntryKind>;\n\ntype WorkingDirectoryEntryKind = 'directory' | 'file' | 'symlink' | 'other';\n\n// Currently, it does not support changing file contents and deleting files.\nexport async function snapshotWorkingDirectory(cwd: string): Promise<WorkingDirectorySnapshot> {\n const snapshot = new Map<string, WorkingDirectoryEntryKind>();\n await collectEntries(cwd, cwd, snapshot);\n return snapshot;\n}\n\nexport async function cleanWorkingDirectory(cwd: string, snapshot: WorkingDirectorySnapshot): Promise<void> {\n await removeUnsnapshotted(cwd, cwd, snapshot);\n}\n\nasync function collectEntries(root: string, dir: string, into: Map<string, WorkingDirectoryEntryKind>): Promise<void> {\n for (const entry of await readdirWithTypes(dir)) {\n const absolutePath = path.join(dir, entry.name);\n into.set(path.relative(root, absolutePath), toEntryKind(entry));\n // Never descend into a symlink: a sandboxed submission could point it outside the directory.\n if (entry.isDirectory()) await collectEntries(root, absolutePath, into);\n }\n}\n\nasync function removeUnsnapshotted(root: string, dir: string, snapshot: WorkingDirectorySnapshot): Promise<void> {\n for (const entry of await readdirWithTypes(dir)) {\n const absolutePath = path.join(dir, entry.name);\n const snapshottedKind = snapshot.get(path.relative(root, absolutePath));\n // The kind must still match: a sandboxed submission can replace one of its own snapshotted\n // entries with a symlink, and matching by path alone would preserve it across test cases.\n if (snapshottedKind === undefined || snapshottedKind !== toEntryKind(entry)) {\n // `absolutePath` has no symlink ancestor (we only recurse into real directories), and\n // `forceRemove`/`fs.rm` unlinks a leaf symlink instead of following it, so this cannot delete\n // outside the working directory even if the submission planted symlinks.\n await forceRemove(absolutePath);\n continue;\n }\n if (entry.isDirectory()) await removeUnsnapshotted(root, absolutePath, snapshot);\n }\n}\n\nfunction toEntryKind(entry: fs.Dirent): WorkingDirectoryEntryKind {\n if (entry.isSymbolicLink()) return 'symlink';\n if (entry.isDirectory()) return 'directory';\n if (entry.isFile()) return 'file';\n return 'other';\n}\n\n/**\n * `readdir` with entry types (which reflect `lstat`, so a symlink reads as a symlink, not a\n * directory), with a fallback for directories a sandboxed process made untraversable.\n */\nasync function readdirWithTypes(dir: string): Promise<fs.Dirent[]> {\n try {\n return await fs.promises.readdir(dir, { withFileTypes: true });\n } catch (error) {\n if (!sandboxUserName) throw error;\n relaxPermissionsAsSandboxUser(dir);\n return await fs.promises.readdir(dir, { withFileTypes: true });\n }\n}\n"],"mappings":"uJAWA,eAAsB,EAAyB,EAAgD,CAC7F,IAAM,EAAW,IAAI,IAErB,OADA,MAAM,EAAe,EAAK,EAAK,CAAQ,EAChC,CACT,CAEA,eAAsB,EAAsB,EAAa,EAAmD,CAC1G,MAAM,EAAoB,EAAK,EAAK,CAAQ,CAC9C,CAEA,eAAe,EAAe,EAAc,EAAa,EAA6D,CACpH,IAAK,IAAM,KAAS,MAAM,EAAiB,CAAG,EAAG,CAC/C,IAAM,EAAe,EAAK,KAAK,EAAK,EAAM,IAAI,EAC9C,EAAK,IAAI,EAAK,SAAS,EAAM,CAAY,EAAG,EAAY,CAAK,CAAC,EAE1D,EAAM,YAAY,GAAG,MAAM,EAAe,EAAM,EAAc,CAAI,CACxE,CACF,CAEA,eAAe,EAAoB,EAAc,EAAa,EAAmD,CAC/G,IAAK,IAAM,KAAS,MAAM,EAAiB,CAAG,EAAG,CAC/C,IAAM,EAAe,EAAK,KAAK,EAAK,EAAM,IAAI,EACxC,EAAkB,EAAS,IAAI,EAAK,SAAS,EAAM,CAAY,CAAC,EAGtE,GAAI,IAAoB,IAAA,IAAa,IAAoB,EAAY,CAAK,EAAG,CAI3E,MAAM,EAAY,CAAY,EAC9B,QACF,CACI,EAAM,YAAY,GAAG,MAAM,EAAoB,EAAM,EAAc,CAAQ,CACjF,CACF,CAEA,SAAS,EAAY,EAA6C,CAIhE,OAHI,EAAM,eAAe,EAAU,UAC/B,EAAM,YAAY,EAAU,YAC5B,EAAM,OAAO,EAAU,OACpB,OACT,CAMA,eAAe,EAAiB,EAAmC,CACjE,GAAI,CACF,OAAO,MAAM,EAAG,SAAS,QAAQ,EAAK,CAAE,cAAe,EAAK,CAAC,CAC/D,OAAS,EAAO,CACd,GAAI,CAAC,EAAiB,MAAM,EAE5B,OADA,EAA8B,CAAG,EAC1B,MAAM,EAAG,SAAS,QAAQ,EAAK,CAAE,cAAe,EAAK,CAAC,CAC/D,CACF"}
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);async function n(e,n){await t.default.promises.cp(e,n,{force:!0,recursive:!0})}exports.copyTestCaseFileInput=n;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./sandboxUser.cjs"),n=require("./safeFs.cjs");let r=require("node:fs");r=e.__toESM(r,1);async function i(e,i){if(!(await r.default.promises.lstat(e)).isDirectory())throw Error(`test case file input must be a directory, not a symlink or file: ${e}`);await n.copyWithoutFollowingSymlinks(e,i),t.makeAccessibleToSandboxUser(i)}exports.copyTestCaseFileInput=i;
2
2
  //# sourceMappingURL=copyTestCaseFileInput.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"copyTestCaseFileInput.cjs","names":["fs"],"sources":["../../src/helpers/copyTestCaseFileInput.ts"],"sourcesContent":["import fs from 'node:fs';\n\nexport async function copyTestCaseFileInput(fileInputPath: string, cwd: string): Promise<void> {\n await fs.promises.cp(fileInputPath, cwd, { force: true, recursive: true });\n}\n"],"mappings":"4GAEA,eAAsB,EAAsB,EAAuB,EAA4B,CAC7F,MAAMA,EAAAA,QAAG,SAAS,GAAG,EAAe,EAAK,CAAE,MAAO,GAAM,UAAW,EAAK,CAAC,CAC3E"}
1
+ {"version":3,"file":"copyTestCaseFileInput.cjs","names":["fs","copyWithoutFollowingSymlinks"],"sources":["../../src/helpers/copyTestCaseFileInput.ts"],"sourcesContent":["import fs from 'node:fs';\n\nimport { copyWithoutFollowingSymlinks } from './safeFs.js';\nimport { makeAccessibleToSandboxUser } from './sandboxUser.js';\n\nexport async function copyTestCaseFileInput(fileInputPath: string, cwd: string): Promise<void> {\n // `readTestCases` only ever yields a real `.fin` directory here (it selects entries by\n // `dirent.isDirectory()`, which does not follow links), and the destination is the working\n // directory itself, so anything else would mean replacing that whole directory — with a file, or\n // with a symlink to the problem's test cases. `lstat`, not `stat`: the latter resolves a symlink\n // source and would report it as a directory.\n const fileInputStats = await fs.promises.lstat(fileInputPath);\n if (!fileInputStats.isDirectory()) {\n throw new Error(`test case file input must be a directory, not a symlink or file: ${fileInputPath}`);\n }\n // A no-follow copy: a sandboxed submission may have planted a symlink at one of these\n // destination paths to redirect this trusted-user write outside its working directory.\n await copyWithoutFollowingSymlinks(fileInputPath, cwd);\n // The copied files are owned by the harness user; the sandboxed submission must read them and\n // may create outputs in the copied directories.\n makeAccessibleToSandboxUser(cwd);\n}\n"],"mappings":"qKAKA,eAAsB,EAAsB,EAAuB,EAA4B,CAO7F,GAAI,EAAC,MADwBA,EAAAA,QAAG,SAAS,MAAM,CAAa,EAAA,CACxC,YAAY,EAC9B,MAAU,MAAM,oEAAoE,GAAe,EAIrG,MAAMC,EAAAA,6BAA6B,EAAe,CAAG,EAGrD,EAAA,4BAA4B,CAAG,CACjC"}
@@ -1,2 +1,2 @@
1
- import e from"node:fs";async function t(t,n){await e.promises.cp(t,n,{force:!0,recursive:!0})}export{t as copyTestCaseFileInput};
1
+ import{makeAccessibleToSandboxUser as e}from"./sandboxUser.js";import{copyWithoutFollowingSymlinks as t}from"./safeFs.js";import n from"node:fs";async function r(r,i){if(!(await n.promises.lstat(r)).isDirectory())throw Error(`test case file input must be a directory, not a symlink or file: ${r}`);await t(r,i),e(i)}export{r as copyTestCaseFileInput};
2
2
  //# sourceMappingURL=copyTestCaseFileInput.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"copyTestCaseFileInput.js","names":[],"sources":["../../src/helpers/copyTestCaseFileInput.ts"],"sourcesContent":["import fs from 'node:fs';\n\nexport async function copyTestCaseFileInput(fileInputPath: string, cwd: string): Promise<void> {\n await fs.promises.cp(fileInputPath, cwd, { force: true, recursive: true });\n}\n"],"mappings":"uBAEA,eAAsB,EAAsB,EAAuB,EAA4B,CAC7F,MAAM,EAAG,SAAS,GAAG,EAAe,EAAK,CAAE,MAAO,GAAM,UAAW,EAAK,CAAC,CAC3E"}
1
+ {"version":3,"file":"copyTestCaseFileInput.js","names":[],"sources":["../../src/helpers/copyTestCaseFileInput.ts"],"sourcesContent":["import fs from 'node:fs';\n\nimport { copyWithoutFollowingSymlinks } from './safeFs.js';\nimport { makeAccessibleToSandboxUser } from './sandboxUser.js';\n\nexport async function copyTestCaseFileInput(fileInputPath: string, cwd: string): Promise<void> {\n // `readTestCases` only ever yields a real `.fin` directory here (it selects entries by\n // `dirent.isDirectory()`, which does not follow links), and the destination is the working\n // directory itself, so anything else would mean replacing that whole directory — with a file, or\n // with a symlink to the problem's test cases. `lstat`, not `stat`: the latter resolves a symlink\n // source and would report it as a directory.\n const fileInputStats = await fs.promises.lstat(fileInputPath);\n if (!fileInputStats.isDirectory()) {\n throw new Error(`test case file input must be a directory, not a symlink or file: ${fileInputPath}`);\n }\n // A no-follow copy: a sandboxed submission may have planted a symlink at one of these\n // destination paths to redirect this trusted-user write outside its working directory.\n await copyWithoutFollowingSymlinks(fileInputPath, cwd);\n // The copied files are owned by the harness user; the sandboxed submission must read them and\n // may create outputs in the copied directories.\n makeAccessibleToSandboxUser(cwd);\n}\n"],"mappings":"iJAKA,eAAsB,EAAsB,EAAuB,EAA4B,CAO7F,GAAI,EAAC,MADwB,EAAG,SAAS,MAAM,CAAa,EAAA,CACxC,YAAY,EAC9B,MAAU,MAAM,oEAAoE,GAAe,EAIrG,MAAM,EAA6B,EAAe,CAAG,EAGrD,EAA4B,CAAG,CACjC"}
@@ -1,4 +1,4 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./removeCommentsInSourceCode.cjs"),n=require("../types/decisionCode.cjs"),r=require("./findLanguageDefinitionByPath.cjs");let i=require("node:path");i=e.__toESM(i,1);let a=require("node:fs");a=e.__toESM(a,1);async function o(e,o){let s=new Set,c=[];for(let n of await a.default.promises.readdir(e,{withFileTypes:!0,recursive:!0})){if(!n.isFile())continue;let o=i.default.relative(e,i.default.join(n.parentPath,n.name));s.add(o);let l=await a.default.promises.readFile(i.default.join(n.parentPath,n.name),`utf8`);if(l.includes(`�`))continue;let u=r.findLanguageDefinitionByPath(n.name);u&&c.push({path:n.name,data:u.grammer?t.removeCommentsInSourceCode(u.grammer,l):l})}if(o.requiredSubmissionFilePaths){let e=o.requiredSubmissionFilePaths.filter(e=>!s.has(e)).toSorted();if(e.length>0)return{decisionCode:n.DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,feedbackMarkdown:`ファイルが不足しています。
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./removeCommentsInSourceCode.cjs"),n=require("../types/decisionCode.cjs"),r=require("./findLanguageDefinitionByPath.cjs");let i=require("node:fs");i=e.__toESM(i,1);let a=require("node:path");a=e.__toESM(a,1);async function o(e,o){let s=new Set,c=[];for(let n of await i.default.promises.readdir(e,{withFileTypes:!0,recursive:!0})){if(!n.isFile())continue;let o=a.default.relative(e,a.default.join(n.parentPath,n.name));s.add(o);let l=await i.default.promises.readFile(a.default.join(n.parentPath,n.name),`utf8`);if(l.includes(`�`))continue;let u=r.findLanguageDefinitionByPath(n.name);u&&c.push({path:n.name,data:u.grammer?t.removeCommentsInSourceCode(u.grammer,l):l})}if(o.requiredSubmissionFilePaths){let e=o.requiredSubmissionFilePaths.filter(e=>!s.has(e)).toSorted();if(e.length>0)return{decisionCode:n.DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,feedbackMarkdown:`ファイルが不足しています。
2
2
  次のファイルを追加してから再度提出してください。
3
3
 
4
4
  ${e.map(e=>`- \`${e}\``).join(`
@@ -1,4 +1,4 @@
1
- import{removeCommentsInSourceCode as e}from"./removeCommentsInSourceCode.js";import{DecisionCode as t}from"../types/decisionCode.js";import{findLanguageDefinitionByPath as n}from"./findLanguageDefinitionByPath.js";import r from"node:path";import i from"node:fs";async function a(a,o){let s=new Set,c=[];for(let t of await i.promises.readdir(a,{withFileTypes:!0,recursive:!0})){if(!t.isFile())continue;let o=r.relative(a,r.join(t.parentPath,t.name));s.add(o);let l=await i.promises.readFile(r.join(t.parentPath,t.name),`utf8`);if(l.includes(`�`))continue;let u=n(t.name);u&&c.push({path:t.name,data:u.grammer?e(u.grammer,l):l})}if(o.requiredSubmissionFilePaths){let e=o.requiredSubmissionFilePaths.filter(e=>!s.has(e)).toSorted();if(e.length>0)return{decisionCode:t.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,feedbackMarkdown:`ファイルが不足しています。
1
+ import{removeCommentsInSourceCode as e}from"./removeCommentsInSourceCode.js";import{DecisionCode as t}from"../types/decisionCode.js";import{findLanguageDefinitionByPath as n}from"./findLanguageDefinitionByPath.js";import r from"node:fs";import i from"node:path";async function a(a,o){let s=new Set,c=[];for(let t of await r.promises.readdir(a,{withFileTypes:!0,recursive:!0})){if(!t.isFile())continue;let o=i.relative(a,i.join(t.parentPath,t.name));s.add(o);let l=await r.promises.readFile(i.join(t.parentPath,t.name),`utf8`);if(l.includes(`�`))continue;let u=n(t.name);u&&c.push({path:t.name,data:u.grammer?e(u.grammer,l):l})}if(o.requiredSubmissionFilePaths){let e=o.requiredSubmissionFilePaths.filter(e=>!s.has(e)).toSorted();if(e.length>0)return{decisionCode:t.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,feedbackMarkdown:`ファイルが不足しています。
2
2
  次のファイルを追加してから再度提出してください。
3
3
 
4
4
  ${e.map(e=>`- \`${e}\``).join(`
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./printTestCaseResult.cjs");let n=require("node:path");n=e.__toESM(n,1);let r=require("node:fs");r=e.__toESM(r,1);async function i(e,i){let a=[];for(let o of i)try{let i=await r.default.promises.readFile(n.default.join(e,o));a.push(t.encodeFileForTestCaseResult(o,i))}catch{}return a}exports.readOutputFiles=i;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./printTestCaseResult.cjs"),n=require("./sandboxUser.cjs"),r=require("./safeFs.cjs");let i=require("node:fs");i=e.__toESM(i,1);let a=require("node:path");a=e.__toESM(a,1);async function o(e,n){let r=[];for(let o of n)try{let n=a.default.join(e,o);if(!await s(e,n))continue;let c=await i.default.promises.readFile(n);r.push(t.encodeFileForTestCaseResult(o,c))}catch{}return r}async function s(e,t){if(!n.sandboxUserName)return!0;try{let n=await i.default.promises.realpath(t),a=await i.default.promises.realpath(e);return r.isContainedPath(a,n)}catch{return!1}}exports.isSafeSubmissionOutputPath=s,exports.readOutputFiles=o;
2
2
  //# sourceMappingURL=readOutputFiles.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"readOutputFiles.cjs","names":["fs","path","encodeFileForTestCaseResult"],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n const buffer = await fs.promises.readFile(path.join(cwd, filePath));\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n"],"mappings":"+LAOA,eAAsB,EACpB,EACA,EACqD,CACrD,IAAM,EAA0D,CAAC,EACjE,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,IAAM,EAAS,MAAMA,EAAAA,QAAG,SAAS,SAASC,EAAAA,QAAK,KAAK,EAAK,CAAQ,CAAC,EAClE,EAAY,KAAKC,EAAAA,4BAA4B,EAAU,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAO,CACT"}
1
+ {"version":3,"file":"readOutputFiles.cjs","names":["path","fs","encodeFileForTestCaseResult","sandboxUserName","isContainedPath"],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\nimport { isContainedPath } from './safeFs.js';\nimport { sandboxUserName } from './sandboxUser.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n const resolvedPath = path.join(cwd, filePath);\n if (!(await isSafeSubmissionOutputPath(cwd, resolvedPath))) continue;\n const buffer = await fs.promises.readFile(resolvedPath);\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n\n/**\n * Whether the harness may read the given submission-created path. When submissions run as the\n * sandbox user while the harness is trusted, a submission could plant a symlink (or a symlinked\n * parent directory) escaping its working directory — e.g. to the 0700 problem directory — and the\n * privileged read would exfiltrate protected bytes, so only paths that resolve inside the working\n * directory are allowed. Without user separation the submission can read those targets itself, so\n * the check is skipped to keep authoring behavior unchanged.\n */\nexport async function isSafeSubmissionOutputPath(cwd: string, filePath: string): Promise<boolean> {\n if (!sandboxUserName) return true;\n try {\n const realFilePath = await fs.promises.realpath(filePath);\n const realCwd = await fs.promises.realpath(cwd);\n return isContainedPath(realCwd, realFilePath);\n } catch {\n return false;\n }\n}\n"],"mappings":"wPASA,eAAsB,EACpB,EACA,EACqD,CACrD,IAAM,EAA0D,CAAC,EACjE,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,IAAM,EAAeA,EAAAA,QAAK,KAAK,EAAK,CAAQ,EAC5C,GAAI,CAAE,MAAM,EAA2B,EAAK,CAAY,EAAI,SAC5D,IAAM,EAAS,MAAMC,EAAAA,QAAG,SAAS,SAAS,CAAY,EACtD,EAAY,KAAKC,EAAAA,4BAA4B,EAAU,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAO,CACT,CAUA,eAAsB,EAA2B,EAAa,EAAoC,CAChG,GAAI,CAACC,EAAAA,gBAAiB,MAAO,GAC7B,GAAI,CACF,IAAM,EAAe,MAAMF,EAAAA,QAAG,SAAS,SAAS,CAAQ,EAClD,EAAU,MAAMA,EAAAA,QAAG,SAAS,SAAS,CAAG,EAC9C,OAAOG,EAAAA,gBAAgB,EAAS,CAAY,CAC9C,MAAQ,CACN,MAAO,EACT,CACF"}
@@ -1,2 +1,11 @@
1
1
  import type { TestCaseResult } from '../types/testCaseResult.js';
2
2
  export declare function readOutputFiles(cwd: string, outputFilePaths: readonly string[]): Promise<NonNullable<TestCaseResult['outputFiles']>>;
3
+ /**
4
+ * Whether the harness may read the given submission-created path. When submissions run as the
5
+ * sandbox user while the harness is trusted, a submission could plant a symlink (or a symlinked
6
+ * parent directory) escaping its working directory — e.g. to the 0700 problem directory — and the
7
+ * privileged read would exfiltrate protected bytes, so only paths that resolve inside the working
8
+ * directory are allowed. Without user separation the submission can read those targets itself, so
9
+ * the check is skipped to keep authoring behavior unchanged.
10
+ */
11
+ export declare function isSafeSubmissionOutputPath(cwd: string, filePath: string): Promise<boolean>;
@@ -1,2 +1,2 @@
1
- import{encodeFileForTestCaseResult as e}from"./printTestCaseResult.js";import t from"node:path";import n from"node:fs";async function r(r,i){let a=[];for(let o of i)try{let i=await n.promises.readFile(t.join(r,o));a.push(e(o,i))}catch{}return a}export{r as readOutputFiles};
1
+ import{encodeFileForTestCaseResult as e}from"./printTestCaseResult.js";import{sandboxUserName as t}from"./sandboxUser.js";import{isContainedPath as n}from"./safeFs.js";import r from"node:fs";import i from"node:path";async function a(t,n){let a=[];for(let s of n)try{let n=i.join(t,s);if(!await o(t,n))continue;let c=await r.promises.readFile(n);a.push(e(s,c))}catch{}return a}async function o(e,i){if(!t)return!0;try{let t=await r.promises.realpath(i),a=await r.promises.realpath(e);return n(a,t)}catch{return!1}}export{o as isSafeSubmissionOutputPath,a as readOutputFiles};
2
2
  //# sourceMappingURL=readOutputFiles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"readOutputFiles.js","names":[],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n const buffer = await fs.promises.readFile(path.join(cwd, filePath));\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n"],"mappings":"uHAOA,eAAsB,EACpB,EACA,EACqD,CACrD,IAAM,EAA0D,CAAC,EACjE,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,IAAM,EAAS,MAAM,EAAG,SAAS,SAAS,EAAK,KAAK,EAAK,CAAQ,CAAC,EAClE,EAAY,KAAK,EAA4B,EAAU,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAO,CACT"}
1
+ {"version":3,"file":"readOutputFiles.js","names":[],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\nimport { isContainedPath } from './safeFs.js';\nimport { sandboxUserName } from './sandboxUser.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n const resolvedPath = path.join(cwd, filePath);\n if (!(await isSafeSubmissionOutputPath(cwd, resolvedPath))) continue;\n const buffer = await fs.promises.readFile(resolvedPath);\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n\n/**\n * Whether the harness may read the given submission-created path. When submissions run as the\n * sandbox user while the harness is trusted, a submission could plant a symlink (or a symlinked\n * parent directory) escaping its working directory — e.g. to the 0700 problem directory — and the\n * privileged read would exfiltrate protected bytes, so only paths that resolve inside the working\n * directory are allowed. Without user separation the submission can read those targets itself, so\n * the check is skipped to keep authoring behavior unchanged.\n */\nexport async function isSafeSubmissionOutputPath(cwd: string, filePath: string): Promise<boolean> {\n if (!sandboxUserName) return true;\n try {\n const realFilePath = await fs.promises.realpath(filePath);\n const realCwd = await fs.promises.realpath(cwd);\n return isContainedPath(realCwd, realFilePath);\n } catch {\n return false;\n }\n}\n"],"mappings":"wNASA,eAAsB,EACpB,EACA,EACqD,CACrD,IAAM,EAA0D,CAAC,EACjE,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,IAAM,EAAe,EAAK,KAAK,EAAK,CAAQ,EAC5C,GAAI,CAAE,MAAM,EAA2B,EAAK,CAAY,EAAI,SAC5D,IAAM,EAAS,MAAM,EAAG,SAAS,SAAS,CAAY,EACtD,EAAY,KAAK,EAA4B,EAAU,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAO,CACT,CAUA,eAAsB,EAA2B,EAAa,EAAoC,CAChG,GAAI,CAAC,EAAiB,MAAO,GAC7B,GAAI,CACF,IAAM,EAAe,MAAM,EAAG,SAAS,SAAS,CAAQ,EAClD,EAAU,MAAM,EAAG,SAAS,SAAS,CAAG,EAC9C,OAAO,EAAgB,EAAS,CAAY,CAC9C,MAAQ,CACN,MAAO,EACT,CACF"}
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../types/problem.cjs");let n=require("node:path");n=e.__toESM(n,1);let r=require("node:fs");r=e.__toESM(r,1);let i=require("front-matter");i=e.__toESM(i,1);async function a(e){for(let a of await r.default.promises.readdir(e,{withFileTypes:!0})){if(!a.isFile()||!(a.name===`problem.md`||a.name.endsWith(`.problem.md`)))continue;let{attributes:e}=(0,i.default)(await r.default.promises.readFile(n.default.join(a.parentPath,a.name),`utf8`));return t.problemMarkdownFrontMatterSchema.parse(e)}throw Error(`problem markdown not found: ${e}`)}exports.readProblemMarkdownFrontMatter=a;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("../types/problem.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:path");r=e.__toESM(r,1);let i=require("front-matter");i=e.__toESM(i,1);async function a(e){for(let a of await n.default.promises.readdir(e,{withFileTypes:!0})){if(!a.isFile()||!(a.name===`problem.md`||a.name.endsWith(`.problem.md`)))continue;let e=await n.default.promises.readFile(r.default.join(a.parentPath,a.name),`utf8`),{attributes:o}=(0,i.default)(e);return t.problemMarkdownFrontMatterSchema.parse(o)}throw Error(`problem markdown not found: ${e}`)}exports.readProblemMarkdownFrontMatter=a;
2
2
  //# sourceMappingURL=readProblemMarkdownFrontMatter.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"readProblemMarkdownFrontMatter.cjs","names":["fs","path","problemMarkdownFrontMatterSchema"],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"yOAQA,eAAsB,EAA+B,EAAyD,CAC5G,IAAK,IAAM,KAAU,MAAMA,EAAAA,QAAG,SAAS,QAAQ,EAAY,CAAE,cAAe,EAAK,CAAC,EAAG,CAEnF,GADI,CAAC,EAAO,OAAO,GACf,EAAE,EAAO,OAAS,cAAgB,EAAO,KAAK,SAAS,aAAa,GAAI,SAI5E,GAAM,CAAE,eAAA,EAAA,EAAA,QAAA,CAA8F,MAF/EA,EAAAA,QAAG,SAAS,SAASC,EAAAA,QAAK,KAAK,EAAO,WAAY,EAAO,IAAI,EAAG,MAAM,CAEiB,EAE9G,OAAOC,EAAAA,iCAAiC,MAAM,CAAU,CAC1D,CAEA,MAAU,MAAM,+BAA+B,GAAY,CAC7D"}
1
+ {"version":3,"file":"readProblemMarkdownFrontMatter.cjs","names":["fs","path","parseFrontMatter","problemMarkdownFrontMatterSchema"],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"yOAQA,eAAsB,EAA+B,EAAyD,CAC5G,IAAK,IAAM,KAAU,MAAMA,EAAAA,QAAG,SAAS,QAAQ,EAAY,CAAE,cAAe,EAAK,CAAC,EAAG,CAEnF,GADI,CAAC,EAAO,OAAO,GACf,EAAE,EAAO,OAAS,cAAgB,EAAO,KAAK,SAAS,aAAa,GAAI,SAE5E,IAAM,EAAW,MAAMA,EAAAA,QAAG,SAAS,SAASC,EAAAA,QAAK,KAAK,EAAO,WAAY,EAAO,IAAI,EAAG,MAAM,EAEvF,CAAE,eAAA,EAAgBC,EAAAA,QAAAA,CAA8E,CAAQ,EAE9G,OAAOC,EAAAA,iCAAiC,MAAM,CAAU,CAC1D,CAEA,MAAU,MAAM,+BAA+B,GAAY,CAC7D"}
@@ -1,2 +1,2 @@
1
- import{problemMarkdownFrontMatterSchema as e}from"../types/problem.js";import t from"node:path";import n from"node:fs";import r from"front-matter";async function i(i){for(let a of await n.promises.readdir(i,{withFileTypes:!0})){if(!a.isFile()||!(a.name===`problem.md`||a.name.endsWith(`.problem.md`)))continue;let{attributes:i}=r(await n.promises.readFile(t.join(a.parentPath,a.name),`utf8`));return e.parse(i)}throw Error(`problem markdown not found: ${i}`)}export{i as readProblemMarkdownFrontMatter};
1
+ import{problemMarkdownFrontMatterSchema as e}from"../types/problem.js";import t from"node:fs";import n from"node:path";import r from"front-matter";async function i(i){for(let a of await t.promises.readdir(i,{withFileTypes:!0})){if(!a.isFile()||!(a.name===`problem.md`||a.name.endsWith(`.problem.md`)))continue;let i=await t.promises.readFile(n.join(a.parentPath,a.name),`utf8`),{attributes:o}=r(i);return e.parse(o)}throw Error(`problem markdown not found: ${i}`)}export{i as readProblemMarkdownFrontMatter};
2
2
  //# sourceMappingURL=readProblemMarkdownFrontMatter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"readProblemMarkdownFrontMatter.js","names":[],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"mJAQA,eAAsB,EAA+B,EAAyD,CAC5G,IAAK,IAAM,KAAU,MAAM,EAAG,SAAS,QAAQ,EAAY,CAAE,cAAe,EAAK,CAAC,EAAG,CAEnF,GADI,CAAC,EAAO,OAAO,GACf,EAAE,EAAO,OAAS,cAAgB,EAAO,KAAK,SAAS,aAAa,GAAI,SAI5E,GAAM,CAAE,cAAgB,EAA8E,MAF/E,EAAG,SAAS,SAAS,EAAK,KAAK,EAAO,WAAY,EAAO,IAAI,EAAG,MAAM,CAEiB,EAE9G,OAAO,EAAiC,MAAM,CAAU,CAC1D,CAEA,MAAU,MAAM,+BAA+B,GAAY,CAC7D"}
1
+ {"version":3,"file":"readProblemMarkdownFrontMatter.js","names":[],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"mJAQA,eAAsB,EAA+B,EAAyD,CAC5G,IAAK,IAAM,KAAU,MAAM,EAAG,SAAS,QAAQ,EAAY,CAAE,cAAe,EAAK,CAAC,EAAG,CAEnF,GADI,CAAC,EAAO,OAAO,GACf,EAAE,EAAO,OAAS,cAAgB,EAAO,KAAK,SAAS,aAAa,GAAI,SAE5E,IAAM,EAAW,MAAM,EAAG,SAAS,SAAS,EAAK,KAAK,EAAO,WAAY,EAAO,IAAI,EAAG,MAAM,EAEvF,CAAE,cAAgB,EAA8E,CAAQ,EAE9G,OAAO,EAAiC,MAAM,CAAU,CAC1D,CAEA,MAAU,MAAM,+BAA+B,GAAY,CAC7D"}
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:path");t=e.__toESM(t,1);let n=require("node:fs");n=e.__toESM(n,1);const r=`_shared`;async function i(e){if(!n.default.existsSync(e))return[];let i=new Set,a=new Map,o=new Map,s=new Map,c=new Map;for(let r of await n.default.promises.readdir(e,{withFileTypes:!0}))if(r.isFile()){let{ext:e,name:s}=t.default.parse(r.name);if(e!==`.in`&&e!==`.out`)continue;let c=await n.default.promises.readFile(t.default.join(r.parentPath,r.name),`utf8`);i.add(s),e===`.in`&&a.set(s,c),e===`.out`&&o.set(s,c)}else if(r.isDirectory()){let{ext:e,name:n}=t.default.parse(r.name);if(e!==`.fin`&&e!==`.fout`)continue;i.add(n),e===`.fin`&&s.set(n,t.default.join(r.parentPath,r.name)),e===`.fout`&&c.set(n,t.default.join(r.parentPath,r.name))}let l=[...i].filter(e=>e!==r).toSorted().map(e=>({id:e,input:a.get(e),output:o.get(e),fileInputPath:s.get(e),fileOutputPath:c.get(e)}));return i.has(r)&&(l.shared={fileInputPath:s.get(r)}),l}exports.readTestCases=i;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:path");n=e.__toESM(n,1);const r=`_shared`;async function i(e){if(!t.default.existsSync(e))return[];let i=new Set,a=new Map,o=new Map,s=new Map,c=new Map;for(let r of await t.default.promises.readdir(e,{withFileTypes:!0}))if(r.isFile()){let{ext:e,name:s}=n.default.parse(r.name);if(e!==`.in`&&e!==`.out`)continue;let c=await t.default.promises.readFile(n.default.join(r.parentPath,r.name),`utf8`);i.add(s),e===`.in`&&a.set(s,c),e===`.out`&&o.set(s,c)}else if(r.isDirectory()){let{ext:e,name:t}=n.default.parse(r.name);if(e!==`.fin`&&e!==`.fout`)continue;i.add(t),e===`.fin`&&s.set(t,n.default.join(r.parentPath,r.name)),e===`.fout`&&c.set(t,n.default.join(r.parentPath,r.name))}let l=[...i].filter(e=>e!==r).toSorted().map(e=>({id:e,input:a.get(e),output:o.get(e),fileInputPath:s.get(e),fileOutputPath:c.get(e)}));return i.has(r)&&(l.shared={fileInputPath:s.get(r)}),l}exports.readTestCases=i;
2
2
  //# sourceMappingURL=readTestCases.cjs.map
@@ -1,2 +1,2 @@
1
- import e from"node:path";import t from"node:fs";const n=`_shared`;async function r(r){if(!t.existsSync(r))return[];let i=new Set,a=new Map,o=new Map,s=new Map,c=new Map;for(let n of await t.promises.readdir(r,{withFileTypes:!0}))if(n.isFile()){let{ext:r,name:s}=e.parse(n.name);if(r!==`.in`&&r!==`.out`)continue;let c=await t.promises.readFile(e.join(n.parentPath,n.name),`utf8`);i.add(s),r===`.in`&&a.set(s,c),r===`.out`&&o.set(s,c)}else if(n.isDirectory()){let{ext:t,name:r}=e.parse(n.name);if(t!==`.fin`&&t!==`.fout`)continue;i.add(r),t===`.fin`&&s.set(r,e.join(n.parentPath,n.name)),t===`.fout`&&c.set(r,e.join(n.parentPath,n.name))}let l=[...i].filter(e=>e!==n).toSorted().map(e=>({id:e,input:a.get(e),output:o.get(e),fileInputPath:s.get(e),fileOutputPath:c.get(e)}));return i.has(n)&&(l.shared={fileInputPath:s.get(n)}),l}export{r as readTestCases};
1
+ import e from"node:fs";import t from"node:path";const n=`_shared`;async function r(r){if(!e.existsSync(r))return[];let i=new Set,a=new Map,o=new Map,s=new Map,c=new Map;for(let n of await e.promises.readdir(r,{withFileTypes:!0}))if(n.isFile()){let{ext:r,name:s}=t.parse(n.name);if(r!==`.in`&&r!==`.out`)continue;let c=await e.promises.readFile(t.join(n.parentPath,n.name),`utf8`);i.add(s),r===`.in`&&a.set(s,c),r===`.out`&&o.set(s,c)}else if(n.isDirectory()){let{ext:e,name:r}=t.parse(n.name);if(e!==`.fin`&&e!==`.fout`)continue;i.add(r),e===`.fin`&&s.set(r,t.join(n.parentPath,n.name)),e===`.fout`&&c.set(r,t.join(n.parentPath,n.name))}let l=[...i].filter(e=>e!==n).toSorted().map(e=>({id:e,input:a.get(e),output:o.get(e),fileInputPath:s.get(e),fileOutputPath:c.get(e)}));return i.has(n)&&(l.shared={fileInputPath:s.get(n)}),l}export{r as readTestCases};
2
2
  //# sourceMappingURL=readTestCases.js.map
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./printDebugBanner.cjs"),n=require("./findModelAnswerDirs.cjs");let r=require("node:path");r=e.__toESM(r,1);async function i(e,i){if(i)return{cwds:[{cwd:i,expectedResult:`accepted`}],isDebugMode:!1};let[a,o]=await Promise.all([n.findModelAnswerDirs(e),n.findFailingModelAnswerDirs(e)]);if(a.length===0&&o.length===0)throw Error(`cwd argument required (no model answer directories found in ${r.default.join(e,n.MODEL_ANSWERS_DIRNAME)} or ${r.default.join(e,n.FAILING_MODEL_ANSWERS_DIRNAME)})`);let c=s(),l=r.default.relative(e,a[0]??o[0]??``)||`<model_answer>`;return t.printDebugBanner([`[DEBUG MODE] cwd not provided -- judging against all model answers`,``,`Problem dir : ${e}`,`Model answers (${a.length}):`,...a.map(t=>` - ${r.default.relative(e,t)}`),`Failing model answers (${o.length}):`,...o.map(t=>` - ${r.default.relative(e,t)}`),``,`To judge a single cwd (e.g., a user submission), pass it as the first argument:`,` bun ${c} <cwd> [params-json]`,`For example:`,` bun ${c} ${l}`,` bun ${c} ${l} '{"language":"python"}'`]),{cwds:[...a.map(e=>({cwd:e,expectedResult:`accepted`})),...o.map(e=>({cwd:e,expectedResult:`rejected`}))],isDebugMode:!0}}function a(e,n){let i=r.default.relative(e,n.cwd)||n.cwd,a=s();t.printDebugBanner([`[DEBUG MODE] judging: ${i}`,`Expected result: ${n.expectedResult}`,``,`To judge only this cwd as a normal submission:`,` bun ${a} ${i}`,`Run without a cwd to check debug-mode expectations.`])}function o(e,n){t.printDebugBanner([`[DEBUG MODE] expectation failed: ${r.default.relative(e,n.cwd)||n.cwd}`,`Expected result: ${n.expectedResult}`,n.expectedResult===`accepted`?`The model answer was rejected by the judge.`:`The failing model answer was accepted by the judge.`])}function s(){let e=process.argv[1];return e?r.default.basename(e):`judge.ts`}exports.printDebugCwdBanner=a,exports.printDebugExpectationFailureBanner=o,exports.resolveCwds=i;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./printDebugBanner.cjs"),n=require("./findModelAnswerDirs.cjs");let r=require("node:path");r=e.__toESM(r,1);async function i(e,i){if(i)return{cwds:[{cwd:i,expectedResult:`accepted`}],isDebugMode:!1};let[a,o]=await Promise.all([n.findModelAnswerDirs(e),n.findFailingModelAnswerDirs(e)]);if(a.length===0&&o.length===0)throw Error(`cwd argument required (no model answer directories found in ${r.default.join(e,n.MODEL_ANSWERS_DIRNAME)} or ${r.default.join(e,n.FAILING_MODEL_ANSWERS_DIRNAME)})`);let c=s(),l=r.default.relative(e,a[0]??o[0]??``)||`<model_answer>`;return t.printDebugBanner([`[DEBUG MODE] cwd not provided -- judging against all model answers`,``,`Problem dir : ${e}`,`Model answers (${a.length}):`,...a.map(t=>` - ${r.default.relative(e,t)}`),`Failing model answers (${o.length}):`,...o.map(t=>` - ${r.default.relative(e,t)}`),``,`To judge a single cwd (e.g., a user submission), pass it as the first argument:`,` bun ${c} <cwd> [params-json]`,`For example:`,` bun ${c} ${l}`,` bun ${c} ${l} '{"language":"python"}'`]),{cwds:[...a.map(e=>({cwd:e,expectedResult:`accepted`})),...o.map(e=>({cwd:e,expectedResult:`rejected`}))],isDebugMode:!0}}function a(e,n){let i=r.default.relative(e,n.cwd)||n.cwd,a=s();t.printDebugBanner([`[DEBUG MODE] judging: ${i}`,`Expected result: ${n.expectedResult}`,``,`To judge only this cwd as a normal submission:`,` bun ${a} ${i}`,`Run without a cwd to check debug-mode expectations.`])}function o(e,n){let i=r.default.relative(e,n.cwd)||n.cwd;t.printDebugBanner([`[DEBUG MODE] expectation failed: ${i}`,`Expected result: ${n.expectedResult}`,n.expectedResult===`accepted`?`The model answer was rejected by the judge.`:`The failing model answer was accepted by the judge.`])}function s(){let e=process.argv[1];return e?r.default.basename(e):`judge.ts`}exports.printDebugCwdBanner=a,exports.printDebugExpectationFailureBanner=o,exports.resolveCwds=i;
2
2
  //# sourceMappingURL=resolveCwds.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveCwds.cjs","names":["findModelAnswerDirs","findFailingModelAnswerDirs","path","MODEL_ANSWERS_DIRNAME","FAILING_MODEL_ANSWERS_DIRNAME"],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"yLAgCA,eAAsB,EAAY,EAAoB,EAAmD,CACvG,GAAI,EAAQ,MAAO,CAAE,KAAM,CAAC,CAAE,IAAK,EAAQ,eAAgB,UAAW,CAAC,EAAG,YAAa,EAAM,EAE7F,GAAM,CAAC,EAAiB,GAA0B,MAAM,QAAQ,IAAI,CAClEA,EAAAA,oBAAoB,CAAU,EAC9BC,EAAAA,2BAA2B,CAAU,CACvC,CAAC,EACD,GAAI,EAAgB,SAAW,GAAK,EAAuB,SAAW,EACpE,MAAU,MACR,+DAA+DC,EAAAA,QAAK,KAAK,EAAYC,EAAAA,qBAAqB,EAAE,MAAMD,EAAAA,QAAK,KAAK,EAAYE,EAAAA,6BAA6B,EAAE,EACzK,EAGF,IAAM,EAAa,EAAqB,EAClC,EACJF,EAAAA,QAAK,SAAS,EAAY,EAAgB,IAAM,EAAuB,IAAM,EAAE,GAAK,iBAiBtF,OAhBA,EAAA,iBAAiB,CACf,qEACA,GACA,iBAAiB,IACjB,kBAAkB,EAAgB,OAAO,IACzC,GAAG,EAAgB,IAAK,GAAQ,OAAOA,EAAAA,QAAK,SAAS,EAAY,CAAG,GAAG,EACvE,0BAA0B,EAAuB,OAAO,IACxD,GAAG,EAAuB,IAAK,GAAQ,OAAOA,EAAAA,QAAK,SAAS,EAAY,CAAG,GAAG,EAC9E,GACA,kFACA,SAAS,EAAW,sBACpB,eACA,SAAS,EAAW,GAAG,IACvB,SAAS,EAAW,GAAG,EAAc,yBACvC,CAAC,EAEM,CACL,KAAM,CACJ,GAAG,EAAgB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,EAC9E,GAAG,EAAuB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,CACvF,EACA,YAAa,EACf,CACF,CAMA,SAAgB,EAAoB,EAAoB,EAAgC,CACtF,IAAM,EAAcA,EAAAA,QAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,IACxE,EAAa,EAAqB,EACxC,EAAA,iBAAiB,CACf,yBAAyB,IACzB,oBAAoB,EAAY,iBAChC,GACA,iDACA,SAAS,EAAW,GAAG,IACvB,qDACF,CAAC,CACH,CAEA,SAAgB,EAAmC,EAAoB,EAAgC,CAErG,EAAA,iBAAiB,CACf,oCAFkBA,EAAAA,QAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,MAG5E,oBAAoB,EAAY,iBAChC,EAAY,iBAAmB,WAC3B,8CACA,qDACN,CAAC,CACH,CAEA,SAAS,GAA+B,CACtC,IAAM,EAAa,QAAQ,KAAK,GAChC,OAAO,EAAaA,EAAAA,QAAK,SAAS,CAAU,EAAI,UAClD"}
1
+ {"version":3,"file":"resolveCwds.cjs","names":["findModelAnswerDirs","findFailingModelAnswerDirs","path","MODEL_ANSWERS_DIRNAME","FAILING_MODEL_ANSWERS_DIRNAME"],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"yLAgCA,eAAsB,EAAY,EAAoB,EAAmD,CACvG,GAAI,EAAQ,MAAO,CAAE,KAAM,CAAC,CAAE,IAAK,EAAQ,eAAgB,UAAW,CAAC,EAAG,YAAa,EAAM,EAE7F,GAAM,CAAC,EAAiB,GAA0B,MAAM,QAAQ,IAAI,CAClEA,EAAAA,oBAAoB,CAAU,EAC9BC,EAAAA,2BAA2B,CAAU,CACvC,CAAC,EACD,GAAI,EAAgB,SAAW,GAAK,EAAuB,SAAW,EACpE,MAAU,MACR,+DAA+DC,EAAAA,QAAK,KAAK,EAAYC,EAAAA,qBAAqB,EAAE,MAAMD,EAAAA,QAAK,KAAK,EAAYE,EAAAA,6BAA6B,EAAE,EACzK,EAGF,IAAM,EAAa,EAAqB,EAClC,EACJF,EAAAA,QAAK,SAAS,EAAY,EAAgB,IAAM,EAAuB,IAAM,EAAE,GAAK,iBAiBtF,OAhBA,EAAA,iBAAiB,CACf,qEACA,GACA,iBAAiB,IACjB,kBAAkB,EAAgB,OAAO,IACzC,GAAG,EAAgB,IAAK,GAAQ,OAAOA,EAAAA,QAAK,SAAS,EAAY,CAAG,GAAG,EACvE,0BAA0B,EAAuB,OAAO,IACxD,GAAG,EAAuB,IAAK,GAAQ,OAAOA,EAAAA,QAAK,SAAS,EAAY,CAAG,GAAG,EAC9E,GACA,kFACA,SAAS,EAAW,sBACpB,eACA,SAAS,EAAW,GAAG,IACvB,SAAS,EAAW,GAAG,EAAc,yBACvC,CAAC,EAEM,CACL,KAAM,CACJ,GAAG,EAAgB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,EAC9E,GAAG,EAAuB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,CACvF,EACA,YAAa,EACf,CACF,CAMA,SAAgB,EAAoB,EAAoB,EAAgC,CACtF,IAAM,EAAcA,EAAAA,QAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,IACxE,EAAa,EAAqB,EACxC,EAAA,iBAAiB,CACf,yBAAyB,IACzB,oBAAoB,EAAY,iBAChC,GACA,iDACA,SAAS,EAAW,GAAG,IACvB,qDACF,CAAC,CACH,CAEA,SAAgB,EAAmC,EAAoB,EAAgC,CACrG,IAAM,EAAcA,EAAAA,QAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,IAC9E,EAAA,iBAAiB,CACf,oCAAoC,IACpC,oBAAoB,EAAY,iBAChC,EAAY,iBAAmB,WAC3B,8CACA,qDACN,CAAC,CACH,CAEA,SAAS,GAA+B,CACtC,IAAM,EAAa,QAAQ,KAAK,GAChC,OAAO,EAAaA,EAAAA,QAAK,SAAS,CAAU,EAAI,UAClD"}
@@ -1,2 +1,2 @@
1
- import{printDebugBanner as e}from"./printDebugBanner.js";import{FAILING_MODEL_ANSWERS_DIRNAME as t,MODEL_ANSWERS_DIRNAME as n,findFailingModelAnswerDirs as r,findModelAnswerDirs as i}from"./findModelAnswerDirs.js";import a from"node:path";async function o(o,s){if(s)return{cwds:[{cwd:s,expectedResult:`accepted`}],isDebugMode:!1};let[c,u]=await Promise.all([i(o),r(o)]);if(c.length===0&&u.length===0)throw Error(`cwd argument required (no model answer directories found in ${a.join(o,n)} or ${a.join(o,t)})`);let d=l(),f=a.relative(o,c[0]??u[0]??``)||`<model_answer>`;return e([`[DEBUG MODE] cwd not provided -- judging against all model answers`,``,`Problem dir : ${o}`,`Model answers (${c.length}):`,...c.map(e=>` - ${a.relative(o,e)}`),`Failing model answers (${u.length}):`,...u.map(e=>` - ${a.relative(o,e)}`),``,`To judge a single cwd (e.g., a user submission), pass it as the first argument:`,` bun ${d} <cwd> [params-json]`,`For example:`,` bun ${d} ${f}`,` bun ${d} ${f} '{"language":"python"}'`]),{cwds:[...c.map(e=>({cwd:e,expectedResult:`accepted`})),...u.map(e=>({cwd:e,expectedResult:`rejected`}))],isDebugMode:!0}}function s(t,n){let r=a.relative(t,n.cwd)||n.cwd,i=l();e([`[DEBUG MODE] judging: ${r}`,`Expected result: ${n.expectedResult}`,``,`To judge only this cwd as a normal submission:`,` bun ${i} ${r}`,`Run without a cwd to check debug-mode expectations.`])}function c(t,n){e([`[DEBUG MODE] expectation failed: ${a.relative(t,n.cwd)||n.cwd}`,`Expected result: ${n.expectedResult}`,n.expectedResult===`accepted`?`The model answer was rejected by the judge.`:`The failing model answer was accepted by the judge.`])}function l(){let e=process.argv[1];return e?a.basename(e):`judge.ts`}export{s as printDebugCwdBanner,c as printDebugExpectationFailureBanner,o as resolveCwds};
1
+ import{printDebugBanner as e}from"./printDebugBanner.js";import{FAILING_MODEL_ANSWERS_DIRNAME as t,MODEL_ANSWERS_DIRNAME as n,findFailingModelAnswerDirs as r,findModelAnswerDirs as i}from"./findModelAnswerDirs.js";import a from"node:path";async function o(o,s){if(s)return{cwds:[{cwd:s,expectedResult:`accepted`}],isDebugMode:!1};let[c,u]=await Promise.all([i(o),r(o)]);if(c.length===0&&u.length===0)throw Error(`cwd argument required (no model answer directories found in ${a.join(o,n)} or ${a.join(o,t)})`);let d=l(),f=a.relative(o,c[0]??u[0]??``)||`<model_answer>`;return e([`[DEBUG MODE] cwd not provided -- judging against all model answers`,``,`Problem dir : ${o}`,`Model answers (${c.length}):`,...c.map(e=>` - ${a.relative(o,e)}`),`Failing model answers (${u.length}):`,...u.map(e=>` - ${a.relative(o,e)}`),``,`To judge a single cwd (e.g., a user submission), pass it as the first argument:`,` bun ${d} <cwd> [params-json]`,`For example:`,` bun ${d} ${f}`,` bun ${d} ${f} '{"language":"python"}'`]),{cwds:[...c.map(e=>({cwd:e,expectedResult:`accepted`})),...u.map(e=>({cwd:e,expectedResult:`rejected`}))],isDebugMode:!0}}function s(t,n){let r=a.relative(t,n.cwd)||n.cwd,i=l();e([`[DEBUG MODE] judging: ${r}`,`Expected result: ${n.expectedResult}`,``,`To judge only this cwd as a normal submission:`,` bun ${i} ${r}`,`Run without a cwd to check debug-mode expectations.`])}function c(t,n){let r=a.relative(t,n.cwd)||n.cwd;e([`[DEBUG MODE] expectation failed: ${r}`,`Expected result: ${n.expectedResult}`,n.expectedResult===`accepted`?`The model answer was rejected by the judge.`:`The failing model answer was accepted by the judge.`])}function l(){let e=process.argv[1];return e?a.basename(e):`judge.ts`}export{s as printDebugCwdBanner,c as printDebugExpectationFailureBanner,o as resolveCwds};
2
2
  //# sourceMappingURL=resolveCwds.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveCwds.js","names":[],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"+OAgCA,eAAsB,EAAY,EAAoB,EAAmD,CACvG,GAAI,EAAQ,MAAO,CAAE,KAAM,CAAC,CAAE,IAAK,EAAQ,eAAgB,UAAW,CAAC,EAAG,YAAa,EAAM,EAE7F,GAAM,CAAC,EAAiB,GAA0B,MAAM,QAAQ,IAAI,CAClE,EAAoB,CAAU,EAC9B,EAA2B,CAAU,CACvC,CAAC,EACD,GAAI,EAAgB,SAAW,GAAK,EAAuB,SAAW,EACpE,MAAU,MACR,+DAA+D,EAAK,KAAK,EAAY,CAAqB,EAAE,MAAM,EAAK,KAAK,EAAY,CAA6B,EAAE,EACzK,EAGF,IAAM,EAAa,EAAqB,EAClC,EACJ,EAAK,SAAS,EAAY,EAAgB,IAAM,EAAuB,IAAM,EAAE,GAAK,iBAiBtF,OAhBA,EAAiB,CACf,qEACA,GACA,iBAAiB,IACjB,kBAAkB,EAAgB,OAAO,IACzC,GAAG,EAAgB,IAAK,GAAQ,OAAO,EAAK,SAAS,EAAY,CAAG,GAAG,EACvE,0BAA0B,EAAuB,OAAO,IACxD,GAAG,EAAuB,IAAK,GAAQ,OAAO,EAAK,SAAS,EAAY,CAAG,GAAG,EAC9E,GACA,kFACA,SAAS,EAAW,sBACpB,eACA,SAAS,EAAW,GAAG,IACvB,SAAS,EAAW,GAAG,EAAc,yBACvC,CAAC,EAEM,CACL,KAAM,CACJ,GAAG,EAAgB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,EAC9E,GAAG,EAAuB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,CACvF,EACA,YAAa,EACf,CACF,CAMA,SAAgB,EAAoB,EAAoB,EAAgC,CACtF,IAAM,EAAc,EAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,IACxE,EAAa,EAAqB,EACxC,EAAiB,CACf,yBAAyB,IACzB,oBAAoB,EAAY,iBAChC,GACA,iDACA,SAAS,EAAW,GAAG,IACvB,qDACF,CAAC,CACH,CAEA,SAAgB,EAAmC,EAAoB,EAAgC,CAErG,EAAiB,CACf,oCAFkB,EAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,MAG5E,oBAAoB,EAAY,iBAChC,EAAY,iBAAmB,WAC3B,8CACA,qDACN,CAAC,CACH,CAEA,SAAS,GAA+B,CACtC,IAAM,EAAa,QAAQ,KAAK,GAChC,OAAO,EAAa,EAAK,SAAS,CAAU,EAAI,UAClD"}
1
+ {"version":3,"file":"resolveCwds.js","names":[],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"+OAgCA,eAAsB,EAAY,EAAoB,EAAmD,CACvG,GAAI,EAAQ,MAAO,CAAE,KAAM,CAAC,CAAE,IAAK,EAAQ,eAAgB,UAAW,CAAC,EAAG,YAAa,EAAM,EAE7F,GAAM,CAAC,EAAiB,GAA0B,MAAM,QAAQ,IAAI,CAClE,EAAoB,CAAU,EAC9B,EAA2B,CAAU,CACvC,CAAC,EACD,GAAI,EAAgB,SAAW,GAAK,EAAuB,SAAW,EACpE,MAAU,MACR,+DAA+D,EAAK,KAAK,EAAY,CAAqB,EAAE,MAAM,EAAK,KAAK,EAAY,CAA6B,EAAE,EACzK,EAGF,IAAM,EAAa,EAAqB,EAClC,EACJ,EAAK,SAAS,EAAY,EAAgB,IAAM,EAAuB,IAAM,EAAE,GAAK,iBAiBtF,OAhBA,EAAiB,CACf,qEACA,GACA,iBAAiB,IACjB,kBAAkB,EAAgB,OAAO,IACzC,GAAG,EAAgB,IAAK,GAAQ,OAAO,EAAK,SAAS,EAAY,CAAG,GAAG,EACvE,0BAA0B,EAAuB,OAAO,IACxD,GAAG,EAAuB,IAAK,GAAQ,OAAO,EAAK,SAAS,EAAY,CAAG,GAAG,EAC9E,GACA,kFACA,SAAS,EAAW,sBACpB,eACA,SAAS,EAAW,GAAG,IACvB,SAAS,EAAW,GAAG,EAAc,yBACvC,CAAC,EAEM,CACL,KAAM,CACJ,GAAG,EAAgB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,EAC9E,GAAG,EAAuB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,CACvF,EACA,YAAa,EACf,CACF,CAMA,SAAgB,EAAoB,EAAoB,EAAgC,CACtF,IAAM,EAAc,EAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,IACxE,EAAa,EAAqB,EACxC,EAAiB,CACf,yBAAyB,IACzB,oBAAoB,EAAY,iBAChC,GACA,iDACA,SAAS,EAAW,GAAG,IACvB,qDACF,CAAC,CACH,CAEA,SAAgB,EAAmC,EAAoB,EAAgC,CACrG,IAAM,EAAc,EAAK,SAAS,EAAY,EAAY,GAAG,GAAK,EAAY,IAC9E,EAAiB,CACf,oCAAoC,IACpC,oBAAoB,EAAY,iBAChC,EAAY,iBAAmB,WAC3B,8CACA,qDACN,CAAC,CACH,CAEA,SAAS,GAA+B,CACtC,IAAM,EAAa,QAAQ,KAAK,GAChC,OAAO,EAAa,EAAK,SAAS,CAAU,EAAI,UAClD"}
@@ -1,2 +1,2 @@
1
- "use strict";const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:child_process");t=e.__toESM(t,1);let n=require("node:fs/promises");n=e.__toESM(n,1);let r=require("node:os");r=e.__toESM(r,1);let i=require("node:path");i=e.__toESM(i,1);const a={bun:[`package.json`,`bun.lock`,`bun.lockb`],cargo:[`Cargo.toml`,`Cargo.lock`],go:[`go.mod`,`go.sum`],gradle:[`build.gradle`,`build.gradle.kts`,`settings.gradle`,`settings.gradle.kts`,`gradle.properties`,`gradle.lockfile`,`buildscript-gradle.lockfile`,`gradle`,`gradlew`,`gradlew.bat`],maven:[`pom.xml`,`.mvn`,`mvnw`,`mvnw.cmd`],npm:[`package.json`,`package-lock.json`],pnpm:[`package.json`,`pnpm-lock.yaml`,`pnpm-workspace.yaml`],ruby:[`Gemfile`,`Gemfile.lock`,`.ruby-version`],uv:[`pyproject.toml`,`uv.lock`],yarn:[`package.json`,`yarn.lock`,`.yarnrc`,`.yarnrc.yml`,`.yarn`]},o={bun:f,cargo:p,go:m,gradle:h,maven:g,npm:_,pnpm:v,ruby:y,uv:b,yarn:x},s=k();async function c(e){let t=await n.default.mkdtemp(i.default.join(r.default.tmpdir(),e.tempDirPrefix??`exercode-`));try{await n.default.cp(e.cwd,t,{recursive:!0}),await E({packageManager:e.packageManager,projectDir:e.projectDir,runDir:t,projectFilePaths:e.projectFilePaths});let r=e.env?{...process.env,...e.env}:process.env,i=await u(e.packageManager,t),a=typeof e.command==`function`?e.command({runDir:t}):e.command,o=Date.now(),s=e.outputLimitBytes??52428800,c;if(i&&(c=await O(i,{cwd:t,env:r,outputLimitBytes:s,stdin:``,timeLimitSeconds:e.timeLimitSeconds}),d(c)))return l({elapsedTimeSeconds:(Date.now()-o)/1e3,options:e,result:c});let f=e.timeLimitSeconds-(Date.now()-o)/1e3;if(f<=0)return{stdin:e.stdin??``,stdout:c?.stdout??``,stderr:c?.stderr??``,status:0,timeSeconds:e.timeLimitSeconds+.001,memoryBytes:c?.memoryBytes??0,timedOut:!0,signal:c?.signal,outputLimitExceeded:!1};let p=await O(a,{cwd:t,env:r,outputLimitBytes:s,stdin:e.stdin??``,timeLimitSeconds:f}),m=(Date.now()-o)/1e3;return l(c?{elapsedTimeSeconds:m,options:e,result:{...p,timeSeconds:c.timeSeconds+p.timeSeconds,memoryBytes:Math.max(c.memoryBytes,p.memoryBytes)}}:{elapsedTimeSeconds:m,options:e,result:p})}finally{await n.default.rm(t,{force:!0,recursive:!0})}}function l(e){return{stdin:e.options.stdin??``,stdout:e.result.stdout,stderr:e.result.stderr,status:e.result.timedOut||e.result.outputLimitExceeded?0:e.result.status,timeSeconds:e.result.timedOut?e.options.timeLimitSeconds+.001:e.result.timeSeconds||e.elapsedTimeSeconds,memoryBytes:e.result.memoryBytes,timedOut:e.result.timedOut,signal:e.result.signal,outputLimitExceeded:e.result.outputLimitExceeded}}function u(e,t){return o[e](t)}function d(e){return e.status!==0||e.timedOut||e.outputLimitExceeded}async function f(e){if(await w(i.default.join(e,`package.json`)))return await C(e,[`bun.lock`,`bun.lockb`])?[`bun`,`install`,`--frozen-lockfile`,`--silent`]:[`bun`,`install`,`--silent`]}async function p(e){if(await w(i.default.join(e,`Cargo.toml`)))return await w(i.default.join(e,`Cargo.lock`))?[`cargo`,`fetch`,`--locked`]:[`cargo`,`fetch`]}async function m(e){if(await w(i.default.join(e,`go.mod`)))return[`go`,`mod`,`download`]}async function h(e){if(!await C(e,[`build.gradle`,`build.gradle.kts`,`settings.gradle`,`settings.gradle.kts`,`gradlew`,`gradlew.bat`]))return;let t=[`--no-daemon`,`--quiet`,`dependencies`];return process.platform===`win32`?await w(i.default.join(e,`gradlew.bat`))?[`cmd.exe`,`/c`,`gradlew.bat`,...t]:[`gradle`,...t]:await w(i.default.join(e,`gradlew`))?[`sh`,`./gradlew`,...t]:[`gradle`,...t]}async function g(e){if(!await w(i.default.join(e,`pom.xml`)))return;let t=[`-q`,`dependency:go-offline`];return process.platform===`win32`?await w(i.default.join(e,`mvnw.cmd`))?[`cmd.exe`,`/c`,`mvnw.cmd`,...t]:[`mvn`,...t]:await w(i.default.join(e,`mvnw`))?[`sh`,`./mvnw`,...t]:[`mvn`,...t]}async function _(e){if(await w(i.default.join(e,`package.json`)))return await w(i.default.join(e,`package-lock.json`))?[`npm`,`ci`,`--silent`]:[`npm`,`install`,`--silent`]}async function v(e){if(await w(i.default.join(e,`package.json`)))return await w(i.default.join(e,`pnpm-lock.yaml`))?[`pnpm`,`install`,`--frozen-lockfile`,`--silent`]:[`pnpm`,`install`,`--silent`]}async function y(e){if(await w(i.default.join(e,`Gemfile`)))return await w(i.default.join(e,`Gemfile.lock`))?[`bundle`,`install`,`--frozen`,`--quiet`]:[`bundle`,`install`,`--quiet`]}async function b(){}async function x(e){if(!await w(i.default.join(e,`package.json`)))return;let t=await S(e),n=await w(i.default.join(e,`yarn.lock`));return t?n?[`yarn`,`install`,`--immutable`]:[`yarn`,`install`]:n?[`yarn`,`install`,`--frozen-lockfile`,`--silent`]:[`yarn`,`install`,`--silent`]}async function S(e){if(await w(i.default.join(e,`.yarnrc.yml`)))return!0;let t=await T(i.default.join(e,`package.json`)),n=typeof t.packageManager==`string`?t.packageManager:void 0,r=/^yarn@(\d+)/.exec(n??``)?.[1];return r!==void 0&&Number(r)>=2}async function C(e,t){for(let n of t)if(await w(i.default.join(e,n)))return!0;return!1}async function w(e){try{return await n.default.access(e),!0}catch(e){if((typeof e==`object`&&e&&`code`in e?e.code:void 0)!==`ENOENT`)throw e;return!1}}async function T(e){try{let t=JSON.parse(await n.default.readFile(e,`utf8`));return typeof t==`object`&&t&&!Array.isArray(t)?t:{}}catch(e){if(e instanceof SyntaxError||(typeof e==`object`&&e&&`code`in e?e.code:void 0)===`ENOENT`)return{};throw e}}async function E(e){for(let t of e.projectFilePaths??a[e.packageManager])await D(i.default.join(e.projectDir,t),i.default.join(e.runDir,t))}async function D(e,t){try{await n.default.cp(e,t,{recursive:!0})}catch(e){if((typeof e==`object`&&e&&`code`in e?e.code:void 0)!==`ENOENT`)throw e}}async function O(e,n){let r=s===void 0?void 0:i.default.join(n.cwd,`.exercode-time-result`),a=s===void 0?e:[...s,`--output=${r}`,...e],o=t.default.spawn(a[0],a.slice(1),{cwd:n.cwd,detached:process.platform!==`win32`,env:n.env,stdio:[`pipe`,`pipe`,`pipe`]}),c=[],l=[],u=0,d=!1,f=!1,p=(e,t)=>{if(u>=n.outputLimitBytes){t.byteLength>0&&(f=!0,A(o,`SIGKILL`));return}let r=n.outputLimitBytes-u,i=t.byteLength>r?t.subarray(0,r):t;e.push(i),u+=i.byteLength,t.byteLength>r&&(f=!0,A(o,`SIGKILL`))};o.stdout.on(`data`,e=>p(c,e)),o.stderr.on(`data`,e=>p(l,e));let m=setTimeout(()=>{d=!0,A(o,`SIGTERM`)},n.timeLimitSeconds*1e3),h=setTimeout(()=>{d&&A(o,`SIGKILL`)},n.timeLimitSeconds*1e3+1e3);h.unref();let{status:g,signal:_}=await new Promise((e,t)=>{let r=!1,i,a=e=>{r||(i=e,A(o,`SIGKILL`),o.pid===void 0&&(r=!0,t(e)))};o.on(`error`,a),o.stdin.on(`error`,e=>{e.code!==`EPIPE`&&a(e)}),o.on(`close`,(n,a)=>{if(!r){if(r=!0,i){t(i);return}e({status:n??void 0,signal:a??void 0})}}),o.stdin.end(n.stdin)}).finally(()=>{clearTimeout(m),clearTimeout(h)}),{timeSeconds:v,memoryBytes:y}=r===void 0?{timeSeconds:0,memoryBytes:0}:await j(r);return{stdout:Buffer.concat(c).toString(),stderr:Buffer.concat(l).toString(),status:g,timeSeconds:v,memoryBytes:y,timedOut:d,signal:_,outputLimitExceeded:f}}function k(){let e=r.default.platform()===`darwin`?`gtime`:`/usr/bin/time`,n=t.default.spawnSync(e,[`--version`],{stdio:`ignore`});if(!(n.error||n.status!==0))return[e,`--format`,`%e %M`]}function A(e,t){if(e.pid!==void 0)try{if(process.platform===`win32`){e.kill(t);return}process.kill(-e.pid,t)}catch(e){let t=typeof e==`object`&&e&&`code`in e?e.code:void 0;if(t!==`ESRCH`&&t!==`EPERM`)throw e}}async function j(e){let t;try{t=await n.default.readFile(e,`utf8`)}catch(e){if((typeof e==`object`&&e&&`code`in e?e.code:void 0)!==`ENOENT`)throw e;return{timeSeconds:0,memoryBytes:0}}let r=/(\d+(?:[.,]\d+)?) (\d+)\s*$/.exec(t);return r?{timeSeconds:Number(r[1].replace(`,`,`.`)),memoryBytes:Number(r[2])*1024}:{timeSeconds:0,memoryBytes:0}}exports.copyPackageManagerProjectFiles=E,exports.runCommandInTemporaryPackageManagerProject=c;
1
+ "use strict";const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./sandboxUser.cjs"),n=require("./safeFs.cjs");let r=require("node:child_process");r=e.__toESM(r,1);let i=require("node:fs");i=e.__toESM(i,1);let a=require("node:fs/promises");a=e.__toESM(a,1);let o=require("node:os");o=e.__toESM(o,1);let s=require("node:path");s=e.__toESM(s,1);const c={bun:[`package.json`,`bun.lock`,`bun.lockb`],cargo:[`Cargo.toml`,`Cargo.lock`],go:[`go.mod`,`go.sum`],gradle:[`build.gradle`,`build.gradle.kts`,`settings.gradle`,`settings.gradle.kts`,`gradle.properties`,`gradle.lockfile`,`buildscript-gradle.lockfile`,`gradle`,`gradlew`,`gradlew.bat`],maven:[`pom.xml`,`.mvn`,`mvnw`,`mvnw.cmd`],npm:[`package.json`,`package-lock.json`],pnpm:[`package.json`,`pnpm-lock.yaml`,`pnpm-workspace.yaml`],ruby:[`Gemfile`,`Gemfile.lock`,`.ruby-version`],uv:[`pyproject.toml`,`uv.lock`],yarn:[`package.json`,`yarn.lock`,`.yarnrc`,`.yarnrc.yml`,`.yarn`]},l={bun:h,cargo:g,go:_,gradle:v,maven:y,npm:b,pnpm:x,ruby:S,uv:C,yarn:w},u=M();async function d(e){let n=await a.default.mkdtemp(s.default.join(o.default.tmpdir(),e.tempDirPrefix??`exercode-`));try{await a.default.cp(e.cwd,n,{recursive:!0}),await k({packageManager:e.packageManager,projectDir:e.projectDir,runDir:n,projectFilePaths:e.projectFilePaths}),t.makeAccessibleToSandboxUser(n);let r=e.env?{...process.env,...e.env}:process.env,i=await p(e.packageManager,n),o=typeof e.command==`function`?e.command({runDir:n}):e.command,s=Date.now(),c=e.outputLimitBytes??52428800,l;if(i&&(l=await j(i,{cwd:n,env:r,outputLimitBytes:c,stdin:``,timeLimitSeconds:e.timeLimitSeconds}),m(l)))return f({elapsedTimeSeconds:(Date.now()-s)/1e3,options:e,result:l});let u=e.timeLimitSeconds-(Date.now()-s)/1e3;if(u<=0)return{stdin:e.stdin??``,stdout:l?.stdout??``,stderr:l?.stderr??``,status:0,timeSeconds:e.timeLimitSeconds+.001,memoryBytes:l?.memoryBytes??0,timedOut:!0,signal:l?.signal,outputLimitExceeded:!1};let d=await j(o,{cwd:n,env:r,outputLimitBytes:c,stdin:e.stdin??``,timeLimitSeconds:u}),h=(Date.now()-s)/1e3;return f(l?{elapsedTimeSeconds:h,options:e,result:{...d,timeSeconds:l.timeSeconds+d.timeSeconds,memoryBytes:Math.max(l.memoryBytes,d.memoryBytes)}}:{elapsedTimeSeconds:h,options:e,result:d})}finally{try{t.sandboxUserName&&t.killSandboxUserProcesses()}finally{await t.forceRemove(n)}}}function f(e){return{stdin:e.options.stdin??``,stdout:e.result.stdout,stderr:e.result.stderr,status:e.result.timedOut||e.result.outputLimitExceeded?0:e.result.status,timeSeconds:e.result.timedOut?e.options.timeLimitSeconds+.001:e.result.timeSeconds||e.elapsedTimeSeconds,memoryBytes:e.result.memoryBytes,timedOut:e.result.timedOut,signal:e.result.signal,outputLimitExceeded:e.result.outputLimitExceeded}}function p(e,t){return l[e](t)}function m(e){return e.status!==0||e.timedOut||e.outputLimitExceeded}async function h(e){if(await D(s.default.join(e,`package.json`)))return await E(e,[`bun.lock`,`bun.lockb`])?[`bun`,`install`,`--frozen-lockfile`,`--silent`]:[`bun`,`install`,`--silent`]}async function g(e){if(await D(s.default.join(e,`Cargo.toml`)))return await D(s.default.join(e,`Cargo.lock`))?[`cargo`,`fetch`,`--locked`]:[`cargo`,`fetch`]}async function _(e){if(await D(s.default.join(e,`go.mod`)))return[`go`,`mod`,`download`]}async function v(e){if(!await E(e,[`build.gradle`,`build.gradle.kts`,`settings.gradle`,`settings.gradle.kts`,`gradlew`,`gradlew.bat`]))return;let t=[`--no-daemon`,`--quiet`,`dependencies`];return process.platform===`win32`?await D(s.default.join(e,`gradlew.bat`))?[`cmd.exe`,`/c`,`gradlew.bat`,...t]:[`gradle`,...t]:await D(s.default.join(e,`gradlew`))?[`sh`,`./gradlew`,...t]:[`gradle`,...t]}async function y(e){if(!await D(s.default.join(e,`pom.xml`)))return;let t=[`-q`,`dependency:go-offline`];return process.platform===`win32`?await D(s.default.join(e,`mvnw.cmd`))?[`cmd.exe`,`/c`,`mvnw.cmd`,...t]:[`mvn`,...t]:await D(s.default.join(e,`mvnw`))?[`sh`,`./mvnw`,...t]:[`mvn`,...t]}async function b(e){if(await D(s.default.join(e,`package.json`)))return await D(s.default.join(e,`package-lock.json`))?[`npm`,`ci`,`--silent`]:[`npm`,`install`,`--silent`]}async function x(e){if(await D(s.default.join(e,`package.json`)))return await D(s.default.join(e,`pnpm-lock.yaml`))?[`pnpm`,`install`,`--frozen-lockfile`,`--silent`]:[`pnpm`,`install`,`--silent`]}async function S(e){if(await D(s.default.join(e,`Gemfile`)))return await D(s.default.join(e,`Gemfile.lock`))?[`bundle`,`install`,`--frozen`,`--quiet`]:[`bundle`,`install`,`--quiet`]}async function C(){}async function w(e){if(!await D(s.default.join(e,`package.json`)))return;let t=await T(e),n=await D(s.default.join(e,`yarn.lock`));return t?n?[`yarn`,`install`,`--immutable`]:[`yarn`,`install`]:n?[`yarn`,`install`,`--frozen-lockfile`,`--silent`]:[`yarn`,`install`,`--silent`]}async function T(e){if(await D(s.default.join(e,`.yarnrc.yml`)))return!0;let t=await O(s.default.join(e,`package.json`)),n=typeof t.packageManager==`string`?t.packageManager:void 0,r=/^yarn@(\d+)/.exec(n??``)?.[1];return r!==void 0&&Number(r)>=2}async function E(e,t){for(let n of t)if(await D(s.default.join(e,n)))return!0;return!1}async function D(e){try{return await a.default.access(e),!0}catch(e){if((typeof e==`object`&&e&&`code`in e?e.code:void 0)!==`ENOENT`)throw e;return!1}}async function O(e){try{let t=JSON.parse(await a.default.readFile(e,`utf8`));return typeof t==`object`&&t&&!Array.isArray(t)?t:{}}catch(e){if(e instanceof SyntaxError||(typeof e==`object`&&e&&`code`in e?e.code:void 0)===`ENOENT`)return{};throw e}}async function k(e){for(let t of e.projectFilePaths??c[e.packageManager])await A(s.default.join(e.projectDir,t),s.default.join(e.runDir,t),e.runDir)}async function A(e,t,r){try{await a.default.lstat(e),await n.createDirectoryWithoutFollowingSymlinks(r,s.default.dirname(t)),await n.copyWithoutFollowingSymlinks(e,t)}catch(e){if((typeof e==`object`&&e&&`code`in e?e.code:void 0)!==`ENOENT`)throw e}}async function j(e,n){let i=u===void 0?void 0:s.default.join(n.cwd,`.exercode-time-result`),a=t.wrapCommandWithSandboxUser(e),o=u===void 0?a:t.prependInsideSandboxWrapper(a,[...u,`--output=${i}`]),c=t.startSandboxTimeoutWatchdog(n.timeLimitSeconds),l=Date.now()+(Math.ceil(n.timeLimitSeconds)+5)*1e3,d;try{d=r.default.spawn(o[0],o.slice(1),{cwd:n.cwd,detached:process.platform!==`win32`,env:{...n.env,...t.getSandboxUserEnvOverrides(n.env)},stdio:[`pipe`,`pipe`,`pipe`]})}catch(e){throw c.cancel(),e}let f=[],p=[],m=0,h=!1,g=!1,_,v,y=e=>{try{N(d,e)}catch(e){_??=e instanceof Error?e:Error(String(e)),v?.()}},b=(e,t)=>{if(m>=n.outputLimitBytes){t.byteLength>0&&(g=!0,y(`SIGKILL`));return}let r=n.outputLimitBytes-m,i=t.byteLength>r?t.subarray(0,r):t;e.push(i),m+=i.byteLength,t.byteLength>r&&(g=!0,y(`SIGKILL`))};d.stdout.on(`data`,e=>b(f,e)),d.stderr.on(`data`,e=>b(p,e));let x=setTimeout(()=>{h=!0,y(`SIGTERM`)},n.timeLimitSeconds*1e3),S=setTimeout(()=>{h&&y(`SIGKILL`)},n.timeLimitSeconds*1e3+1e3);S.unref();let C,w=!1,{status:T,signal:E}=await new Promise((e,t)=>{let r=!1,i,a=e=>{r||(i=e,y(`SIGKILL`),d.pid===void 0&&(r=!0,t(e)))};v=()=>{C??=setTimeout(()=>{r||(r=!0,t(_??Error(`failed to terminate the submission`)))},Math.max(0,l-Date.now())+2e3)},d.on(`error`,a),d.stdin.on(`error`,e=>{e.code!==`EPIPE`&&a(e)}),d.on(`close`,(n,a)=>{if(!r){if(r=!0,w=!0,i){t(i);return}e({status:n??void 0,signal:a??void 0})}}),d.stdin.end(n.stdin)}).finally(()=>{clearTimeout(x),clearTimeout(S),C&&clearTimeout(C),(w||!_)&&c.cancel()}),{timeSeconds:D,memoryBytes:O}=i===void 0?{timeSeconds:0,memoryBytes:0}:await F(i);return{stdout:Buffer.concat(f).toString(),stderr:Buffer.concat(p).toString(),status:T,timeSeconds:D,memoryBytes:O,timedOut:h,signal:E,outputLimitExceeded:g}}function M(){let e=o.default.platform()===`darwin`?`gtime`:`/usr/bin/time`,t=r.default.spawnSync(e,[`--version`],{stdio:`ignore`});if(!(t.error||t.status!==0))return[e,`--format`,`%e %M`]}function N(e,n){if(e.pid!==void 0){if(t.sandboxUserName){t.killSandboxUserProcesses([n===`SIGKILL`?`KILL`:`TERM`]);return}try{if(process.platform===`win32`){e.kill(n);return}process.kill(-e.pid,n)}catch(e){let t=typeof e==`object`&&e&&`code`in e?e.code:void 0;if(t!==`ESRCH`&&t!==`EPERM`)throw e}}}function P(e,t){return typeof e==`object`&&!!e&&`code`in e&&e.code===t}async function F(e){let t,n;try{if(n=await a.default.open(e,i.default.constants.O_RDONLY|i.default.constants.O_NOFOLLOW|i.default.constants.O_NONBLOCK),!(await n.stat()).isFile())throw Error(`${e} is not a regular file`);t=await n.readFile(`utf8`)}catch(t){if(P(t,`ENOENT`))return{timeSeconds:0,memoryBytes:0};throw Error(`failed to read the time measurement at ${e}`,{cause:t})}finally{await n?.close()}let r=/(\d+(?:[.,]\d+)?) (\d+)\s*$/.exec(t);return r?{timeSeconds:Number(r[1].replace(`,`,`.`)),memoryBytes:Number(r[2])*1024}:{timeSeconds:0,memoryBytes:0}}exports.copyPackageManagerProjectFiles=k,exports.runCommandInTemporaryPackageManagerProject=d;
2
2
  //# sourceMappingURL=runCommandInTemporaryPackageManagerProject.cjs.map