@probelabs/visor 0.1.144 → 0.1.145-ee

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 (89) hide show
  1. package/dist/config.d.ts.map +1 -1
  2. package/dist/docs/architecture.md +28 -0
  3. package/dist/docs/configuration.md +2 -0
  4. package/dist/docs/sandbox-engines.md +357 -0
  5. package/dist/docs/security.md +40 -0
  6. package/dist/generated/config-schema.d.ts +5 -0
  7. package/dist/generated/config-schema.d.ts.map +1 -1
  8. package/dist/generated/config-schema.json +9 -0
  9. package/dist/index.js +2388 -183
  10. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  11. package/dist/sandbox/bubblewrap-sandbox.d.ts +30 -0
  12. package/dist/sandbox/bubblewrap-sandbox.d.ts.map +1 -0
  13. package/dist/sandbox/index.d.ts +3 -1
  14. package/dist/sandbox/index.d.ts.map +1 -1
  15. package/dist/sandbox/sandbox-manager.d.ts +3 -2
  16. package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
  17. package/dist/sandbox/seatbelt-sandbox.d.ts +36 -0
  18. package/dist/sandbox/seatbelt-sandbox.d.ts.map +1 -0
  19. package/dist/sandbox/types.d.ts +3 -1
  20. package/dist/sandbox/types.d.ts.map +1 -1
  21. package/dist/sdk/{check-provider-registry-VTNNTMWC.mjs → check-provider-registry-HFPKHYTG.mjs} +3 -3
  22. package/dist/sdk/{check-provider-registry-WBEOZCGW.mjs → check-provider-registry-TH25S2OB.mjs} +7 -7
  23. package/dist/sdk/{chunk-D3UC5KUJ.mjs → chunk-3BOOHJI5.mjs} +472 -105
  24. package/dist/sdk/chunk-3BOOHJI5.mjs.map +1 -0
  25. package/dist/sdk/{chunk-PXWWPPNF.mjs → chunk-GZMQPC6D.mjs} +459 -92
  26. package/dist/sdk/chunk-GZMQPC6D.mjs.map +1 -0
  27. package/dist/sdk/{chunk-CLQTOZKH.mjs → chunk-I42ZCVA5.mjs} +3 -3
  28. package/dist/sdk/{chunk-PQWAAGUP.mjs → chunk-L3XPYQ6I.mjs} +2 -2
  29. package/dist/sdk/{chunk-FG6THKK7.mjs → chunk-OM3WYVFI.mjs} +3 -3
  30. package/dist/sdk/chunk-OM3WYVFI.mjs.map +1 -0
  31. package/dist/sdk/{chunk-AKCHIYWU.mjs → chunk-YOKAA4IU.mjs} +96 -63
  32. package/dist/sdk/chunk-YOKAA4IU.mjs.map +1 -0
  33. package/dist/sdk/{config-KOKJ3PYE.mjs → config-AAB2FL22.mjs} +2 -2
  34. package/dist/sdk/{failure-condition-evaluator-LWH3NQ2S.mjs → failure-condition-evaluator-O464EJMD.mjs} +3 -3
  35. package/dist/sdk/{github-frontend-UUASYGNV.mjs → github-frontend-MSX6Q2WL.mjs} +3 -3
  36. package/dist/sdk/{host-LAF3NFPZ.mjs → host-GA76UESS.mjs} +2 -2
  37. package/dist/sdk/knex-store-HPXJILBL.mjs +411 -0
  38. package/dist/sdk/knex-store-HPXJILBL.mjs.map +1 -0
  39. package/dist/sdk/loader-ZC5G3JGJ.mjs +89 -0
  40. package/dist/sdk/loader-ZC5G3JGJ.mjs.map +1 -0
  41. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  42. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  43. package/dist/sdk/{routing-LEUV6A4K.mjs → routing-RIHVCEIU.mjs} +4 -4
  44. package/dist/sdk/{schedule-tool-handler-W7IB4MK3.mjs → schedule-tool-handler-BTLEDYAI.mjs} +3 -3
  45. package/dist/sdk/{schedule-tool-handler-EYDCUGOB.mjs → schedule-tool-handler-NYL2ONJB.mjs} +7 -7
  46. package/dist/sdk/sdk.d.mts +3 -1
  47. package/dist/sdk/sdk.d.ts +3 -1
  48. package/dist/sdk/sdk.js +2006 -348
  49. package/dist/sdk/sdk.js.map +1 -1
  50. package/dist/sdk/sdk.mjs +6 -6
  51. package/dist/sdk/{trace-helpers-NNBQNFWZ.mjs → trace-helpers-QQSTZGDT.mjs} +2 -2
  52. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  53. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  54. package/dist/sdk/{workflow-check-provider-WW5U6R2P.mjs → workflow-check-provider-3IIKJFM4.mjs} +3 -3
  55. package/dist/sdk/{workflow-check-provider-FLBIJQ4Z.mjs → workflow-check-provider-LVUUL2PZ.mjs} +7 -7
  56. package/dist/slack/socket-runner.d.ts.map +1 -1
  57. package/dist/utils/workspace-manager.d.ts +9 -0
  58. package/dist/utils/workspace-manager.d.ts.map +1 -1
  59. package/package.json +2 -2
  60. package/dist/output/traces/run-2026-02-25T17-29-59-894Z.ndjson +0 -138
  61. package/dist/output/traces/run-2026-02-25T17-30-47-149Z.ndjson +0 -1442
  62. package/dist/sdk/check-provider-registry-GKLK3I2X.mjs +0 -30
  63. package/dist/sdk/chunk-AKCHIYWU.mjs.map +0 -1
  64. package/dist/sdk/chunk-D3UC5KUJ.mjs.map +0 -1
  65. package/dist/sdk/chunk-FG6THKK7.mjs.map +0 -1
  66. package/dist/sdk/chunk-N7LW3Q5B.mjs +0 -40284
  67. package/dist/sdk/chunk-N7LW3Q5B.mjs.map +0 -1
  68. package/dist/sdk/chunk-PXWWPPNF.mjs.map +0 -1
  69. package/dist/sdk/schedule-tool-handler-7RGTKO24.mjs +0 -40
  70. package/dist/sdk/workflow-check-provider-2G2CEXFR.mjs +0 -30
  71. package/dist/sdk/workflow-check-provider-2G2CEXFR.mjs.map +0 -1
  72. package/dist/sdk/workflow-check-provider-FLBIJQ4Z.mjs.map +0 -1
  73. package/dist/sdk/workflow-check-provider-WW5U6R2P.mjs.map +0 -1
  74. package/dist/traces/run-2026-02-25T17-29-59-894Z.ndjson +0 -138
  75. package/dist/traces/run-2026-02-25T17-30-47-149Z.ndjson +0 -1442
  76. /package/dist/sdk/{check-provider-registry-GKLK3I2X.mjs.map → check-provider-registry-HFPKHYTG.mjs.map} +0 -0
  77. /package/dist/sdk/{check-provider-registry-VTNNTMWC.mjs.map → check-provider-registry-TH25S2OB.mjs.map} +0 -0
  78. /package/dist/sdk/{chunk-CLQTOZKH.mjs.map → chunk-I42ZCVA5.mjs.map} +0 -0
  79. /package/dist/sdk/{chunk-PQWAAGUP.mjs.map → chunk-L3XPYQ6I.mjs.map} +0 -0
  80. /package/dist/sdk/{check-provider-registry-WBEOZCGW.mjs.map → config-AAB2FL22.mjs.map} +0 -0
  81. /package/dist/sdk/{config-KOKJ3PYE.mjs.map → failure-condition-evaluator-O464EJMD.mjs.map} +0 -0
  82. /package/dist/sdk/{github-frontend-UUASYGNV.mjs.map → github-frontend-MSX6Q2WL.mjs.map} +0 -0
  83. /package/dist/sdk/{host-LAF3NFPZ.mjs.map → host-GA76UESS.mjs.map} +0 -0
  84. /package/dist/sdk/{failure-condition-evaluator-LWH3NQ2S.mjs.map → routing-RIHVCEIU.mjs.map} +0 -0
  85. /package/dist/sdk/{routing-LEUV6A4K.mjs.map → schedule-tool-handler-BTLEDYAI.mjs.map} +0 -0
  86. /package/dist/sdk/{schedule-tool-handler-7RGTKO24.mjs.map → schedule-tool-handler-NYL2ONJB.mjs.map} +0 -0
  87. /package/dist/sdk/{schedule-tool-handler-EYDCUGOB.mjs.map → trace-helpers-QQSTZGDT.mjs.map} +0 -0
  88. /package/dist/sdk/{schedule-tool-handler-W7IB4MK3.mjs.map → workflow-check-provider-3IIKJFM4.mjs.map} +0 -0
  89. /package/dist/sdk/{trace-helpers-NNBQNFWZ.mjs.map → workflow-check-provider-LVUUL2PZ.mjs.map} +0 -0
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  FailureConditionEvaluator,
3
3
  init_failure_condition_evaluator
4
- } from "./chunk-PQWAAGUP.mjs";
4
+ } from "./chunk-L3XPYQ6I.mjs";
5
5
  import {
6
6
  addEvent,
7
7
  init_trace_helpers
8
- } from "./chunk-FG6THKK7.mjs";
8
+ } from "./chunk-OM3WYVFI.mjs";
9
9
  import {
10
10
  createExtendedLiquid,
11
11
  init_liquid_extensions
@@ -1499,4 +1499,4 @@ export {
1499
1499
  evaluateTransitions,
1500
1500
  init_routing
1501
1501
  };
1502
- //# sourceMappingURL=chunk-CLQTOZKH.mjs.map
1502
+ //# sourceMappingURL=chunk-I42ZCVA5.mjs.map
@@ -3,7 +3,7 @@ import {
3
3
  fallback_ndjson_exports,
4
4
  init_fallback_ndjson,
5
5
  init_trace_helpers
6
- } from "./chunk-FG6THKK7.mjs";
6
+ } from "./chunk-OM3WYVFI.mjs";
7
7
  import {
8
8
  addFailIfTriggered,
9
9
  init_metrics
@@ -736,4 +736,4 @@ export {
736
736
  failure_condition_evaluator_exports,
737
737
  init_failure_condition_evaluator
738
738
  };
739
- //# sourceMappingURL=chunk-PQWAAGUP.mjs.map
739
+ //# sourceMappingURL=chunk-L3XPYQ6I.mjs.map
@@ -88,7 +88,7 @@ var require_package = __commonJS({
88
88
  "package.json"(exports, module) {
89
89
  module.exports = {
90
90
  name: "@probelabs/visor",
91
- version: "0.1.144",
91
+ version: "0.1.42",
92
92
  main: "dist/index.js",
93
93
  bin: {
94
94
  visor: "./dist/index.js"
@@ -202,7 +202,7 @@ var require_package = __commonJS({
202
202
  "@opentelemetry/sdk-node": "^0.203.0",
203
203
  "@opentelemetry/sdk-trace-base": "^1.30.1",
204
204
  "@opentelemetry/semantic-conventions": "^1.30.1",
205
- "@probelabs/probe": "^0.6.0-rc259",
205
+ "@probelabs/probe": "^0.6.0-rc260",
206
206
  "@types/commander": "^2.12.0",
207
207
  "@types/uuid": "^10.0.0",
208
208
  acorn: "^8.16.0",
@@ -440,4 +440,4 @@ export {
440
440
  trace_helpers_exports,
441
441
  init_trace_helpers
442
442
  };
443
- //# sourceMappingURL=chunk-FG6THKK7.mjs.map
443
+ //# sourceMappingURL=chunk-OM3WYVFI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/fallback-ndjson.ts","../../package.json","../../src/telemetry/trace-helpers.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nlet CURRENT_FILE: string | null = null;\nlet dirReady = false;\nlet writeChain: Promise<void> = Promise.resolve();\nfunction resolveTargetPath(outDir: string): string {\n if (process.env.VISOR_FALLBACK_TRACE_FILE) {\n CURRENT_FILE = process.env.VISOR_FALLBACK_TRACE_FILE;\n return CURRENT_FILE;\n }\n if (CURRENT_FILE) return CURRENT_FILE;\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\n CURRENT_FILE = path.join(outDir, `${ts}.ndjson`);\n return CURRENT_FILE;\n}\n\nfunction isEnabled(): boolean {\n // Enable when CLI set a fallback file (serverless mode), or when explicit file sink is enabled\n if (process.env.VISOR_FALLBACK_TRACE_FILE) return true;\n return (\n process.env.VISOR_TELEMETRY_ENABLED === 'true' &&\n (process.env.VISOR_TELEMETRY_SINK || 'file') === 'file'\n );\n}\n\nfunction appendAsync(outDir: string, line: string): void {\n writeChain = writeChain\n .then(async () => {\n if (!dirReady) {\n try {\n await fs.promises.mkdir(outDir, { recursive: true });\n } catch {}\n dirReady = true;\n }\n const target = resolveTargetPath(outDir);\n await fs.promises.appendFile(target, line, 'utf8');\n })\n .catch(() => {});\n}\n\nexport async function flushNdjson(): Promise<void> {\n try {\n await writeChain;\n } catch {}\n}\n\nexport function emitNdjsonFallback(name: string, attrs: Record<string, unknown>): void {\n try {\n if (!isEnabled()) return;\n const outDir = process.env.VISOR_TRACE_DIR || path.join(process.cwd(), 'output', 'traces');\n const line = JSON.stringify({ name, attributes: attrs }) + '\\n';\n appendAsync(outDir, line);\n } catch {\n // ignore\n }\n}\n\nexport function emitNdjsonSpanWithEvents(\n name: string,\n attrs: Record<string, unknown>,\n events: Array<{ name: string; attrs?: Record<string, unknown> }>\n): void {\n try {\n if (!isEnabled()) return;\n const outDir = process.env.VISOR_TRACE_DIR || path.join(process.cwd(), 'output', 'traces');\n const line = JSON.stringify({ name, attributes: attrs, events }) + '\\n';\n appendAsync(outDir, line);\n } catch {\n // ignore\n }\n}\n","{\n \"name\": \"@probelabs/visor\",\n \"version\": \"0.1.42\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"visor\": \"./dist/index.js\"\n },\n \"exports\": {\n \".\": {\n \"require\": \"./dist/index.js\",\n \"import\": \"./dist/index.js\"\n },\n \"./sdk\": {\n \"types\": \"./dist/sdk/sdk.d.ts\",\n \"import\": \"./dist/sdk/sdk.mjs\",\n \"require\": \"./dist/sdk/sdk.js\"\n },\n \"./cli\": {\n \"require\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist/\",\n \"defaults/\",\n \"action.yml\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"scripts\": {\n \"build:cli\": \"ncc build src/index.ts -o dist && cp -r defaults dist/ && cp -r output dist/ && cp -r docs dist/ && cp -r examples dist/ && cp -r src/debug-visualizer/ui dist/debug-visualizer/ && node scripts/inject-version.js && echo '#!/usr/bin/env node' | cat - dist/index.js > temp && mv temp dist/index.js && chmod +x dist/index.js\",\n \"build:sdk\": \"tsup src/sdk.ts --dts --sourcemap --format esm,cjs --out-dir dist/sdk\",\n \"build\": \"./scripts/build-oss.sh\",\n \"build:ee\": \"npm run build:cli && npm run build:sdk\",\n \"test\": \"jest && npm run test:yaml\",\n \"test:unit\": \"jest\",\n \"prepublishOnly\": \"npm run build\",\n \"test:watch\": \"jest --watch\",\n \"test:coverage\": \"jest --coverage\",\n \"test:ee\": \"jest --testPathPatterns='tests/ee' --testPathIgnorePatterns='/node_modules/' --no-coverage\",\n \"test:manual:bash\": \"RUN_MANUAL_TESTS=true jest tests/manual/bash-config-manual.test.ts\",\n \"lint\": \"eslint src tests --ext .ts\",\n \"lint:fix\": \"eslint src tests --ext .ts --fix\",\n \"format\": \"prettier --write src tests\",\n \"format:check\": \"prettier --check src tests\",\n \"clean\": \"\",\n \"clean:traces\": \"node scripts/clean-traces.js\",\n \"prebuild\": \"npm run clean && node scripts/generate-config-schema.js\",\n \"pretest\": \"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli\",\n \"pretest:unit\": \"npm run clean:traces && node scripts/generate-config-schema.js && npm run build:cli\",\n \"test:with-build\": \"npm run build:cli && jest\",\n \"test:yaml\": \"node dist/index.js test --progress compact\",\n \"test:yaml:parallel\": \"node dist/index.js test --progress compact --max-parallel 4\",\n \"prepare\": \"husky\",\n \"pre-commit\": \"lint-staged\",\n \"deploy:site\": \"cd site && npx wrangler pages deploy . --project-name=visor-site --commit-dirty=true\",\n \"deploy:worker\": \"npx wrangler deploy\",\n \"deploy\": \"npm run deploy:site && npm run deploy:worker\",\n \"publish:ee\": \"./scripts/publish-ee.sh\",\n \"release\": \"./scripts/release.sh\",\n \"release:patch\": \"./scripts/release.sh patch\",\n \"release:minor\": \"./scripts/release.sh minor\",\n \"release:major\": \"./scripts/release.sh major\",\n \"release:prerelease\": \"./scripts/release.sh prerelease\",\n \"docs:validate\": \"node scripts/validate-readme-links.js\",\n \"workshop:setup\": \"npm install -D reveal-md@6.1.2\",\n \"workshop:serve\": \"cd workshop && reveal-md slides.md -w\",\n \"workshop:export\": \"reveal-md workshop/slides.md --static workshop/build\",\n \"workshop:pdf\": \"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter\",\n \"workshop:pdf:ci\": \"reveal-md workshop/slides.md --print workshop/Visor-Workshop.pdf --print-size letter --puppeteer-launch-args=\\\"--no-sandbox --disable-dev-shm-usage\\\"\",\n \"workshop:pdf:a4\": \"reveal-md workshop/slides.md --print workshop/Visor-Workshop-A4.pdf --print-size A4\",\n \"workshop:build\": \"npm run workshop:export && npm run workshop:pdf\",\n \"simulate:issue\": \"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issues --action opened --debug\",\n \"simulate:comment\": \"TS_NODE_TRANSPILE_ONLY=1 ts-node scripts/simulate-gh-run.ts --event issue_comment --action created --debug\"\n },\n \"keywords\": [\n \"code-review\",\n \"ai\",\n \"github-action\",\n \"cli\",\n \"pr-review\",\n \"visor\"\n ],\n \"author\": \"Probe Labs\",\n \"license\": \"MIT\",\n \"description\": \"AI workflow engine for code review, assistants, and automation — orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/probelabs/visor.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/probelabs/visor/issues\"\n },\n \"homepage\": \"https://github.com/probelabs/visor#readme\",\n \"dependencies\": {\n \"@actions/core\": \"^1.11.1\",\n \"@apidevtools/swagger-parser\": \"^12.1.0\",\n \"@modelcontextprotocol/sdk\": \"^1.25.3\",\n \"@nyariv/sandboxjs\": \"github:probelabs/SandboxJS#f1c13b8eee98734a8ea024061eada4aa9a9ff2e9\",\n \"@octokit/action\": \"^8.0.2\",\n \"@octokit/auth-app\": \"^8.1.0\",\n \"@octokit/core\": \"^7.0.3\",\n \"@octokit/rest\": \"^22.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/core\": \"^1.30.1\",\n \"@opentelemetry/exporter-trace-otlp-grpc\": \"^0.203.0\",\n \"@opentelemetry/exporter-trace-otlp-http\": \"^0.203.0\",\n \"@opentelemetry/instrumentation\": \"^0.203.0\",\n \"@opentelemetry/resources\": \"^1.30.1\",\n \"@opentelemetry/sdk-metrics\": \"^1.30.1\",\n \"@opentelemetry/sdk-node\": \"^0.203.0\",\n \"@opentelemetry/sdk-trace-base\": \"^1.30.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.30.1\",\n \"@probelabs/probe\": \"^0.6.0-rc260\",\n \"@types/commander\": \"^2.12.0\",\n \"@types/uuid\": \"^10.0.0\",\n \"acorn\": \"^8.16.0\",\n \"acorn-walk\": \"^8.3.5\",\n \"ajv\": \"^8.17.1\",\n \"ajv-formats\": \"^3.0.1\",\n \"better-sqlite3\": \"^11.0.0\",\n \"blessed\": \"^0.1.81\",\n \"cli-table3\": \"^0.6.5\",\n \"commander\": \"^14.0.0\",\n \"deepmerge\": \"^4.3.1\",\n \"dotenv\": \"^17.2.3\",\n \"ignore\": \"^7.0.5\",\n \"js-yaml\": \"^4.1.0\",\n \"jsonpath-plus\": \"^10.4.0\",\n \"liquidjs\": \"^10.21.1\",\n \"minimatch\": \"^10.2.2\",\n \"node-cron\": \"^3.0.3\",\n \"open\": \"^9.1.0\",\n \"simple-git\": \"^3.28.0\",\n \"uuid\": \"^11.1.0\",\n \"ws\": \"^8.18.3\"\n },\n \"optionalDependencies\": {\n \"@anthropic/claude-code-sdk\": \"npm:null@*\",\n \"@open-policy-agent/opa-wasm\": \"^1.10.0\",\n \"knex\": \"^3.1.0\",\n \"mysql2\": \"^3.11.0\",\n \"pg\": \"^8.13.0\",\n \"tedious\": \"^19.0.0\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.34.0\",\n \"@kie/act-js\": \"^2.6.2\",\n \"@kie/mock-github\": \"^2.0.1\",\n \"@swc/core\": \"^1.13.2\",\n \"@swc/jest\": \"^0.2.37\",\n \"@types/better-sqlite3\": \"^7.6.0\",\n \"@types/blessed\": \"^0.1.27\",\n \"@types/jest\": \"^30.0.0\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/node\": \"^24.3.0\",\n \"@types/node-cron\": \"^3.0.11\",\n \"@types/ws\": \"^8.18.1\",\n \"@typescript-eslint/eslint-plugin\": \"^8.42.0\",\n \"@typescript-eslint/parser\": \"^8.42.0\",\n \"@vercel/ncc\": \"^0.38.4\",\n \"eslint\": \"^9.34.0\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-prettier\": \"^5.5.4\",\n \"husky\": \"^9.1.7\",\n \"jest\": \"^30.1.3\",\n \"lint-staged\": \"^16.1.6\",\n \"prettier\": \"^3.6.2\",\n \"reveal-md\": \"^6.1.2\",\n \"ts-json-schema-generator\": \"^1.5.1\",\n \"ts-node\": \"^10.9.2\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.2\",\n \"wrangler\": \"^3.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"@anthropic/claude-code-sdk\": {\n \"optional\": true\n }\n },\n \"directories\": {\n \"test\": \"tests\"\n },\n \"lint-staged\": {\n \"src/**/*.{ts,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"tests/**/*.{ts,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"*.{json,md,yml,yaml}\": [\n \"prettier --write\"\n ]\n }\n}\n","import { context as otContext, Span, SpanStatusCode, trace, Attributes } from './lazy-otel';\n\nexport function getTracer() {\n return trace.getTracer('visor');\n}\n\nexport async function withActiveSpan<T>(\n name: string,\n attrs: Record<string, unknown> | undefined,\n fn: (span: Span) => Promise<T>\n): Promise<T> {\n const tracer = getTracer();\n // Preserve parent context via tracer API; avoid logging parent IDs to stdout\n // Avoid noisy stdout logs that break JSON consumers\n return await new Promise<T>((resolve, reject) => {\n const callback = async (span: Span) => {\n // console.debug(`[trace] Span callback invoked for: [trace_id=${ctx.traceId} span_id=${ctx.spanId}] ${name} span: true`);\n try {\n const res = await fn(span);\n // console.debug('[trace] Span execution completed for:', name);\n resolve(res);\n } catch (err) {\n // console.debug('[trace] Span execution errored for:', name, err);\n try {\n if (err instanceof Error) span.recordException(err);\n span.setStatus({ code: SpanStatusCode.ERROR });\n } catch {}\n reject(err);\n } finally {\n try {\n // console.debug('[trace] Ending span:', name);\n span.end();\n } catch {}\n }\n };\n // startActiveSpan should use the current active context to set parent automatically\n const options = attrs ? { attributes: attrs as Attributes } : {};\n tracer.startActiveSpan(name, options, callback);\n });\n}\n\nexport function addEvent(name: string, attrs?: Record<string, unknown>): void {\n const span = trace.getSpan(otContext.active());\n if (span) {\n try {\n span.addEvent(name, attrs as Attributes);\n } catch {\n // ignore\n }\n }\n // Fallback NDJSON emission for serverless/file sink when SDK may be inactive\n try {\n const { emitNdjsonSpanWithEvents } = require('./fallback-ndjson');\n emitNdjsonSpanWithEvents('visor.event', {}, [{ name, attrs }]);\n if (name === 'fail_if.triggered') {\n emitNdjsonSpanWithEvents('visor.event', {}, [\n { name: 'fail_if.evaluated', attrs },\n { name: 'fail_if.triggered', attrs },\n ]);\n }\n } catch {}\n}\n\nexport function setSpanAttributes(attrs: Record<string, unknown>): void {\n const span = trace.getSpan(otContext.active());\n if (!span) return;\n try {\n for (const [k, v] of Object.entries(attrs)) span.setAttribute(k, v as never);\n } catch {\n // ignore\n }\n}\n\nexport function setSpanError(err: unknown): void {\n const span = trace.getSpan(otContext.active());\n if (!span) return;\n try {\n if (err instanceof Error) span.recordException(err);\n span.setStatus({ code: SpanStatusCode.ERROR });\n } catch {\n // ignore\n }\n}\n\n/**\n * Return standard visor.* resource attributes for the root `visor.run` span.\n * Reads version from package.json / env and git commit short SHA from env.\n */\nexport function getVisorRunAttributes(): Record<string, string> {\n const attrs: Record<string, string> = {};\n try {\n attrs['visor.version'] =\n process.env.VISOR_VERSION || (require('../../package.json')?.version ?? 'dev');\n } catch {\n attrs['visor.version'] = 'dev';\n }\n const commitShort = process.env.VISOR_COMMIT_SHORT || '';\n const commitFull = process.env.VISOR_COMMIT_SHA || process.env.VISOR_COMMIT || '';\n if (commitShort) {\n attrs['visor.commit'] = commitShort;\n }\n if (commitFull) {\n attrs['visor.commit.sha'] = commitFull;\n }\n return attrs;\n}\n\n// Internal helper for tests: write a minimal run marker to NDJSON when using file sink\nlet __ndjsonPath: string | null = null;\nexport function __getOrCreateNdjsonPath(): string | null {\n try {\n // If sink is explicitly set to non-file, skip. If unset, still allow when a trace dir/file is configured.\n if (process.env.VISOR_TELEMETRY_SINK && process.env.VISOR_TELEMETRY_SINK !== 'file')\n return null;\n const path = require('path');\n const fs = require('fs');\n // Prefer explicit fallback file path if set by the CLI\n if (process.env.VISOR_FALLBACK_TRACE_FILE) {\n __ndjsonPath = process.env.VISOR_FALLBACK_TRACE_FILE;\n const dir = path.dirname(__ndjsonPath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return __ndjsonPath;\n }\n const outDir = process.env.VISOR_TRACE_DIR || path.join(process.cwd(), 'output', 'traces');\n if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });\n if (!__ndjsonPath) {\n const ts = new Date().toISOString().replace(/[:.]/g, '-');\n __ndjsonPath = path.join(outDir, `${ts}.ndjson`);\n }\n return __ndjsonPath;\n } catch {\n return null;\n }\n}\nexport function _appendRunMarker(): void {\n try {\n const fs = require('fs');\n const p = __getOrCreateNdjsonPath();\n if (!p) return;\n const line = { name: 'visor.run', attributes: { started: true } };\n fs.appendFileSync(p, JSON.stringify(line) + '\\n', 'utf8');\n } catch {}\n}\n"],"mappings":"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","names":["emitNdjsonSpanWithEvents","path","fs"]}
@@ -2728,6 +2728,11 @@ var init_config_schema = __esm({
2728
2728
  SandboxConfig: {
2729
2729
  type: "object",
2730
2730
  properties: {
2731
+ engine: {
2732
+ type: "string",
2733
+ enum: ["docker", "bubblewrap", "seatbelt"],
2734
+ description: "Sandbox engine type: 'docker' (default), 'bubblewrap' (Linux namespaces), or 'seatbelt' (macOS sandbox-exec)"
2735
+ },
2731
2736
  image: {
2732
2737
  type: "string",
2733
2738
  description: 'Docker image to use (e.g., "node:20-alpine")'
@@ -4104,92 +4109,120 @@ ${errors}`);
4104
4109
  message: `Sandbox name '${name}' contains invalid characters. Only letters, numbers, dots, hyphens, underscores allowed.`
4105
4110
  });
4106
4111
  }
4107
- const modes = [
4108
- config.image ? "image" : null,
4109
- config.dockerfile || config.dockerfile_inline ? "dockerfile" : null,
4110
- config.compose ? "compose" : null
4111
- ].filter(Boolean);
4112
- if (modes.length === 0) {
4113
- errors.push({
4114
- field: `sandboxes.${name}`,
4115
- message: `Sandbox '${name}' must specify one of: image, dockerfile, dockerfile_inline, or compose`
4116
- });
4117
- } else if (modes.length > 1) {
4118
- errors.push({
4119
- field: `sandboxes.${name}`,
4120
- message: `Sandbox '${name}' has multiple modes (${modes.join(", ")}). Specify exactly one.`
4121
- });
4122
- }
4123
- if (config.compose && !config.service) {
4112
+ if (config.engine && !["docker", "bubblewrap", "seatbelt"].includes(config.engine)) {
4124
4113
  errors.push({
4125
- field: `sandboxes.${name}.service`,
4126
- message: `Sandbox '${name}' uses compose mode but is missing required 'service' field`
4114
+ field: `sandboxes.${name}.engine`,
4115
+ message: `Sandbox '${name}' has invalid engine '${config.engine}'. Must be 'docker', 'bubblewrap', or 'seatbelt'.`
4127
4116
  });
4128
4117
  }
4129
- if (config.dockerfile && /\.\./.test(config.dockerfile)) {
4130
- errors.push({
4131
- field: `sandboxes.${name}.dockerfile`,
4132
- message: `Dockerfile path '${config.dockerfile}' in sandbox '${name}' must not contain '..' path traversal`
4133
- });
4134
- }
4135
- if (config.compose && /\.\./.test(config.compose)) {
4136
- errors.push({
4137
- field: `sandboxes.${name}.compose`,
4138
- message: `Compose file path '${config.compose}' in sandbox '${name}' must not contain '..' path traversal`
4139
- });
4140
- }
4141
- if (config.workdir) {
4142
- if (!config.workdir.startsWith("/")) {
4118
+ const isNativeEngine = config.engine === "bubblewrap" || config.engine === "seatbelt";
4119
+ if (isNativeEngine) {
4120
+ const dockerOnlyFields = [
4121
+ ["image", config.image],
4122
+ ["dockerfile", config.dockerfile],
4123
+ ["dockerfile_inline", config.dockerfile_inline],
4124
+ ["compose", config.compose],
4125
+ ["service", config.service],
4126
+ ["cache", config.cache],
4127
+ ["visor_path", config.visor_path],
4128
+ ["resources", config.resources]
4129
+ ];
4130
+ for (const [field, value] of dockerOnlyFields) {
4131
+ if (value !== void 0) {
4132
+ errors.push({
4133
+ field: `sandboxes.${name}.${field}`,
4134
+ message: `Sandbox '${name}' uses ${config.engine} engine but has Docker-only field '${field}'. Remove it or switch to engine: docker.`
4135
+ });
4136
+ }
4137
+ }
4138
+ } else {
4139
+ const modes = [
4140
+ config.image ? "image" : null,
4141
+ config.dockerfile || config.dockerfile_inline ? "dockerfile" : null,
4142
+ config.compose ? "compose" : null
4143
+ ].filter(Boolean);
4144
+ if (modes.length === 0) {
4143
4145
  errors.push({
4144
- field: `sandboxes.${name}.workdir`,
4145
- message: `Workdir '${config.workdir}' in sandbox '${name}' must be an absolute path (start with /)`
4146
+ field: `sandboxes.${name}`,
4147
+ message: `Sandbox '${name}' must specify one of: image, dockerfile, dockerfile_inline, or compose`
4148
+ });
4149
+ } else if (modes.length > 1) {
4150
+ errors.push({
4151
+ field: `sandboxes.${name}`,
4152
+ message: `Sandbox '${name}' has multiple modes (${modes.join(", ")}). Specify exactly one.`
4146
4153
  });
4147
4154
  }
4148
- if (/\.\./.test(config.workdir)) {
4155
+ if (config.compose && !config.service) {
4149
4156
  errors.push({
4150
- field: `sandboxes.${name}.workdir`,
4151
- message: `Workdir '${config.workdir}' in sandbox '${name}' must not contain '..' path traversal`
4157
+ field: `sandboxes.${name}.service`,
4158
+ message: `Sandbox '${name}' uses compose mode but is missing required 'service' field`
4152
4159
  });
4153
4160
  }
4154
- }
4155
- if (config.visor_path) {
4156
- if (!config.visor_path.startsWith("/")) {
4161
+ if (config.dockerfile && /\.\./.test(config.dockerfile)) {
4157
4162
  errors.push({
4158
- field: `sandboxes.${name}.visor_path`,
4159
- message: `visor_path '${config.visor_path}' in sandbox '${name}' must be an absolute path (start with /)`
4163
+ field: `sandboxes.${name}.dockerfile`,
4164
+ message: `Dockerfile path '${config.dockerfile}' in sandbox '${name}' must not contain '..' path traversal`
4160
4165
  });
4161
4166
  }
4162
- if (/\.\./.test(config.visor_path)) {
4167
+ if (config.compose && /\.\./.test(config.compose)) {
4163
4168
  errors.push({
4164
- field: `sandboxes.${name}.visor_path`,
4165
- message: `visor_path '${config.visor_path}' in sandbox '${name}' must not contain '..' path traversal`
4169
+ field: `sandboxes.${name}.compose`,
4170
+ message: `Compose file path '${config.compose}' in sandbox '${name}' must not contain '..' path traversal`
4166
4171
  });
4167
4172
  }
4168
- }
4169
- if (config.cache?.paths) {
4170
- for (const p of config.cache.paths) {
4171
- if (!p.startsWith("/")) {
4173
+ if (config.visor_path) {
4174
+ if (!config.visor_path.startsWith("/")) {
4172
4175
  errors.push({
4173
- field: `sandboxes.${name}.cache.paths`,
4174
- message: `Cache path '${p}' in sandbox '${name}' must be absolute (start with /)`,
4175
- value: p
4176
+ field: `sandboxes.${name}.visor_path`,
4177
+ message: `visor_path '${config.visor_path}' in sandbox '${name}' must be an absolute path (start with /)`
4176
4178
  });
4177
4179
  }
4178
- if (/\.\./.test(p)) {
4180
+ if (/\.\./.test(config.visor_path)) {
4179
4181
  errors.push({
4180
- field: `sandboxes.${name}.cache.paths`,
4181
- message: `Cache path '${p}' in sandbox '${name}' must not contain '..' path traversal`,
4182
- value: p
4182
+ field: `sandboxes.${name}.visor_path`,
4183
+ message: `visor_path '${config.visor_path}' in sandbox '${name}' must not contain '..' path traversal`
4184
+ });
4185
+ }
4186
+ }
4187
+ if (config.cache?.paths) {
4188
+ for (const p of config.cache.paths) {
4189
+ if (!p.startsWith("/")) {
4190
+ errors.push({
4191
+ field: `sandboxes.${name}.cache.paths`,
4192
+ message: `Cache path '${p}' in sandbox '${name}' must be absolute (start with /)`,
4193
+ value: p
4194
+ });
4195
+ }
4196
+ if (/\.\./.test(p)) {
4197
+ errors.push({
4198
+ field: `sandboxes.${name}.cache.paths`,
4199
+ message: `Cache path '${p}' in sandbox '${name}' must not contain '..' path traversal`,
4200
+ value: p
4201
+ });
4202
+ }
4203
+ }
4204
+ }
4205
+ if (config.resources?.cpu !== void 0) {
4206
+ if (typeof config.resources.cpu !== "number" || config.resources.cpu <= 0) {
4207
+ errors.push({
4208
+ field: `sandboxes.${name}.resources.cpu`,
4209
+ message: `CPU limit in sandbox '${name}' must be a positive number`,
4210
+ value: config.resources.cpu
4183
4211
  });
4184
4212
  }
4185
4213
  }
4186
4214
  }
4187
- if (config.resources?.cpu !== void 0) {
4188
- if (typeof config.resources.cpu !== "number" || config.resources.cpu <= 0) {
4215
+ if (config.workdir) {
4216
+ if (!config.workdir.startsWith("/")) {
4189
4217
  errors.push({
4190
- field: `sandboxes.${name}.resources.cpu`,
4191
- message: `CPU limit in sandbox '${name}' must be a positive number`,
4192
- value: config.resources.cpu
4218
+ field: `sandboxes.${name}.workdir`,
4219
+ message: `Workdir '${config.workdir}' in sandbox '${name}' must be an absolute path (start with /)`
4220
+ });
4221
+ }
4222
+ if (/\.\./.test(config.workdir)) {
4223
+ errors.push({
4224
+ field: `sandboxes.${name}.workdir`,
4225
+ message: `Workdir '${config.workdir}' in sandbox '${name}' must not contain '..' path traversal`
4193
4226
  });
4194
4227
  }
4195
4228
  }
@@ -4933,4 +4966,4 @@ export {
4933
4966
  config_exports,
4934
4967
  init_config
4935
4968
  };
4936
- //# sourceMappingURL=chunk-AKCHIYWU.mjs.map
4969
+ //# sourceMappingURL=chunk-YOKAA4IU.mjs.map