@simulatte/doppler 0.1.3 → 0.1.5

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 (114) hide show
  1. package/README.md +11 -5
  2. package/package.json +27 -4
  3. package/src/client/doppler-api.browser.d.ts +1 -0
  4. package/src/client/doppler-api.browser.js +288 -0
  5. package/src/client/doppler-api.d.ts +80 -0
  6. package/src/client/doppler-api.js +298 -0
  7. package/src/client/doppler-provider/types.js +1 -1
  8. package/src/client/doppler-registry.d.ts +23 -0
  9. package/src/client/doppler-registry.js +88 -0
  10. package/src/client/doppler-registry.json +39 -0
  11. package/src/config/execution-contract-check.d.ts +82 -0
  12. package/src/config/execution-contract-check.js +317 -0
  13. package/src/config/execution-v0-contract-check.d.ts +94 -0
  14. package/src/config/execution-v0-contract-check.js +251 -0
  15. package/src/config/execution-v0-graph-contract-check.d.ts +20 -0
  16. package/src/config/execution-v0-graph-contract-check.js +64 -0
  17. package/src/config/kernel-path-contract-check.d.ts +76 -0
  18. package/src/config/kernel-path-contract-check.js +479 -0
  19. package/src/config/kernel-path-loader.d.ts +16 -0
  20. package/src/config/kernel-path-loader.js +54 -0
  21. package/src/config/kernels/kernel-ref-digests.js +12 -0
  22. package/src/config/kernels/registry.json +556 -0
  23. package/src/config/loader.js +90 -67
  24. package/src/config/merge-contract-check.d.ts +16 -0
  25. package/src/config/merge-contract-check.js +321 -0
  26. package/src/config/merge-helpers.d.ts +58 -0
  27. package/src/config/merge-helpers.js +54 -0
  28. package/src/config/merge.js +3 -6
  29. package/src/config/presets/models/janus-text.json +27 -0
  30. package/src/config/quantization-contract-check.d.ts +12 -0
  31. package/src/config/quantization-contract-check.js +91 -0
  32. package/src/config/required-inference-fields-contract-check.d.ts +24 -0
  33. package/src/config/required-inference-fields-contract-check.js +231 -0
  34. package/src/config/schema/browser-suite-metrics.schema.d.ts +17 -0
  35. package/src/config/schema/browser-suite-metrics.schema.js +46 -0
  36. package/src/config/schema/conversion-report.schema.d.ts +40 -0
  37. package/src/config/schema/conversion-report.schema.js +108 -0
  38. package/src/config/schema/doppler.schema.js +12 -18
  39. package/src/config/schema/index.d.ts +22 -0
  40. package/src/config/schema/index.js +18 -0
  41. package/src/converter/core.d.ts +10 -0
  42. package/src/converter/core.js +49 -11
  43. package/src/converter/parsers/diffusion.js +63 -3
  44. package/src/converter/tokenizer-utils.js +17 -3
  45. package/src/formats/rdrr/validation.js +13 -0
  46. package/src/gpu/kernels/depthwise_conv2d.d.ts +29 -0
  47. package/src/gpu/kernels/depthwise_conv2d.js +98 -0
  48. package/src/gpu/kernels/depthwise_conv2d.wgsl +58 -0
  49. package/src/gpu/kernels/depthwise_conv2d_f16.wgsl +62 -0
  50. package/src/gpu/kernels/grouped_pointwise_conv2d.d.ts +27 -0
  51. package/src/gpu/kernels/grouped_pointwise_conv2d.js +92 -0
  52. package/src/gpu/kernels/grouped_pointwise_conv2d.wgsl +47 -0
  53. package/src/gpu/kernels/grouped_pointwise_conv2d_f16.wgsl +51 -0
  54. package/src/gpu/kernels/index.d.ts +30 -0
  55. package/src/gpu/kernels/index.js +25 -0
  56. package/src/gpu/kernels/relu.d.ts +18 -0
  57. package/src/gpu/kernels/relu.js +45 -0
  58. package/src/gpu/kernels/relu.wgsl +21 -0
  59. package/src/gpu/kernels/relu_f16.wgsl +23 -0
  60. package/src/gpu/kernels/repeat_channels.d.ts +21 -0
  61. package/src/gpu/kernels/repeat_channels.js +60 -0
  62. package/src/gpu/kernels/repeat_channels.wgsl +29 -0
  63. package/src/gpu/kernels/repeat_channels_f16.wgsl +31 -0
  64. package/src/gpu/kernels/sana_linear_attention.d.ts +27 -0
  65. package/src/gpu/kernels/sana_linear_attention.js +122 -0
  66. package/src/gpu/kernels/sana_linear_attention_apply.wgsl +44 -0
  67. package/src/gpu/kernels/sana_linear_attention_apply_f16.wgsl +47 -0
  68. package/src/gpu/kernels/sana_linear_attention_summary.wgsl +47 -0
  69. package/src/gpu/kernels/sana_linear_attention_summary_f16.wgsl +49 -0
  70. package/src/index-browser.d.ts +1 -0
  71. package/src/index-browser.js +2 -1
  72. package/src/index.d.ts +1 -0
  73. package/src/index.js +2 -1
  74. package/src/inference/browser-harness.js +164 -38
  75. package/src/inference/pipelines/diffusion/init.js +14 -0
  76. package/src/inference/pipelines/diffusion/pipeline.js +206 -77
  77. package/src/inference/pipelines/diffusion/sana-transformer.d.ts +53 -0
  78. package/src/inference/pipelines/diffusion/sana-transformer.js +738 -0
  79. package/src/inference/pipelines/diffusion/scheduler.d.ts +17 -1
  80. package/src/inference/pipelines/diffusion/scheduler.js +91 -3
  81. package/src/inference/pipelines/diffusion/text-encoder-gpu.d.ts +6 -4
  82. package/src/inference/pipelines/diffusion/text-encoder-gpu.js +270 -0
  83. package/src/inference/pipelines/diffusion/text-encoder.js +18 -1
  84. package/src/inference/pipelines/diffusion/types.d.ts +4 -0
  85. package/src/inference/pipelines/diffusion/vae.js +782 -78
  86. package/src/inference/pipelines/text/config.d.ts +5 -0
  87. package/src/inference/pipelines/text/config.js +1 -1
  88. package/src/inference/pipelines/text/execution-v0.js +141 -101
  89. package/src/inference/pipelines/text/init.js +41 -10
  90. package/src/inference/pipelines/text.js +7 -1
  91. package/src/rules/execution-rules-contract-check.d.ts +17 -0
  92. package/src/rules/execution-rules-contract-check.js +245 -0
  93. package/src/rules/kernels/depthwise-conv2d.rules.json +6 -0
  94. package/src/rules/kernels/grouped-pointwise-conv2d.rules.json +6 -0
  95. package/src/rules/kernels/relu.rules.json +6 -0
  96. package/src/rules/kernels/repeat-channels.rules.json +6 -0
  97. package/src/rules/kernels/sana-linear-attention.rules.json +6 -0
  98. package/src/rules/layer-pattern-contract-check.d.ts +17 -0
  99. package/src/rules/layer-pattern-contract-check.js +231 -0
  100. package/src/rules/rule-registry.d.ts +28 -0
  101. package/src/rules/rule-registry.js +38 -0
  102. package/src/tooling/conversion-config-materializer.d.ts +24 -0
  103. package/src/tooling/conversion-config-materializer.js +99 -0
  104. package/src/tooling/lean-execution-contract-runner.d.ts +43 -0
  105. package/src/tooling/lean-execution-contract-runner.js +158 -0
  106. package/src/tooling/lean-execution-contract.d.ts +16 -0
  107. package/src/tooling/lean-execution-contract.js +81 -0
  108. package/src/tooling/node-convert.d.ts +10 -0
  109. package/src/tooling/node-converter.js +59 -0
  110. package/src/tooling/node-webgpu.js +30 -9
  111. package/src/version.d.ts +2 -0
  112. package/src/version.js +2 -0
  113. package/tools/convert-safetensors-node.js +47 -0
  114. package/tools/doppler-cli.js +167 -6
@@ -13,6 +13,8 @@ import { createToolingErrorEnvelope } from '../src/tooling/command-envelope.js';
13
13
 
14
14
  const NODE_WEBGPU_INCOMPLETE_MESSAGE = 'node command: WebGPU runtime is incomplete in Node';
15
15
  const CLI_POLICY_PATH = fileURLToPath(new URL('./configs/cli/doppler-cli-policy.json', import.meta.url));
16
+ const DEFAULT_EXTERNAL_MODELS_ROOT = process.env.DOPPLER_EXTERNAL_MODELS_ROOT || '/media/x/models';
17
+ const DEFAULT_EXTERNAL_RDRR_ROOT = path.join(DEFAULT_EXTERNAL_MODELS_ROOT, 'rdrr');
16
18
  const DEFAULT_CLI_POLICY = {
17
19
  defaults: {
18
20
  surface: {
@@ -413,6 +415,37 @@ async function resolveBrowserModelUrl(request, browserOptions = {}) {
413
415
  };
414
416
  }
415
417
 
418
+ export async function resolveNodeModelUrl(request, options = {}) {
419
+ if (request.modelUrl || !request.modelId) {
420
+ return request;
421
+ }
422
+
423
+ const modelId = String(request.modelId);
424
+ const rdrrRoot = path.resolve(asStringOrNull(options.rdrrRoot) || DEFAULT_EXTERNAL_RDRR_ROOT);
425
+ const manifestPath = path.join(rdrrRoot, modelId, 'manifest.json');
426
+ if (!await pathExists(manifestPath)) {
427
+ return request;
428
+ }
429
+
430
+ const modelDir = path.dirname(manifestPath);
431
+ try {
432
+ const files = await fs.readdir(modelDir, { withFileTypes: true });
433
+ const hasShards = files.some((entry) =>
434
+ entry.isFile() && /^shard_\d+\.bin$/u.test(entry.name)
435
+ );
436
+ if (!hasShards) {
437
+ return request;
438
+ }
439
+ } catch {
440
+ return request;
441
+ }
442
+
443
+ return {
444
+ ...request,
445
+ modelUrl: pathToFileURL(modelDir).href.replace(/\/$/, ''),
446
+ };
447
+ }
448
+
416
449
  function parseSurface(value, command, policy = DEFAULT_CLI_POLICY) {
417
450
  const normalizedInput = asStringOrNull(value);
418
451
  const normalizedSurface = policy.defaults && policy.defaults.surface && policy.defaults.surface.default
@@ -616,10 +649,14 @@ function isTrainingCommandFlow(request) {
616
649
 
617
650
  async function runCommandOnSurface(request, surface, runConfig, jsonOutput) {
618
651
  if (surface === 'node') {
652
+ const nodeRequest = await resolveNodeModelUrl(request);
619
653
  if (!jsonOutput) {
620
654
  console.error('[surface] running on: node');
655
+ if (nodeRequest.modelUrl && nodeRequest.modelUrl !== request.modelUrl) {
656
+ console.error(`[surface] node resolved modelUrl=${nodeRequest.modelUrl}`);
657
+ }
621
658
  }
622
- return runNodeCommand(request, buildNodeRunOptions(jsonOutput));
659
+ return runNodeCommand(nodeRequest, buildNodeRunOptions(jsonOutput));
623
660
  }
624
661
 
625
662
  const browserOptions = buildBrowserRunOptions(runConfig, jsonOutput, request);
@@ -676,7 +713,17 @@ function toSummary(result) {
676
713
  }
677
714
 
678
715
  if (result.manifest?.modelId) {
679
- return `converted ${result.manifest.modelId} (${result.tensorCount} tensors, ${result.shardCount} shards)`;
716
+ const contractStatus = result.executionContractArtifact?.ok === true
717
+ ? ' contract=pass'
718
+ : result.executionContractArtifact
719
+ ? ' contract=fail'
720
+ : '';
721
+ const graphStatus = result.executionV0GraphContractArtifact?.ok === true
722
+ ? ' graph=pass'
723
+ : result.executionV0GraphContractArtifact
724
+ ? ' graph=fail'
725
+ : '';
726
+ return `converted ${result.manifest.modelId} (${result.tensorCount} tensors, ${result.shardCount} shards)${contractStatus}${graphStatus}`;
680
727
  }
681
728
 
682
729
  const suite = result.suite || result.report?.suite || 'suite';
@@ -977,6 +1024,102 @@ function printMemoryReport(result) {
977
1024
  console.log(`[memory] ${parts.join(' ')}`);
978
1025
  }
979
1026
 
1027
+ function printExecutionContractSummary(result) {
1028
+ const artifact = result?.metrics?.executionContractArtifact;
1029
+ if (!artifact || typeof artifact !== 'object') return;
1030
+ const checks = Array.isArray(artifact.checks) ? artifact.checks : [];
1031
+ const passedChecks = checks.filter((entry) => entry?.ok === true).length;
1032
+ const session = artifact.session && typeof artifact.session === 'object'
1033
+ ? artifact.session
1034
+ : null;
1035
+ const attentionPhases = artifact.steps?.attentionPhases && typeof artifact.steps.attentionPhases === 'object'
1036
+ ? artifact.steps.attentionPhases
1037
+ : null;
1038
+ const parts = [
1039
+ `status=${artifact.ok === true ? 'pass' : 'fail'}`,
1040
+ checks.length > 0 ? `checks=${passedChecks}/${checks.length}` : 'checks=n/a',
1041
+ ];
1042
+ if (session?.layout) {
1043
+ parts.push(`layout=${session.layout}`);
1044
+ }
1045
+ if (attentionPhases) {
1046
+ parts.push(
1047
+ `attn(prefill=${attentionPhases.prefill ?? 'n/a'},decode=${attentionPhases.decode ?? 'n/a'},both=${attentionPhases.both ?? 'n/a'})`
1048
+ );
1049
+ }
1050
+ console.log(`[contract] ${parts.join(' ')}`);
1051
+ if (artifact.ok !== true && Array.isArray(artifact.errors)) {
1052
+ for (const error of artifact.errors.slice(0, 3)) {
1053
+ console.log(`[contract] error=${quoteOneLine(error)}`);
1054
+ }
1055
+ }
1056
+ }
1057
+
1058
+ function printExecutionV0GraphSummary(artifact) {
1059
+ if (!artifact || typeof artifact !== 'object') return;
1060
+ const checks = Array.isArray(artifact.checks) ? artifact.checks : [];
1061
+ const passedChecks = checks.filter((entry) => entry?.ok === true).length;
1062
+ const stats = artifact.stats && typeof artifact.stats === 'object' ? artifact.stats : null;
1063
+ const parts = [
1064
+ `status=${artifact.ok === true ? 'pass' : 'fail'}`,
1065
+ checks.length > 0 ? `checks=${passedChecks}/${checks.length}` : 'checks=n/a',
1066
+ ];
1067
+ if (Number.isFinite(stats?.prefillSteps) || Number.isFinite(stats?.decodeSteps)) {
1068
+ parts.push(`steps(prefill=${stats?.prefillSteps ?? 'n/a'},decode=${stats?.decodeSteps ?? 'n/a'})`);
1069
+ }
1070
+ console.log(`[graph] ${parts.join(' ')}`);
1071
+ if (artifact.ok !== true && Array.isArray(artifact.errors)) {
1072
+ for (const error of artifact.errors.slice(0, 3)) {
1073
+ console.log(`[graph] error=${quoteOneLine(error)}`);
1074
+ }
1075
+ }
1076
+ }
1077
+
1078
+ function printSimpleArtifactSummary(label, artifact) {
1079
+ if (!artifact || typeof artifact !== 'object') return;
1080
+ const checks = Array.isArray(artifact.checks) ? artifact.checks : [];
1081
+ const passedChecks = checks.filter((entry) => entry?.ok === true).length;
1082
+ console.log(
1083
+ `[${label}] status=${artifact.ok === true ? 'pass' : 'fail'} ` +
1084
+ `checks=${checks.length > 0 ? `${passedChecks}/${checks.length}` : 'n/a'}`
1085
+ );
1086
+ if (artifact.ok !== true && Array.isArray(artifact.errors)) {
1087
+ for (const error of artifact.errors.slice(0, 2)) {
1088
+ console.log(`[${label}] error=${quoteOneLine(error)}`);
1089
+ }
1090
+ }
1091
+ }
1092
+
1093
+ function printConvertContractSummary(result) {
1094
+ const artifact = result?.executionContractArtifact;
1095
+ if (!artifact || typeof artifact !== 'object') return;
1096
+ const checks = Array.isArray(artifact.checks) ? artifact.checks : [];
1097
+ const passedChecks = checks.filter((entry) => entry?.ok === true).length;
1098
+ const session = artifact.session && typeof artifact.session === 'object'
1099
+ ? artifact.session
1100
+ : null;
1101
+ console.log(
1102
+ `[contract] status=${artifact.ok === true ? 'pass' : 'fail'} ` +
1103
+ `checks=${checks.length > 0 ? `${passedChecks}/${checks.length}` : 'n/a'} ` +
1104
+ `layout=${session?.layout ?? 'n/a'}`
1105
+ );
1106
+ if (artifact.ok !== true && Array.isArray(artifact.errors)) {
1107
+ for (const error of artifact.errors.slice(0, 3)) {
1108
+ console.log(`[contract] error=${quoteOneLine(error)}`);
1109
+ }
1110
+ }
1111
+ printExecutionV0GraphSummary(result?.executionV0GraphContractArtifact);
1112
+ printSimpleArtifactSummary('layer-pattern', result?.layerPatternContractArtifact);
1113
+ printSimpleArtifactSummary('required-inference', result?.requiredInferenceFieldsArtifact);
1114
+ }
1115
+
1116
+ function printConvertReportSummary(result) {
1117
+ const reportInfo = result?.reportInfo;
1118
+ if (!reportInfo || typeof reportInfo !== 'object') return;
1119
+ if (typeof reportInfo.path !== 'string' || reportInfo.path.length === 0) return;
1120
+ console.log(`[report] ${reportInfo.path}`);
1121
+ }
1122
+
980
1123
  function printMetricsSummary(result) {
981
1124
  if (!result || typeof result !== 'object') return;
982
1125
  const suite = String(result.suite || '');
@@ -1001,6 +1144,8 @@ function printMetricsSummary(result) {
1001
1144
  `prefill=${formatNumber(metrics.prefillTokensPerSec)} ` +
1002
1145
  `decode=${formatNumber(metrics.decodeTokensPerSec)}`
1003
1146
  );
1147
+ printExecutionContractSummary(result);
1148
+ printExecutionV0GraphSummary(metrics.executionV0GraphContractArtifact);
1004
1149
  return;
1005
1150
  }
1006
1151
 
@@ -1015,6 +1160,8 @@ function printMetricsSummary(result) {
1015
1160
  `median=${formatMs(metrics.medianEmbeddingMs)} avg=${formatMs(metrics.avgEmbeddingMs)} ` +
1016
1161
  `eps=${formatNumber(metrics.avgEmbeddingsPerSec)}`
1017
1162
  );
1163
+ printExecutionContractSummary(result);
1164
+ printExecutionV0GraphSummary(metrics.executionV0GraphContractArtifact);
1018
1165
  return;
1019
1166
  }
1020
1167
 
@@ -1036,6 +1183,8 @@ function printMetricsSummary(result) {
1036
1183
  `[metrics] latency first=${formatMs(metrics.firstTokenMs)} ` +
1037
1184
  `prefill=${formatMs(metrics.prefillMs)} decode=${formatMs(metrics.decodeMs)}`
1038
1185
  );
1186
+ printExecutionContractSummary(result);
1187
+ printExecutionV0GraphSummary(metrics.executionV0GraphContractArtifact);
1039
1188
  printDeviceInfo(result);
1040
1189
  printGpuPhases(metrics);
1041
1190
  printMemoryReport(result);
@@ -1153,6 +1302,8 @@ async function main() {
1153
1302
  }
1154
1303
 
1155
1304
  console.log(`[ok] ${toSummary(response.result)}`);
1305
+ printConvertContractSummary(response.result);
1306
+ printConvertReportSummary(response.result);
1156
1307
  printMetricsSummary(response.result);
1157
1308
  } catch (error) {
1158
1309
  if (jsonOutputRequested) {
@@ -1164,7 +1315,17 @@ async function main() {
1164
1315
  }
1165
1316
  }
1166
1317
 
1167
- main().catch((error) => {
1168
- console.error(`[error] ${error?.message || String(error)}`);
1169
- process.exit(1);
1170
- });
1318
+ function isMainModule(metaUrl) {
1319
+ const entryPath = process.argv[1];
1320
+ if (!entryPath) {
1321
+ return false;
1322
+ }
1323
+ return path.resolve(fileURLToPath(metaUrl)) === path.resolve(entryPath);
1324
+ }
1325
+
1326
+ if (isMainModule(import.meta.url)) {
1327
+ main().catch((error) => {
1328
+ console.error(`[error] ${error?.message || String(error)}`);
1329
+ process.exit(1);
1330
+ });
1331
+ }