deepline 0.3.59 → 0.3.61

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.
@@ -7,10 +7,10 @@ import type { ToolExecutionErrorSchemaVersion } from './tool-execution-error';
7
7
  import type { PlayDataset, PlayDatasetInput, PlayDatasetRow } from './dataset';
8
8
 
9
9
  export const LEGACY_PLAY_AUTHORING_CONTRACT_EDITION = 1 as const;
10
- export const PLAY_AUTHORING_CONTRACT_EDITION = 5 as const;
10
+ export const PLAY_AUTHORING_CONTRACT_EDITION = 6 as const;
11
11
  export const PLAY_AUTHORING_INPUT_SCHEMA_SNAPSHOT_EDITION = 3 as const;
12
12
  export const SUPPORTED_PLAY_AUTHORING_CONTRACT_EDITIONS = [
13
- 1, 2, 3, 4, 5,
13
+ 1, 2, 3, 4, 5, 6,
14
14
  ] as const;
15
15
 
16
16
  export type PlayAuthoringContractEdition =
@@ -59,6 +59,14 @@ export const PLAY_AUTHORING_CONTRACT_CHANGELOG = [
59
59
  newWritesEnd: null,
60
60
  readerRemoval: null,
61
61
  },
62
+ {
63
+ edition: 6,
64
+ changed:
65
+ 'Adds static cron input and rejects unknown definePlay and binding fields during new admission. Editions 1–5 retain their admitted binding semantics.',
66
+ compatibilityOwner: 'Plays Runtime',
67
+ newWritesEnd: null,
68
+ readerRemoval: null,
69
+ },
62
70
  ] as const;
63
71
 
64
72
  /**
@@ -310,7 +318,11 @@ export type PlayTriggersSummary = {
310
318
  sqlListeners?: PlayTriggerSqlListenerSummary[];
311
319
  /** Present when the play has at least one sqlListener trigger. */
312
320
  sqlListenerEvent?: PlayTriggerSqlListenerEventSummary;
313
- cron?: { schedule: string; timezone?: string };
321
+ cron?: {
322
+ schedule: string;
323
+ timezone?: string;
324
+ input?: Record<string, unknown>;
325
+ };
314
326
  webhook?: true;
315
327
  };
316
328
 
@@ -344,9 +356,11 @@ export function derivePlayTriggersSummary(
344
356
  };
345
357
  }
346
358
  if (bindings.cron?.schedule) {
347
- summary.cron = bindings.cron.timezone
348
- ? { schedule: bindings.cron.schedule, timezone: bindings.cron.timezone }
349
- : { schedule: bindings.cron.schedule };
359
+ summary.cron = {
360
+ schedule: bindings.cron.schedule,
361
+ ...(bindings.cron.timezone ? { timezone: bindings.cron.timezone } : {}),
362
+ ...(bindings.cron.input ? { input: bindings.cron.input } : {}),
363
+ };
350
364
  }
351
365
  if (bindings.webhook) summary.webhook = true;
352
366
  return summary.sqlListeners || summary.cron || summary.webhook
@@ -377,15 +391,74 @@ export type PlayAuthoringAstBindings = {
377
391
  };
378
392
  auth?: PlayStandardWebhookAuth;
379
393
  };
380
- cron?: { schedule: string; timezone?: string };
394
+ cron?: {
395
+ schedule: string;
396
+ timezone?: string;
397
+ /** Static JSON object supplied to every run started by this cron binding. */
398
+ input?: Record<string, unknown>;
399
+ };
381
400
  sqlListeners?: PlayAuthoringAstSqlListenerDeclaration[];
382
401
  invalidSqlListenerSingular?: boolean;
383
402
  invalidSqlListenerShape?: boolean;
384
403
  secrets?: string[];
385
404
  };
386
405
 
406
+ /**
407
+ * Static binding vocabulary. The AST adapter reads this rather than carrying
408
+ * a second allowlist, so `plays check` and publish reject typos consistently.
409
+ * Existing revisions are never re-admitted merely because this expands.
410
+ */
411
+ export const PLAY_AUTHORING_BINDING_FIELDS = {
412
+ root: [
413
+ 'billing',
414
+ 'compatibility',
415
+ 'cron',
416
+ 'inline',
417
+ 'runtime',
418
+ 'secrets',
419
+ 'sqlListeners',
420
+ 'webhook',
421
+ ],
422
+ cron: ['schedule', 'timezone', 'input'],
423
+ webhook: ['auth', 'hmac'],
424
+ sqlListener: [
425
+ 'id',
426
+ 'tool',
427
+ 'stream',
428
+ 'where',
429
+ 'table',
430
+ 'monitor',
431
+ 'output',
432
+ 'operations',
433
+ ],
434
+ } as const;
435
+
436
+ /** Fields allowed in the object form and third argument of `definePlay`. */
437
+ export const PLAY_AUTHORING_DEFINE_PLAY_OPTION_FIELDS = [
438
+ 'id',
439
+ 'name',
440
+ 'description',
441
+ 'input',
442
+ 'run',
443
+ 'bindings',
444
+ ...PLAY_AUTHORING_BINDING_FIELDS.root,
445
+ ] as const;
446
+
447
+ /**
448
+ * Static cron input must be an object because the scheduler accepts a JSON
449
+ * object. It is tied to the Play handler input so TypeScript rejects missing
450
+ * required fields and incompatible values before the Play reaches `check`.
451
+ */
452
+ export type PlayAuthoringCronInput<TInput> = TInput extends readonly unknown[]
453
+ ? never
454
+ : TInput extends object
455
+ ? TInput
456
+ : never;
457
+
387
458
  /** The one public type for options accepted by definePlay. */
388
- export type PlayAuthoringBindings = {
459
+ export type PlayAuthoringBindings<
460
+ TInput = Record<string, unknown>,
461
+ > = {
389
462
  description?: string;
390
463
  compatibility?: {
391
464
  toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
@@ -420,6 +493,8 @@ export type PlayAuthoringBindings = {
420
493
  cron?: {
421
494
  schedule: string;
422
495
  timezone?: string;
496
+ /** Static JSON object supplied to every run started by this cron binding. */
497
+ input?: PlayAuthoringCronInput<TInput>;
423
498
  };
424
499
  sqlListeners?: PlaySqlListenerDeclaration[];
425
500
  secrets?: readonly string[];
@@ -495,7 +570,7 @@ export type PlaySecretAwareRequestInit = Omit<RequestInit, 'headers'> & {
495
570
  /** Ordinary request headers, recorded in the durable receipt with any resolved Play secret value redacted. Prefer `auth` for credentials: it enforces HTTPS and keeps the auth header out of the receipt. */
496
571
  headers?: HeadersInit;
497
572
  /**
498
- * One or more credentialed headers for this request. Pass a single `ctx.secrets` auth for the common case, or an array when an API requires multiple credentialed headers — for example, Supabase with both `apikey` and `Authorization`. Auth-helper requests require HTTPS and omit the credential from the durable receipt. Each auth entry must target a distinct header.
573
+ * One or more credentialed headers for this request. Pass a single `ctx.secrets` auth for the common case, or an array when an API requires multiple credentialed headers. Auth-helper requests require HTTPS and omit the credential from the durable receipt. Each auth entry must target a distinct header.
499
574
  */
500
575
  auth?: PlaySecretAuthInput;
501
576
  };
@@ -522,10 +597,10 @@ export type PlayAuthoringDefineConfig<
522
597
  description?: string;
523
598
  input: PlayAuthoringInputContract<TInput>;
524
599
  run: (ctx: TContext, input: TInput) => Promise<TOutput>;
525
- bindings?: PlayAuthoringBindings;
526
- billing?: PlayAuthoringBindings['billing'];
527
- runtime?: PlayAuthoringBindings['runtime'];
528
- compatibility?: PlayAuthoringBindings['compatibility'];
600
+ bindings?: PlayAuthoringBindings<TInput>;
601
+ billing?: PlayAuthoringBindings<TInput>['billing'];
602
+ runtime?: PlayAuthoringBindings<TInput>['runtime'];
603
+ compatibility?: PlayAuthoringBindings<TInput>['compatibility'];
529
604
  };
530
605
 
531
606
  /** Shared callable-plus-handle shape returned by `definePlay`. */
@@ -536,9 +611,9 @@ export type PlayAuthoringDefinedPlay<
536
611
  THandle extends object,
537
612
  > = ((ctx: TContext, input: TInput) => Promise<TOutput>) &
538
613
  THandle & {
539
- readonly bindings?: PlayAuthoringBindings;
540
- readonly runtime?: PlayAuthoringBindings['runtime'];
541
- readonly compatibility?: PlayAuthoringBindings['compatibility'];
614
+ readonly bindings?: PlayAuthoringBindings<TInput>;
615
+ readonly runtime?: PlayAuthoringBindings<TInput>['runtime'];
616
+ readonly compatibility?: PlayAuthoringBindings<TInput>['compatibility'];
542
617
  readonly playName: string;
543
618
  };
544
619
 
@@ -1428,6 +1503,24 @@ export const PLAY_AUTHORING_FIELD_REGISTRY = {
1428
1503
  errorMessage:
1429
1504
  'bindings.cron.timezone must be a valid non-empty IANA timezone string.',
1430
1505
  },
1506
+ 'bindings.cron.input': {
1507
+ schema: Type.Object({}, { additionalProperties: true }),
1508
+ fixtures: {
1509
+ valid: { apply: true },
1510
+ invalid: ['apply'],
1511
+ absent: undefined,
1512
+ unresolved: ['cronInput'],
1513
+ edition1: undefined,
1514
+ },
1515
+ referenceType: 'Record<string, unknown>',
1516
+ required: false,
1517
+ resolution: 'static-required',
1518
+ issueCode: 'play_authoring_binding_invalid',
1519
+ description:
1520
+ 'Static JSON object passed to every run created by this cron binding.',
1521
+ errorMessage:
1522
+ 'bindings.cron.input must be a static JSON object (no variables, spreads, or functions).',
1523
+ },
1431
1524
  'bindings.sqlListeners': {
1432
1525
  schema: Type.Array(Type.Object({}, { additionalProperties: true })),
1433
1526
  fixtures: {
@@ -2619,14 +2712,15 @@ export const PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
2619
2712
  ' readonly timeoutMs?: PlayRuntimeTimeoutMs;',
2620
2713
  ' readonly receiptWaitMs?: PlayReceiptWaitMs;',
2621
2714
  '};',
2622
- 'export type PlayBindings = {',
2715
+ 'export type PlayCronInput<TInput> = TInput extends readonly unknown[] ? never : TInput extends object ? TInput : never;',
2716
+ 'export type PlayBindings<TInput = Record<string, unknown>> = {',
2623
2717
  ` description?: ${cloudReferenceType('description')};`,
2624
2718
  ` compatibility?: { toolErrorSchemaVersion?: ${cloudReferenceType('compatibility.toolErrorSchemaVersion')}; toolResponseReceiptRevision?: ${cloudReferenceType('compatibility.toolResponseReceiptRevision')} };`,
2625
2719
  ` inline?: ${cloudReferenceType('inline')};`,
2626
2720
  ` billing?: { maxCreditsPerRun?: ${cloudReferenceType('billing.maxCreditsPerRun')} };`,
2627
2721
  ` runtime?: { timeout?: ${cloudReferenceType('runtime.timeout')}; size?: ${cloudReferenceType('runtime.size')} };`,
2628
2722
  ` webhook?: { hmac?: { algorithm?: ${cloudReferenceType('bindings.webhook.hmac.algorithm')}; header?: ${cloudReferenceType('bindings.webhook.hmac.header')}; secretEnv: ${cloudReferenceType('bindings.webhook.hmac.secretEnv')} }; auth?: { type: ${cloudReferenceType('bindings.webhook.auth.type')}; headerFamily: ${cloudReferenceType('bindings.webhook.auth.headerFamily')}; signingSecrets: readonly ${cloudReferenceType('bindings.webhook.auth.signingSecrets[]')}[]; toleranceSeconds?: ${cloudReferenceType('bindings.webhook.auth.toleranceSeconds')} } };`,
2629
- ` cron?: { schedule: ${cloudReferenceType('bindings.cron.schedule')}; timezone?: ${cloudReferenceType('bindings.cron.timezone')} };`,
2723
+ ` cron?: { schedule: ${cloudReferenceType('bindings.cron.schedule')}; timezone?: ${cloudReferenceType('bindings.cron.timezone')}; input?: PlayCronInput<TInput> };`,
2630
2724
  ' sqlListeners?: readonly SqlListenerDeclaration[];',
2631
2725
  ` secrets?: readonly ${cloudReferenceType('bindings.secrets[]')}[];`,
2632
2726
  '};',
@@ -2692,6 +2786,8 @@ export const PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
2692
2786
  ' log(message: string): void;',
2693
2787
  ` sleep(ms: ${cloudReferenceType('ctx.sleep.ms')}): Promise<void>;`,
2694
2788
  '}',
2695
- "export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = { id: string; description?: string; input: PlayInputContract<TInput>; run: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>; bindings?: PlayBindings; billing?: PlayBindings['billing']; runtime?: PlayBindings['runtime']; compatibility?: PlayBindings['compatibility'] };",
2696
- "export type DefinedPlay<TInput, TOutput extends PlayReturnObject> = ((ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>) & { readonly name: string; readonly __inputType?: TInput; readonly __outputType?: TOutput; readonly runtime?: PlayBindings['runtime']; readonly compatibility?: PlayBindings['compatibility'] };",
2789
+ "export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = { id: string; description?: string; input: PlayInputContract<TInput>; run: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>; bindings?: PlayBindings<TInput>; billing?: PlayBindings<TInput>['billing']; runtime?: PlayBindings<TInput>['runtime']; compatibility?: PlayBindings<TInput>['compatibility'] };",
2790
+ "export type DefinedPlay<TInput, TOutput extends PlayReturnObject> = ((ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>) & { readonly name: string; readonly __inputType?: TInput; readonly __outputType?: TOutput; readonly bindings?: PlayBindings<TInput>; readonly runtime?: PlayBindings<TInput>['runtime']; readonly compatibility?: PlayBindings<TInput>['compatibility'] };",
2791
+ 'export type PlayHandlerInput<THandler> = THandler extends (context: DeeplinePlayRuntimeContext, input: infer TInput) => Promise<PlayReturnObject> ? TInput : never;',
2792
+ 'export type PlayHandlerOutput<THandler> = THandler extends (context: DeeplinePlayRuntimeContext, input: unknown) => Promise<infer TOutput extends PlayReturnObject> ? TOutput : never;',
2697
2793
  ] as const;
@@ -41,7 +41,8 @@ import { createPlayInputContract } from './input-contract-definition';
41
41
 
42
42
  export type { ToolExecuteResult } from './tool-result-types';
43
43
 
44
- export type PlayBindings = PlayAuthoringBindings;
44
+ export type PlayBindings<TInput = Record<string, unknown>> =
45
+ PlayAuthoringBindings<TInput>;
45
46
  export type SqlListenerOperation = PlaySqlListenerOperation;
46
47
  export type SqlListenerFilterScalar = PlaySqlListenerFilterScalar;
47
48
  export type SqlListenerFilterOperator = PlaySqlListenerFilterOperator;
@@ -135,14 +136,14 @@ export type DefinePlayConfig<
135
136
  TOutput extends PlayReturnObject,
136
137
  > = PlayAuthoringDefineConfig<TInput, TOutput, DeeplinePlayRuntimeContext>;
137
138
 
138
- export type PlayMetadata = {
139
+ export type PlayMetadata<TInput = Record<string, unknown>> = {
139
140
  name: string;
140
141
  description?: string;
141
- bindings?: PlayBindings;
142
+ bindings?: PlayBindings<TInput>;
142
143
  inputSchema?: Record<string, unknown>;
143
- billing?: PlayBindings['billing'];
144
- runtime?: PlayBindings['runtime'];
145
- compatibility?: PlayBindings['compatibility'];
144
+ billing?: PlayBindings<TInput>['billing'];
145
+ runtime?: PlayBindings<TInput>['runtime'];
146
+ compatibility?: PlayBindings<TInput>['compatibility'];
146
147
  };
147
148
 
148
149
  export type CoreNamedPlayHandle<
@@ -170,6 +171,20 @@ export type DefinedPlay<
170
171
  THandle
171
172
  >;
172
173
 
174
+ type PlayHandlerInput<THandler> = THandler extends (
175
+ context: DeeplinePlayRuntimeContext,
176
+ input: infer TInput,
177
+ ) => Promise<PlayReturnObject>
178
+ ? TInput
179
+ : never;
180
+
181
+ type PlayHandlerOutput<THandler> = THandler extends (
182
+ context: DeeplinePlayRuntimeContext,
183
+ input: unknown,
184
+ ) => Promise<infer TOutput extends PlayReturnObject>
185
+ ? TOutput
186
+ : never;
187
+
173
188
  export const PLAY_METADATA_SYMBOL = Symbol.for('deepline.play.metadata');
174
189
 
175
190
  class PlayCoreConditionalStepResolver<
@@ -317,7 +332,7 @@ export function createDefinedPlay<
317
332
  maybeFn:
318
333
  | ((ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>)
319
334
  | undefined,
320
- maybeBindings: PlayBindings | undefined,
335
+ maybeBindings: PlayBindings<TInput> | undefined,
321
336
  createHandle: (name: string) => THandle,
322
337
  ): DefinedPlay<TInput, TOutput, THandle> {
323
338
  const config =
@@ -368,7 +383,7 @@ export function createDefinedPlay<
368
383
  );
369
384
  }
370
385
 
371
- const metadata: PlayMetadata = {
386
+ const metadata: PlayMetadata<TInput> = {
372
387
  name,
373
388
  ...(description ? { description } : {}),
374
389
  ...(config.bindings ? { bindings: config.bindings } : {}),
@@ -426,18 +441,36 @@ export function createDefinedPlay<
426
441
  export function definePlay<TInput, TOutput extends PlayReturnObject>(
427
442
  config: DefinePlayConfig<TInput, TOutput>,
428
443
  ): DefinedPlay<TInput, TOutput>;
429
- export function definePlay<TInput, TOutput extends PlayReturnObject>(
444
+ /** @internal Contextually type unannotated monitor-event handlers as unknown. */
445
+ export function definePlay<TOutput extends PlayReturnObject>(
430
446
  name: string,
431
- fn: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>,
432
- bindings?: PlayBindings,
433
- ): DefinedPlay<TInput, TOutput>;
447
+ fn: (
448
+ context: DeeplinePlayRuntimeContext,
449
+ input: unknown,
450
+ ) => Promise<TOutput>,
451
+ bindings: PlayBindings<never> & {
452
+ readonly sqlListeners: readonly SqlListenerDeclaration[];
453
+ },
454
+ ): DefinedPlay<unknown, TOutput>;
455
+ /* eslint-disable @typescript-eslint/no-explicit-any -- This constraint must infer a concrete contravariant handler input. */
456
+ export function definePlay<
457
+ THandler extends (
458
+ context: DeeplinePlayRuntimeContext,
459
+ input: any,
460
+ ) => Promise<PlayReturnObject>,
461
+ >(
462
+ name: string,
463
+ fn: THandler,
464
+ bindings?: PlayBindings<NoInfer<PlayHandlerInput<THandler>>>,
465
+ ): DefinedPlay<PlayHandlerInput<THandler>, PlayHandlerOutput<THandler>>;
466
+ /* eslint-enable @typescript-eslint/no-explicit-any */
434
467
  export function definePlay<TInput, TOutput extends PlayReturnObject>(
435
468
  nameOrConfig: string | DefinePlayConfig<TInput, TOutput>,
436
469
  maybeFn?: (
437
470
  ctx: DeeplinePlayRuntimeContext,
438
471
  input: TInput,
439
472
  ) => Promise<TOutput>,
440
- maybeBindings?: PlayBindings,
473
+ maybeBindings?: PlayBindings<TInput>,
441
474
  ): DefinedPlay<TInput, TOutput> {
442
475
  return createDefinedPlay(nameOrConfig, maybeFn, maybeBindings, (name) =>
443
476
  createUnavailableNamedPlayHandle<TInput, TOutput>(name),