deepline 0.3.422 → 0.3.424

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 (156) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +15 -8
  2. package/dist/bundling-sources/sdk/src/index.ts +2 -0
  3. package/dist/bundling-sources/sdk/src/play.ts +227 -184
  4. package/dist/bundling-sources/sdk/src/plays/local-file-discovery.ts +9 -2
  5. package/dist/bundling-sources/sdk/src/plays/local-play-execution.ts +1 -1
  6. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  7. package/dist/bundling-sources/sdk/src/tool-calls.ts +3 -1
  8. package/dist/bundling-sources/sdk/src/types.ts +5 -5
  9. package/dist/bundling-sources/shared_libs/monitors/fleets/verdict.ts +11 -1
  10. package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +38 -4
  11. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +12 -0
  12. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-control-plane-capability.ts +25 -0
  13. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-errors.ts +10 -0
  14. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +201 -0
  15. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-state.ts +42 -5
  16. package/dist/bundling-sources/shared_libs/monitors/provider-webhook-monitor-runtime.ts +5 -0
  17. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +37 -36
  18. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +179 -38
  19. package/dist/bundling-sources/shared_libs/plays/dataset.ts +2 -2
  20. package/dist/bundling-sources/shared_libs/plays/docflow.ts +4 -0
  21. package/dist/bundling-sources/shared_libs/plays/fetch-http-error.ts +1 -1
  22. package/dist/bundling-sources/shared_libs/plays/local-file-discovery.ts +12 -4
  23. package/dist/bundling-sources/shared_libs/plays/play-exports.ts +27 -5
  24. package/dist/bundling-sources/shared_libs/plays/script-entry.ts +992 -0
  25. package/dist/bundling-sources/shared_libs/plays/source-authoring-edition.ts +63 -0
  26. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +8 -4
  27. package/dist/bundling-sources/shared_libs/plays/ts-ast.ts +2 -0
  28. package/dist/cli/auth-MN7MWTFR.js +40 -0
  29. package/dist/cli/{auth-DMLBSXLV.mjs → auth-QITAQMHF.mjs} +4 -4
  30. package/dist/cli/{billing-IFGFPGJV.js → billing-N5AOFDSU.js} +73 -73
  31. package/dist/cli/{billing-SEXKROBQ.mjs → billing-UX2GH5L2.mjs} +4 -4
  32. package/dist/cli/{chunk-BL3LY54Y.js → chunk-22XGRO2M.js} +8 -8
  33. package/dist/cli/{chunk-AARWVK4C.mjs → chunk-2BQUML3X.mjs} +792 -69
  34. package/dist/cli/{chunk-ERFN2QY4.mjs → chunk-3DNKFH2G.mjs} +1 -1
  35. package/dist/cli/{chunk-QNBHQM5R.mjs → chunk-3FQUUVN2.mjs} +1 -1
  36. package/dist/cli/{chunk-4CAVSRQH.mjs → chunk-3O7KATMQ.mjs} +1 -1
  37. package/dist/cli/{chunk-S4KGXRCV.js → chunk-3VB5DQ7Y.js} +20 -20
  38. package/dist/cli/{chunk-VT6WJ26Y.mjs → chunk-5MD5I4MM.mjs} +1 -1
  39. package/dist/cli/{chunk-W74RDGRL.mjs → chunk-5OBCPN2C.mjs} +2 -2
  40. package/dist/cli/{chunk-LXRDHISW.js → chunk-5YLEB4CL.js} +8 -8
  41. package/dist/cli/{chunk-2JKQORUX.mjs → chunk-7KNBC4RJ.mjs} +2 -2
  42. package/dist/cli/{chunk-MLP4CAY7.mjs → chunk-7VC7STG5.mjs} +4 -4
  43. package/dist/cli/{chunk-KBJP3UAU.js → chunk-7W4N6VRE.js} +35 -35
  44. package/dist/cli/{chunk-3CE3WGKP.mjs → chunk-7Y5M5YE3.mjs} +2 -2
  45. package/dist/cli/{chunk-V4RAH5D6.js → chunk-CJD5QKYK.js} +26 -26
  46. package/dist/cli/{chunk-AYM2KZN3.js → chunk-DD6MM6WX.js} +6 -6
  47. package/dist/cli/{chunk-63ILLN5H.mjs → chunk-DS7Y7X26.mjs} +2 -2
  48. package/dist/cli/{chunk-CTNA5QY2.mjs → chunk-EER67G2B.mjs} +43 -28
  49. package/dist/cli/{chunk-OZHPZCAU.js → chunk-F3MMA7JY.js} +52 -52
  50. package/dist/cli/{chunk-CO3VMH33.mjs → chunk-FJ5U2IZY.mjs} +28 -27
  51. package/dist/cli/{chunk-27GJKC5Q.js → chunk-GXOQRZXG.js} +2 -2
  52. package/dist/cli/{chunk-AXDEH2AM.mjs → chunk-HBW6PEVG.mjs} +2 -2
  53. package/dist/cli/{chunk-PKBPSMOT.js → chunk-INFLI36H.js} +43 -28
  54. package/dist/cli/{chunk-4PG4ARL2.mjs → chunk-KPKU53YO.mjs} +1 -1
  55. package/dist/cli/{chunk-2LVM22ZU.js → chunk-LSZZVHQP.js} +2 -2
  56. package/dist/cli/{chunk-IMZ56EOH.mjs → chunk-LXTSVUZN.mjs} +2 -2
  57. package/dist/cli/{chunk-WGO2DY4L.js → chunk-M2VXDQI2.js} +11 -11
  58. package/dist/cli/{chunk-7OJEYJ6G.mjs → chunk-M67UCQKW.mjs} +3 -3
  59. package/dist/cli/{chunk-KXPIFC5S.mjs → chunk-MFXQVT7P.mjs} +3 -3
  60. package/dist/cli/{chunk-IHG7UAHD.mjs → chunk-MLJBCS3E.mjs} +32 -13
  61. package/dist/cli/{chunk-4EV2FKBI.js → chunk-OSNDC3VF.js} +16 -16
  62. package/dist/cli/{chunk-PXO253DP.mjs → chunk-OWWFCA7A.mjs} +1 -1
  63. package/dist/cli/{chunk-VRI3ABTK.js → chunk-PNGJIAJ3.js} +50 -50
  64. package/dist/cli/{chunk-HCYNAIHZ.js → chunk-QP5ATTMC.js} +4 -4
  65. package/dist/cli/{chunk-GEJDBXXM.js → chunk-QWRHGGUH.js} +1 -1
  66. package/dist/cli/{chunk-AD47BXN2.js → chunk-R2QWSSAG.js} +8 -8
  67. package/dist/cli/{chunk-QADCFSGH.js → chunk-RDIN3NKA.js} +17 -17
  68. package/dist/cli/{chunk-JRSULUPQ.js → chunk-RISEING7.js} +2 -2
  69. package/dist/cli/{chunk-M6SXXFMT.mjs → chunk-UOZCQPD4.mjs} +2 -2
  70. package/dist/cli/{chunk-TP26TAAF.mjs → chunk-UPH6UNUI.mjs} +1 -1
  71. package/dist/cli/{chunk-UQQRMCOL.js → chunk-UTF57UBW.js} +6 -6
  72. package/dist/cli/{chunk-FEKJENBB.mjs → chunk-VC5NKF4B.mjs} +3 -3
  73. package/dist/cli/{chunk-BQR6UN3C.js → chunk-VUYUI35Q.js} +32 -13
  74. package/dist/cli/{chunk-WP7T4BPE.js → chunk-YA3LMTLU.js} +1 -1
  75. package/dist/cli/{chunk-OQQOXSYA.js → chunk-YHRS6XTB.js} +845 -122
  76. package/dist/cli/{chunk-K4X472AT.js → chunk-YMASNIC5.js} +260 -259
  77. package/dist/cli/{chunk-SDCIROIS.mjs → chunk-ZMU2DDID.mjs} +5 -5
  78. package/dist/cli/command-docs.js +2 -2
  79. package/dist/cli/command-docs.mjs +1 -1
  80. package/dist/cli/{csv-J7UVP4KB.mjs → csv-NM5IHLVM.mjs} +3 -3
  81. package/dist/cli/{csv-Y4YWZSLB.js → csv-RL53NPRV.js} +12 -12
  82. package/dist/cli/{db-CQ6NHMLG.mjs → db-FZTIS4QG.mjs} +5 -5
  83. package/dist/cli/{db-SVFCM6YZ.js → db-RJCFUM2J.js} +26 -26
  84. package/dist/cli/{describe-FSDW6LTN.js → describe-A2MGAI3Y.js} +24 -24
  85. package/dist/cli/{describe-Y65BU7ZY.mjs → describe-T77IEILZ.mjs} +16 -16
  86. package/dist/cli/describe-core.d.mts +2 -2
  87. package/dist/cli/describe-core.d.ts +2 -2
  88. package/dist/cli/describe-core.js +4 -4
  89. package/dist/cli/describe-core.mjs +3 -3
  90. package/dist/cli/{executions-IW762OIJ.mjs → executions-AMQK53QX.mjs} +4 -4
  91. package/dist/cli/{executions-SJIKBRHT.js → executions-R6UPRZ5N.js} +6 -6
  92. package/dist/cli/{feedback-VMJIWAMT.mjs → feedback-BA5ZHVCZ.mjs} +3 -3
  93. package/dist/cli/{feedback-RCYSUOB3.js → feedback-JFT536KI.js} +7 -7
  94. package/dist/cli/{git-Q2WY3K6X.mjs → git-5ONARXFO.mjs} +4 -4
  95. package/dist/cli/git-NHQR3NKF.js +24 -0
  96. package/dist/cli/index.js +135 -135
  97. package/dist/cli/index.mjs +37 -37
  98. package/dist/cli/{legacy-noops-JVEE2VHK.mjs → legacy-noops-7J4K6QUX.mjs} +4 -4
  99. package/dist/cli/{legacy-noops-U4YPPYXU.js → legacy-noops-WT7M7WYD.js} +7 -7
  100. package/dist/cli/{monitors-AY4KQRTC.mjs → monitors-N3WDXW7H.mjs} +19 -13
  101. package/dist/cli/{monitors-BMAOQ37R.js → monitors-YH6PKEIW.js} +99 -93
  102. package/dist/cli/{org-ME4X6HWH.mjs → org-2V5ELSYS.mjs} +4 -4
  103. package/dist/cli/{org-G5IURX74.js → org-KGYHMT5P.js} +64 -64
  104. package/dist/cli/{play-X5GSZOKZ.js → play-2JOQQRZI.js} +606 -567
  105. package/dist/cli/{play-WLYU7WQL.mjs → play-CL2LCBAF.mjs} +113 -74
  106. package/dist/cli/{providers-2LBMNB7B.mjs → providers-I7EEPWNW.mjs} +4 -4
  107. package/dist/cli/{providers-AHEUVD3R.js → providers-VIP6MCWC.js} +7 -7
  108. package/dist/cli/{quickstart-DP2SKLIG.js → quickstart-33WC2KWE.js} +5 -5
  109. package/dist/cli/{quickstart-DBLYGHJP.mjs → quickstart-VRBKQODE.mjs} +3 -3
  110. package/dist/cli/{search-YKJHY3ZJ.mjs → search-7TDSKXOO.mjs} +5 -5
  111. package/dist/cli/search-A6RZZ4LK.js +30 -0
  112. package/dist/cli/{secrets-ECLARBO6.mjs → secrets-DGLCIN7Y.mjs} +4 -4
  113. package/dist/cli/{secrets-2P3I3OEZ.js → secrets-TQH5FXAC.js} +13 -13
  114. package/dist/cli/{sessions-MC4ZCTSN.js → sessions-4D4UDPIS.js} +5 -5
  115. package/dist/cli/{sessions-3GDFID7R.mjs → sessions-D6QGKQ2G.mjs} +4 -4
  116. package/dist/cli/{settings-RTPJXMOA.mjs → settings-6HVXBCVR.mjs} +8 -8
  117. package/dist/cli/{settings-7SVR2OVL.js → settings-V3QRG4AO.js} +75 -75
  118. package/dist/cli/{setup-4WLIJX36.js → setup-6WP7D5I3.js} +42 -42
  119. package/dist/cli/{setup-OKAZZGAW.mjs → setup-CSJ3HSL7.mjs} +7 -7
  120. package/dist/cli/{skills-2CVL6RG5.mjs → skills-2MTWP4PS.mjs} +5 -5
  121. package/dist/cli/skills-QOYOARZT.js +29 -0
  122. package/dist/cli/{tools-KAFHP6J4.mjs → tools-GAR3BWB6.mjs} +15 -15
  123. package/dist/cli/tools-MGEKAIOU.js +44 -0
  124. package/dist/cli/update-HMZCLFLZ.js +31 -0
  125. package/dist/cli/{update-3ZV3W7I4.mjs → update-XV3WV3MU.mjs} +7 -7
  126. package/dist/cli/{workflow-DKSUNZXE.mjs → workflow-DTZAWSB2.mjs} +9 -9
  127. package/dist/cli/{workflow-GULDFFP3.js → workflow-WNE7ORMT.js} +19 -19
  128. package/dist/{client-CCWIUnk7.d.mts → client-BcfFWD4Z.d.mts} +19 -15
  129. package/dist/{client-vHqBm-OL.d.ts → client-DH-fmT69.d.ts} +19 -15
  130. package/dist/{compiler-manifest-lzWpbV3w.d.mts → compiler-manifest-DaFuA1ki.d.mts} +35 -32
  131. package/dist/{compiler-manifest-lzWpbV3w.d.ts → compiler-manifest-DaFuA1ki.d.ts} +35 -32
  132. package/dist/{index-CtNK-0nI.d.mts → index-0yS9ihly.d.mts} +10 -3
  133. package/dist/{index-C8Cy-YTm.d.ts → index-CRAScKPg.d.ts} +10 -3
  134. package/dist/index.d.mts +120 -150
  135. package/dist/index.d.ts +120 -150
  136. package/dist/index.js +77 -12
  137. package/dist/index.mjs +74 -9
  138. package/dist/install-integrity.json +99 -98
  139. package/dist/plays/bundle-play-file.d.mts +3 -3
  140. package/dist/plays/bundle-play-file.d.ts +3 -3
  141. package/dist/plays/bundle-play-file.mjs +1 -1
  142. package/dist/plays/play-description.d.mts +2 -2
  143. package/dist/plays/play-description.d.ts +2 -2
  144. package/dist/plays/run-request.d.mts +2 -2
  145. package/dist/plays/run-request.d.ts +2 -2
  146. package/dist/release.d.mts +1 -1
  147. package/dist/release.d.ts +1 -1
  148. package/dist/release.js +2 -2
  149. package/dist/release.mjs +1 -1
  150. package/package.json +1 -1
  151. package/dist/cli/auth-HD5AM2WM.js +0 -40
  152. package/dist/cli/git-JAW3UEGA.js +0 -24
  153. package/dist/cli/search-4K3VSDS5.js +0 -30
  154. package/dist/cli/skills-ZNSQOXO2.js +0 -29
  155. package/dist/cli/tools-W4U4FT3R.js +0 -44
  156. package/dist/cli/update-IE2FPLB5.js +0 -31
@@ -60,6 +60,14 @@ import type { ToolExecutionErrorSchemaVersion } from '../tool-execution-error';
60
60
  import type { PlaySandboxRuntimeDeclaration } from '../sandbox-runtime-limits';
61
61
  import { validatePlaySourceFilesHaveNoInlineSecrets } from '../secret-guardrails';
62
62
  import { MAX_PLAY_BUNDLE_BYTES } from './limits';
63
+ import {
64
+ parseScriptPlay,
65
+ PLAY_FILE_PATTERN,
66
+ playNameFromPath,
67
+ SCRIPT_PLAY_MODULE_DECLARATION,
68
+ validateScriptPlay,
69
+ wrapScriptPlay,
70
+ } from '../script-entry';
63
71
  import {
64
72
  extractPlaySourceAuthoringEdition,
65
73
  resolvePlaySourceAuthoringContractEdition,
@@ -83,7 +91,6 @@ const SOURCE_EXTENSIONS = [
83
91
  '.cjs',
84
92
  '.json',
85
93
  ];
86
- const PLAY_SOURCE_FILE_PATTERN = /\.play\.(?:[cm]?[jt]sx?)$/i;
87
94
  const TEXT_IMPORT_EXTENSIONS = new Set(['.md', '.txt']);
88
95
  const EXPLICIT_IMPORT_EXTENSIONS = new Set([
89
96
  ...SOURCE_EXTENSIONS,
@@ -143,13 +150,17 @@ export type PlayBundlingAdapter = {
143
150
  sdkPackageJson: string;
144
151
  sdkEntryFile: string;
145
152
  sdkTypesEntryFile?: string;
153
+ /** Reads through the sources the build analyzed. */
146
154
  discoverPackagedLocalFiles(
147
155
  filePath: string,
156
+ analyzedSources: Readonly<Record<string, string>>,
148
157
  ): Promise<PlayLocalFileDiscoveryResult>;
149
158
  typecheckPlaySource?(input: {
150
159
  sourceCode: string;
151
160
  sourcePath: string;
152
161
  importedFilePaths: string[];
162
+ /** File contents to use instead of the disk; an imported script play is its declaration. */
163
+ sourceFiles: Record<string, string>;
153
164
  }): Promise<string[]> | string[];
154
165
  warnAboutNonDevelopmentBundling?(filePath: string): void;
155
166
  };
@@ -219,6 +230,10 @@ type SourceGraphAnalysis = {
219
230
  sourceAuthoringEdition: PlaySourceAuthoringEdition;
220
231
  sourceHasLocalPlayExport: boolean;
221
232
  importedPlayDependencies: ImportedPlayDependency[];
233
+ /** Imported play files as typecheck reads them instead of the disk: a script play as a play declaration. */
234
+ importedPlaySources: Record<string, string>;
235
+ /** The entry when it is a script play; esbuild bundles it wrapped, not rewritten. */
236
+ entryScript: string | null;
222
237
  };
223
238
 
224
239
  type PlayWorkspace = {
@@ -332,7 +347,7 @@ function getPackageName(specifier: string): string {
332
347
  }
333
348
 
334
349
  function isPlaySourceFile(filePath: string): boolean {
335
- return PLAY_SOURCE_FILE_PATTERN.test(filePath);
350
+ return PLAY_FILE_PATTERN.test(filePath);
336
351
  }
337
352
 
338
353
  function stripCommentsToSpaces(source: string): string {
@@ -557,8 +572,15 @@ function findMatchingBrace(source: string, openIndex: number): number {
557
572
  return -1;
558
573
  }
559
574
 
560
- export function extractDefinedPlayName(sourceCode: string): string | null {
561
- return extractDefinedPlayMetadata(sourceCode, null)?.name ?? null;
575
+ /**
576
+ * The play name a file defines. For a script play this is `config.name`, else
577
+ * the file name when `filePath` is given (`lookup.play.ts` → `lookup`).
578
+ */
579
+ export function extractDefinedPlayName(
580
+ sourceCode: string,
581
+ filePath?: string,
582
+ ): string | null {
583
+ return extractDefinedPlayMetadata(sourceCode, null, filePath)?.name ?? null;
562
584
  }
563
585
 
564
586
  export function extractDefinedPlayNameForExport(
@@ -606,6 +628,8 @@ function parsePlaySourceAst(sourceCode: string): AstNode | null {
606
628
  ecmaVersion: 'latest',
607
629
  sourceType: 'module',
608
630
  allowHashBang: true,
631
+ // Script plays may end early with a top-level `return`.
632
+ allowReturnOutsideFunction: true,
609
633
  }) as unknown as AstNode;
610
634
  } catch {
611
635
  try {
@@ -620,6 +644,8 @@ function parsePlaySourceAst(sourceCode: string): AstNode | null {
620
644
  ecmaVersion: 'latest',
621
645
  sourceType: 'module',
622
646
  allowHashBang: true,
647
+ // Script plays may end early with a top-level `return`.
648
+ allowReturnOutsideFunction: true,
623
649
  }) as unknown as AstNode;
624
650
  } catch {
625
651
  return null;
@@ -1247,6 +1273,40 @@ function playMetadataFromDefinePlayCall(
1247
1273
  };
1248
1274
  }
1249
1275
 
1276
+ /** A script's config object read like definePlay's options. */
1277
+ function playMetadataFromScriptConfig(
1278
+ config: AstNode | null,
1279
+ context: PlayMetadataExtractionContext,
1280
+ filePath: string | undefined,
1281
+ ): ExtractedPlayMetadata {
1282
+ const toolErrorSchemaVersion = toolErrorSchemaVersionFromOptions(
1283
+ config,
1284
+ context,
1285
+ );
1286
+ const toolResponseReceiptRevision = toolResponseReceiptRevisionFromOptions(
1287
+ config,
1288
+ context,
1289
+ );
1290
+ return {
1291
+ name:
1292
+ stringPropertyFromObjectExpression(config, 'name', context) ??
1293
+ (filePath ? playNameFromPath(filePath) : null),
1294
+ description: stringPropertyFromObjectExpression(
1295
+ config,
1296
+ 'description',
1297
+ context,
1298
+ ),
1299
+ sandboxRuntimeDeclaration: sandboxRuntimeDeclarationFromOptions(
1300
+ config,
1301
+ context,
1302
+ ),
1303
+ toolErrorSchemaVersion: toolErrorSchemaVersion ?? null,
1304
+ toolErrorSchemaVersionUnknown: toolErrorSchemaVersion === null,
1305
+ toolResponseReceiptRevision: toolResponseReceiptRevision ?? null,
1306
+ toolResponseReceiptRevisionUnknown: toolResponseReceiptRevision === null,
1307
+ };
1308
+ }
1309
+
1250
1310
  function resolveExportExpression(
1251
1311
  exportName: string | null,
1252
1312
  context: PlayMetadataExtractionContext,
@@ -1295,11 +1355,21 @@ function resolveExportExpression(
1295
1355
  function extractDefinedPlayMetadata(
1296
1356
  sourceCode: string,
1297
1357
  exportName: string | null,
1358
+ filePath?: string,
1298
1359
  ): ExtractedPlayMetadata | null {
1299
1360
  const ast = parsePlaySourceAst(sourceCode);
1300
1361
  if (!ast) return null;
1301
1362
  const context = buildPlayMetadataContext(ast);
1302
1363
 
1364
+ // A script play is one play, the default export; parseScriptPlay only
1365
+ // throws on source that failed to parse above, which already returned.
1366
+ const script =
1367
+ exportName === null || exportName === 'default'
1368
+ ? parseScriptPlay(sourceCode)
1369
+ : null;
1370
+ if (script)
1371
+ return playMetadataFromScriptConfig(script.config, context, filePath);
1372
+
1303
1373
  const exportedExpression = resolveExportExpression(exportName, context);
1304
1374
  const exportedMetadata = playMetadataFromDefinePlayCall(
1305
1375
  exportedExpression,
@@ -1745,19 +1815,23 @@ export function instrumentPlayDocflowRuntimeHits(sourceCode: string): string {
1745
1815
 
1746
1816
  // Build the parent index once so every binding's symbol resolution reuses it.
1747
1817
  const parents = buildDocflowParentIndex(ast);
1818
+ // A script play has no run function: its module-level runtime is the context.
1819
+ const scriptContext = parseScriptPlay(sourceCode)?.contextName ?? null;
1748
1820
  for (const binding of parsed.bindings) {
1749
1821
  // ADR 0016 rule 1: prefer the statement the `out:` symbol names; fall back
1750
1822
  // to positional resolution. Instrumentation and `plays check` share this
1751
1823
  // resolver, so the observed statement and the lint agree.
1752
1824
  const resolution = resolveDocflowBinding(ast, binding, lineStarts, parents);
1753
- const context = findDocflowContext({
1754
- ast,
1755
- sourceCode,
1756
- statement: resolution.statement,
1757
- bindingLine: binding.line,
1758
- lineStarts,
1759
- parents,
1760
- });
1825
+ const context =
1826
+ findDocflowContext({
1827
+ ast,
1828
+ sourceCode,
1829
+ statement: resolution.statement,
1830
+ bindingLine: binding.line,
1831
+ lineStarts,
1832
+ parents,
1833
+ }) ??
1834
+ (scriptContext ? { kind: 'named' as const, name: scriptContext } : null);
1761
1835
  // No owning definePlay: the binding is in a module-level helper with no
1762
1836
  // context in scope, so it is observed through its caller's bindings.
1763
1837
  if (!context) continue;
@@ -1893,30 +1967,41 @@ export function instrumentPlayDocflowRuntimeHits(sourceCode: string): string {
1893
1967
  );
1894
1968
  }
1895
1969
 
1970
+ /**
1971
+ * Serves esbuild the exact sources the graph analysis read, so what is
1972
+ * bundled is what was hashed and checked.
1973
+ */
1896
1974
  function docflowRuntimeInstrumentationPlugin(
1897
- customerSourceFilePaths: readonly string[],
1975
+ analyzedSources: Readonly<Record<string, string>>,
1976
+ scriptEntry: { path: string; source: string } | null,
1898
1977
  ): Plugin {
1899
- const customerSourceFiles = new Set(
1900
- customerSourceFilePaths
1901
- .filter((path) => extname(path).toLowerCase() !== '.json')
1902
- .map((path) => resolve(path)),
1978
+ const customerSourceFiles = new Map(
1979
+ Object.entries(analyzedSources)
1980
+ .filter(([path]) => extname(path).toLowerCase() !== '.json')
1981
+ .map(([path, contents]) => [resolve(path), contents]),
1903
1982
  );
1904
1983
  return {
1905
1984
  name: 'deepline-docflow-runtime-instrumentation',
1906
1985
  setup(buildContext) {
1907
1986
  buildContext.onLoad({ filter: /./ }, (args) => {
1908
- if (!customerSourceFiles.has(resolve(args.path))) return undefined;
1987
+ if (scriptEntry && resolve(args.path) === resolve(scriptEntry.path)) {
1988
+ return {
1989
+ contents: scriptEntryModule(scriptEntry.source, args.path),
1990
+ loader: sourceLoaderForPath(args.path),
1991
+ resolveDir: dirname(args.path),
1992
+ };
1993
+ }
1994
+ const contents = customerSourceFiles.get(resolve(args.path));
1995
+ if (contents === undefined) return undefined;
1909
1996
  if (isTextImportFile(args.path)) {
1910
1997
  return {
1911
- contents: readFileSync(args.path, 'utf8'),
1998
+ contents,
1912
1999
  loader: 'text',
1913
2000
  resolveDir: dirname(args.path),
1914
2001
  };
1915
2002
  }
1916
2003
  return {
1917
- contents: instrumentPlayDocflowRuntimeHits(
1918
- readFileSync(args.path, 'utf8'),
1919
- ),
2004
+ contents: instrumentPlayDocflowRuntimeHits(contents),
1920
2005
  loader: sourceLoaderForPath(args.path),
1921
2006
  resolveDir: dirname(args.path),
1922
2007
  };
@@ -1925,6 +2010,24 @@ function docflowRuntimeInstrumentationPlugin(
1925
2010
  };
1926
2011
  }
1927
2012
 
2013
+ /**
2014
+ * A script-play entry, instrumented, as the function the runner calls: the
2015
+ * module body runs inside the run and its default-exported play function, if
2016
+ * any, is dispatched (see `wrapScriptPlay`).
2017
+ */
2018
+ function scriptEntryModule(source: string, path: string): string {
2019
+ const instrumented = instrumentPlayDocflowRuntimeHits(source);
2020
+ const script = parseScriptPlay(instrumented);
2021
+ if (!script) {
2022
+ throw new Error(
2023
+ 'Docflow instrumentation turned a script play into a non-script.',
2024
+ );
2025
+ }
2026
+ return wrapScriptPlay(instrumented, script, {
2027
+ typed: /^tsx?$/.test(sourceLoaderForPath(path)),
2028
+ });
2029
+ }
2030
+
1928
2031
  function buildImportedPlayProxyModule(playName: string): string {
1929
2032
  const serializedName = JSON.stringify(playName);
1930
2033
  return `
@@ -2109,6 +2212,8 @@ async function analyzeSourceGraph(
2109
2212
  const nodeBuiltins = new Set<string>();
2110
2213
  const packages = new Map<string, string | null>();
2111
2214
  const importedPlayDependencies = new Map<string, ImportedPlayDependency>();
2215
+ const importedPlaySources = new Map<string, string>();
2216
+ let entryScript: string | null = null;
2112
2217
  const visited = new Set<string>();
2113
2218
  const importViolations: string[] = [];
2114
2219
 
@@ -2123,6 +2228,13 @@ async function analyzeSourceGraph(
2123
2228
  /* turbopackIgnore: true */ absolutePath,
2124
2229
  'utf-8',
2125
2230
  );
2231
+ if (absolutePath === absoluteEntryFile) {
2232
+ const script = parseScriptPlay(sourceCode);
2233
+ if (script) {
2234
+ validateScriptPlay(sourceCode, script);
2235
+ entryScript = sourceCode;
2236
+ }
2237
+ }
2126
2238
  localFiles.set(absolutePath, sourceCode);
2127
2239
 
2128
2240
  if (
@@ -2166,10 +2278,20 @@ async function analyzeSourceGraph(
2166
2278
  /* turbopackIgnore: true */ resolved,
2167
2279
  'utf-8',
2168
2280
  );
2169
- const importedPlayName = extractDefinedPlayName(importedSource);
2281
+ const importedScript = parseScriptPlay(importedSource);
2282
+ if (importedScript)
2283
+ validateScriptPlay(importedSource, importedScript);
2284
+ // A script play has no module shape to type-check against: give the
2285
+ // checker a play reference. A definePlay module is checked as usual.
2286
+ if (importedScript)
2287
+ importedPlaySources.set(resolved, SCRIPT_PLAY_MODULE_DECLARATION);
2288
+ const importedPlayName = extractDefinedPlayName(
2289
+ importedSource,
2290
+ resolved,
2291
+ );
2170
2292
  if (!importedPlayName) {
2171
2293
  throw new Error(
2172
- `${absolutePath}:${line}:${column} Imported play file "${specifier}" must export definePlay(...) so it can be runtime-composed.`,
2294
+ `${absolutePath}:${line}:${column} Imported play file "${specifier}" is not a play: write it as a script play (import deepline from 'deepline') or default-export a play function, so it can be runtime-composed.`,
2173
2295
  );
2174
2296
  }
2175
2297
  importedPlayDependencies.set(resolved, {
@@ -2243,6 +2365,8 @@ async function analyzeSourceGraph(
2243
2365
  .sort((left, right) => left.filePath.localeCompare(right.filePath)),
2244
2366
  }),
2245
2367
  );
2368
+ // Read the author's file: a script's metadata comes from its config.
2369
+ const authoredSource: string = sourceCode;
2246
2370
  const sourceAst = parsePlaySourceAst(sourceCode);
2247
2371
  if (!sourceAst)
2248
2372
  throw new Error(
@@ -2258,9 +2382,13 @@ async function analyzeSourceGraph(
2258
2382
  selection.definition,
2259
2383
  buildPlayMetadataContext(sourceAst),
2260
2384
  )
2261
- : extractDefinedPlayMetadata(sourceCode, exportName)) ??
2385
+ : extractDefinedPlayMetadata(
2386
+ authoredSource,
2387
+ exportName,
2388
+ absoluteEntryFile,
2389
+ )) ??
2262
2390
  (exportName === 'default'
2263
- ? extractDefinedPlayMetadata(sourceCode, null)
2391
+ ? extractDefinedPlayMetadata(authoredSource, null, absoluteEntryFile)
2264
2392
  : null);
2265
2393
  const compatibilityDiagnostic = metadata?.toolErrorSchemaVersionUnknown
2266
2394
  ? 'definePlay compatibility.toolErrorSchemaVersion must be the static literal 0 or 1.'
@@ -2310,6 +2438,8 @@ async function analyzeSourceGraph(
2310
2438
  importedPlayDependencies: [...importedPlayDependencies.values()].sort(
2311
2439
  (left, right) => left.filePath.localeCompare(right.filePath),
2312
2440
  ),
2441
+ importedPlaySources: Object.fromEntries(importedPlaySources),
2442
+ entryScript,
2313
2443
  };
2314
2444
  }
2315
2445
 
@@ -2434,7 +2564,8 @@ type EsbuildBundleOutput = {
2434
2564
 
2435
2565
  async function runEsbuildForCjsNode(
2436
2566
  entryFile: string,
2437
- customerSourceFilePaths: string[],
2567
+ analyzedSources: Readonly<Record<string, string>>,
2568
+ entryScript: string | null,
2438
2569
  importedPlayDependencies: ImportedPlayDependency[],
2439
2570
  adapter: PlayBundlingAdapter,
2440
2571
  exportName: string,
@@ -2442,14 +2573,14 @@ async function runEsbuildForCjsNode(
2442
2573
  ): Promise<EsbuildBundleOutput | string[]> {
2443
2574
  const sdkAliasPlugin = localSdkAliasPlugin(adapter);
2444
2575
  const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
2445
- const docflowPlugin = docflowRuntimeInstrumentationPlugin([
2446
- entryFile,
2447
- ...customerSourceFilePaths,
2448
- ]);
2576
+ const docflowPlugin = docflowRuntimeInstrumentationPlugin(
2577
+ analyzedSources,
2578
+ entryScript === null ? null : { path: entryFile, source: entryScript },
2579
+ );
2449
2580
  const namedExportShim =
2450
- exportName === 'default'
2451
- ? null
2452
- : `export { ${exportName} as default } from ${JSON.stringify(entryFile)};\n`;
2581
+ exportName !== 'default'
2582
+ ? `export { ${exportName} as default } from ${JSON.stringify(entryFile)};\n`
2583
+ : null;
2453
2584
  const result = await build({
2454
2585
  ...(namedExportShim
2455
2586
  ? {
@@ -2539,7 +2670,10 @@ export async function bundlePlayFile(
2539
2670
  );
2540
2671
  }
2541
2672
  analysis.graphHash = sha256(
2542
- `${analysis.graphHash}\nentry-export:${exportName}\nauthoring-contract-edition:${edition}${edition >= 10 ? '\nimported-proxy-options:description' : ''}${preservedCompatibility === undefined ? '\ndataset-row-input:current_run' : `\npreserved-compatibility:${JSON.stringify(preservedCompatibility)}`}`,
2673
+ `${analysis.graphHash}\nentry-export:${exportName}\nauthoring-contract-edition:${edition}${edition >= 10 ? '\nimported-proxy-options:description' : ''}${preservedCompatibility === undefined ? '\ndataset-row-input:current_run' : `\npreserved-compatibility:${JSON.stringify(preservedCompatibility)}`}` +
2674
+ // A script entry is bundled wrapped; keep its artifacts apart.
2675
+ // definePlay plays keep their existing hash.
2676
+ (analysis.entryScript === null ? '' : '\nentry-form:script-v2'),
2543
2677
  );
2544
2678
  const sourceFiles = Object.fromEntries(
2545
2679
  Object.entries(analysis.sourceFiles).map(([sourcePath, sourceCode]) => [
@@ -2573,6 +2707,10 @@ export async function bundlePlayFile(
2573
2707
  (dependency) => dependency.filePath,
2574
2708
  ),
2575
2709
  ],
2710
+ sourceFiles: {
2711
+ ...analysis.sourceFiles,
2712
+ ...analysis.importedPlaySources,
2713
+ },
2576
2714
  })) ?? []),
2577
2715
  ];
2578
2716
  if (typecheckErrors.length > 0) {
@@ -2591,8 +2729,10 @@ export async function bundlePlayFile(
2591
2729
  target,
2592
2730
  adapter,
2593
2731
  );
2594
- const discoveredFiles =
2595
- await adapter.discoverPackagedLocalFiles(absolutePath);
2732
+ const discoveredFiles = await adapter.discoverPackagedLocalFiles(
2733
+ absolutePath,
2734
+ analysis.sourceFiles,
2735
+ );
2596
2736
  if (cachedArtifact) {
2597
2737
  const cachedArtifactSizeError = getBundleSizeError(
2598
2738
  absolutePath,
@@ -2642,7 +2782,8 @@ export async function bundlePlayFile(
2642
2782
  const bundleRoot = resolve(sourceIdentityRoot ?? adapter.projectRoot);
2643
2783
  const buildOutcome = await runEsbuildForCjsNode(
2644
2784
  absolutePath,
2645
- analysis.importPolicy.localFiles,
2785
+ analysis.sourceFiles,
2786
+ analysis.entryScript,
2646
2787
  analysis.importedPlayDependencies,
2647
2788
  adapter,
2648
2789
  exportName,
@@ -217,13 +217,13 @@ export type PlayDatasetTransformOptions = {
217
217
  };
218
218
 
219
219
  /**
220
- * Durable handle for rows produced by `ctx.csv(...)` or `ctx.dataset(...).run()`.
220
+ * Durable handle for rows produced by `deepline.csv(...)` or `deepline.dataset(...).run()`.
221
221
  *
222
222
  * A `PlayDataset` is not a normal in-memory array. It points at runtime-managed
223
223
  * rows, usually backed by persisted sheet storage, and carries metadata such as
224
224
  * dataset kind, dataset id, table namespace, count, and preview rows.
225
225
  *
226
- * Pass dataset handles directly into later `ctx.dataset(...)` stages by default so
226
+ * Pass dataset handles directly into later `deepline.dataset(...)` stages by default so
227
227
  * Deepline keeps row progress, retries, memory use, and table output under
228
228
  * runtime control. Use `count()` and `peek()` for bounded inspection. Use
229
229
  * `materialize(limit)` or async iteration only when the dataset is intentionally
@@ -1288,6 +1288,10 @@ function attachBindingsToBlocks(
1288
1288
  const exportRanges = playExportSourceRanges(sourceCode);
1289
1289
  for (const binding of bindings) {
1290
1290
  let owners = blocks.filter((block) => block.nodes.has(binding.nodeId));
1291
+ // A helper module can serve several plays, each drawing only its own
1292
+ // boxes, so an imported annotation this play's diagram does not draw is
1293
+ // another play's. An annotation in the play's own file must name a node.
1294
+ if (owners.length === 0 && binding.sourcePath) continue;
1291
1295
  if (owners.length === 0) {
1292
1296
  errors.push(
1293
1297
  `Docflow annotation "${binding.nodeId}" does not name a graph node.`,
@@ -1,7 +1,7 @@
1
1
  import type { PlayAuthoringFetchResponse } from './authoring-contract';
2
2
 
3
3
  /**
4
- * Edition 5+ `ctx.fetch` error for a non-2xx response. Its full readable body is secret-redacted; editions 1–4 retain `PlayFetchResponse { ok: false }`.
4
+ * Edition 5+ `deepline.fetch` error for a non-2xx response. Its full readable body is secret-redacted; editions 1–4 retain `PlayFetchResponse { ok: false }`.
5
5
  *
6
6
  * @sdkReference runtime 178 CtxFetchHttpError
7
7
  */
@@ -9,6 +9,7 @@ import {
9
9
  relative,
10
10
  } from 'node:path';
11
11
  import * as ts from 'typescript';
12
+ import { isRuntimeReceiver, playRuntimeNames } from './script-entry';
12
13
 
13
14
  export interface PlayLocalFileReference {
14
15
  sourceFragment: string;
@@ -63,14 +64,18 @@ function contentTypeForFile(filePath: string): string {
63
64
  return 'application/octet-stream';
64
65
  }
65
66
 
66
- function isCtxCsvCall(node: ts.CallExpression): boolean {
67
+ /** `ctx.csv(...)`, `*Ctx.csv(...)`, or a script's `deepline.csv(...)`. */
68
+ function isCtxCsvCall(
69
+ node: ts.CallExpression,
70
+ runtimeNames: ReadonlySet<string>,
71
+ ): boolean {
67
72
  if (!ts.isPropertyAccessExpression(node.expression)) {
68
73
  return false;
69
74
  }
70
75
  const target = node.expression.expression;
71
76
  return (
72
77
  ts.isIdentifier(target) &&
73
- (target.text === 'ctx' || target.text.endsWith('Ctx')) &&
78
+ isRuntimeReceiver(target.text, runtimeNames) &&
74
79
  node.expression.name.text === 'csv'
75
80
  );
76
81
  }
@@ -257,6 +262,7 @@ async function resolveLocalImport(
257
262
 
258
263
  export async function discoverPackagedLocalFiles(
259
264
  entryFile: string,
265
+ analyzedSources: Readonly<Record<string, string>> = {},
260
266
  ): Promise<PlayLocalFileDiscoveryResult> {
261
267
  const absoluteEntryFile = resolve(entryFile);
262
268
  const packagingRoot = dirname(absoluteEntryFile);
@@ -271,7 +277,8 @@ export async function discoverPackagedLocalFiles(
271
277
  }
272
278
  visitedFiles.add(absolutePath);
273
279
 
274
- const sourceCode = await readFile(absolutePath, 'utf-8');
280
+ const sourceCode =
281
+ analyzedSources[absolutePath] ?? (await readFile(absolutePath, 'utf-8'));
275
282
  if (isTextImportFile(absolutePath)) {
276
283
  return;
277
284
  }
@@ -283,10 +290,11 @@ export async function discoverPackagedLocalFiles(
283
290
  ts.ScriptKind.TS,
284
291
  );
285
292
  const constants = collectTopLevelStringConstants(sourceFile);
293
+ const runtimeNames = playRuntimeNames(sourceCode);
286
294
  const childVisits: Promise<void>[] = [];
287
295
 
288
296
  const visitNode = async (node: ts.Node): Promise<void> => {
289
- if (ts.isCallExpression(node) && isCtxCsvCall(node)) {
297
+ if (ts.isCallExpression(node) && isCtxCsvCall(node, runtimeNames)) {
290
298
  const argument = node.arguments[0];
291
299
  if (!argument) {
292
300
  unresolved.push({
@@ -19,6 +19,7 @@ import {
19
19
  parsePlaySourceForAnalysis,
20
20
  type AstNode,
21
21
  } from './ts-ast';
22
+ import { parseScriptPlay } from './script-entry';
22
23
 
23
24
  /** The export name the runtime, the registry and the CLI all use for a file's
24
25
  * default play. Aliases resolve to it, never the other way round. */
@@ -111,8 +112,16 @@ function definePlayName(node: AstNode | null): string | null {
111
112
  astArray(expression.arguments)[0] ?? null,
112
113
  );
113
114
  if (first?.type !== 'ObjectExpression') return stringLiteralValue(first);
114
- let id: string | null = null;
115
- for (const property of astArray(first.properties)) {
115
+ return objectStringProperty(first, 'id');
116
+ }
117
+
118
+ /** The literal string `propertyName` of an object literal, when it is one. */
119
+ function objectStringProperty(
120
+ object: AstNode | null,
121
+ propertyName: string,
122
+ ): string | null {
123
+ let value: string | null = null;
124
+ for (const property of astArray(object?.properties)) {
116
125
  if (property.type !== 'Property' || property.computed) continue;
117
126
  const key = isAstNode(property.key) ? property.key : null;
118
127
  const keyName =
@@ -120,10 +129,12 @@ function definePlayName(node: AstNode | null): string | null {
120
129
  (key?.type === 'Literal' && typeof key.value === 'string'
121
130
  ? key.value
122
131
  : null);
123
- if (keyName !== 'id') continue;
124
- id = stringLiteralValue(isAstNode(property.value) ? property.value : null);
132
+ if (keyName !== propertyName) continue;
133
+ value = stringLiteralValue(
134
+ isAstNode(property.value) ? property.value : null,
135
+ );
125
136
  }
126
- return id;
137
+ return value;
127
138
  }
128
139
 
129
140
  /**
@@ -137,6 +148,17 @@ export function listPlayFileExports(
137
148
  ): PlayFileExport[] | null {
138
149
  const ast = parsePlaySourceForAnalysis(sourceCode);
139
150
  if (!ast) return null;
151
+ // A script play is one play, the default; its name is `config.name`.
152
+ const script = parseScriptPlay(sourceCode);
153
+ if (script) {
154
+ return [
155
+ {
156
+ name: PLAY_DEFAULT_EXPORT,
157
+ aliases: [],
158
+ playName: objectStringProperty(script.config, 'name'),
159
+ },
160
+ ];
161
+ }
140
162
 
141
163
  /** Local const/let/var name -> its initializer, for resolving `export { x }`
142
164
  * and `export default x` back to the `definePlay` call they name. */