deepline 0.3.257 → 0.3.259

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 (68) hide show
  1. package/dist/bundling-sources/sdk/src/api-error.ts +45 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +98 -459
  3. package/dist/bundling-sources/sdk/src/http.ts +1 -34
  4. package/dist/bundling-sources/sdk/src/index.ts +8 -0
  5. package/dist/bundling-sources/sdk/src/plays/csv-data-input.ts +139 -0
  6. package/dist/bundling-sources/sdk/src/plays/run-request.ts +855 -0
  7. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  8. package/dist/bundling-sources/sdk/src/runs/overview.ts +45 -2
  9. package/dist/bundling-sources/sdk/src/types.ts +5 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +8 -0
  11. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +42 -10
  12. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +3 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +23 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +3 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/play-admission-outcome.ts +23 -5
  16. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +1 -1
  17. package/dist/bundling-sources/shared_libs/play-runtime/run-execution-state.ts +845 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +106 -6
  19. package/dist/bundling-sources/shared_libs/play-runtime/run-observation.ts +440 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +35 -2
  21. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +66 -7
  22. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +0 -29
  23. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -2
  24. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +6 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +475 -36
  26. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +78 -11
  27. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +550 -42
  28. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +181 -8
  29. package/dist/bundling-sources/shared_libs/play-runtime/step-lifecycle-tracker.ts +0 -18
  30. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +80 -7
  31. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +37 -2
  32. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +148 -18
  33. package/dist/bundling-sources/shared_libs/plays/cascade-falloff.ts +86 -0
  34. package/dist/bundling-sources/shared_libs/plays/docflow-unreached-reason.ts +611 -0
  35. package/dist/bundling-sources/shared_libs/plays/docflow.ts +21 -0
  36. package/dist/bundling-sources/shared_libs/plays/play-exports.ts +28 -5
  37. package/dist/bundling-sources/shared_libs/plays/play-grep-search.ts +40 -2
  38. package/dist/bundling-sources/shared_libs/plays/settings-contract.ts +92 -10
  39. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +5 -0
  40. package/dist/bundling-sources/shared_libs/plays/trigger-config-contract.ts +222 -0
  41. package/dist/bundling-sources/shared_libs/plays/trigger-config-route.ts +15 -0
  42. package/dist/cli/index.js +4957 -771
  43. package/dist/cli/index.mjs +4957 -771
  44. package/dist/client-B5XbKrrs.d.mts +6564 -0
  45. package/dist/client-C9Y49yya.d.ts +6564 -0
  46. package/dist/{compiler-manifest-C4mdRJOP.d.mts → compiler-manifest-CUuh8C3b.d.mts} +14 -1
  47. package/dist/{compiler-manifest-C4mdRJOP.d.ts → compiler-manifest-CUuh8C3b.d.ts} +14 -1
  48. package/dist/index.d.mts +7 -6275
  49. package/dist/index.d.ts +7 -6275
  50. package/dist/index.js +360 -326
  51. package/dist/index.mjs +360 -326
  52. package/dist/install-integrity.json +21 -2
  53. package/dist/plays/bundle-play-file.d.mts +2 -2
  54. package/dist/plays/bundle-play-file.d.ts +2 -2
  55. package/dist/plays/bundle-play-file.mjs +117 -18
  56. package/dist/plays/csv-data-input.d.mts +37 -0
  57. package/dist/plays/csv-data-input.d.ts +37 -0
  58. package/dist/plays/csv-data-input.js +3135 -0
  59. package/dist/plays/csv-data-input.mjs +3108 -0
  60. package/dist/plays/run-request.d.mts +6 -0
  61. package/dist/plays/run-request.d.ts +6 -0
  62. package/dist/plays/run-request.js +664 -0
  63. package/dist/plays/run-request.mjs +614 -0
  64. package/dist/release.d.mts +1 -1
  65. package/dist/release.d.ts +1 -1
  66. package/dist/release.js +1 -1
  67. package/dist/release.mjs +1 -1
  68. package/package.json +12 -1
@@ -5,6 +5,7 @@ export const CONVEX_PLAY_GREP_SEARCH_TERM_MAX_BYTES = 31;
5
5
  export const CONVEX_PLAY_GREP_SEARCH_MAX_TERMS = 16;
6
6
 
7
7
  const CONVEX_PLAY_GREP_SEARCH_TERM_PATTERN = /[\p{L}\p{N}]+/gu;
8
+ const CONVEX_PLAY_GREP_SEARCH_ENCODER = new TextEncoder();
8
9
 
9
10
  export type PlayGrepMatch = {
10
11
  field: 'name' | 'description' | 'provider' | 'source';
@@ -31,12 +32,49 @@ export function countNormalizedPlayGrepSearchTerms(value: string): number {
31
32
  return extractPlayGrepSearchTerms(normalizePlayGrepSearchQuery(value)).length;
32
33
  }
33
34
 
35
+ /**
36
+ * Match the canonical indexed grep corpus without relying on relevance-ranked
37
+ * search pagination. Native grep unions complete token matches; only the final
38
+ * query term also matches the start of a corpus token.
39
+ */
40
+ export function playGrepSearchTextMatches(
41
+ query: string,
42
+ searchText: string | null | undefined,
43
+ ): boolean {
44
+ const queryTerms = extractPlayGrepSearchTerms(
45
+ normalizePlayGrepSearchQuery(query),
46
+ );
47
+ if (queryTerms.length === 0 || typeof searchText !== 'string') return false;
48
+
49
+ const corpusTerms = new Set(
50
+ extractPlayGrepSearchTerms(normalizePlayGrepSearchQuery(searchText)).filter(
51
+ (term) =>
52
+ CONVEX_PLAY_GREP_SEARCH_ENCODER.encode(term).byteLength <=
53
+ CONVEX_PLAY_GREP_SEARCH_TERM_MAX_BYTES,
54
+ ),
55
+ );
56
+ const finalQueryTerm = queryTerms[queryTerms.length - 1]!;
57
+ let finalPrefixMatches = false;
58
+ for (const corpusTerm of corpusTerms) {
59
+ if (corpusTerm.startsWith(finalQueryTerm)) {
60
+ finalPrefixMatches = true;
61
+ break;
62
+ }
63
+ }
64
+ return queryTerms.some((term, index) => {
65
+ if (index === queryTerms.length - 1) {
66
+ return finalPrefixMatches;
67
+ }
68
+ return corpusTerms.has(term);
69
+ });
70
+ }
71
+
34
72
  /** True when a query term exceeds Convex's usable full-text-search limit. */
35
73
  export function hasOverlongPlayGrepSearchTerm(value: string): boolean {
36
- const encoder = new TextEncoder();
37
74
  return extractPlayGrepSearchTerms(normalizePlayGrepSearchQuery(value)).some(
38
75
  (term) =>
39
- encoder.encode(term).byteLength > CONVEX_PLAY_GREP_SEARCH_TERM_MAX_BYTES,
76
+ CONVEX_PLAY_GREP_SEARCH_ENCODER.encode(term).byteLength >
77
+ CONVEX_PLAY_GREP_SEARCH_TERM_MAX_BYTES,
40
78
  );
41
79
  }
42
80
 
@@ -119,16 +119,18 @@ export const PLAY_SETTING_FIELDS = {
119
119
  ui: { control: 'play-location-picker' as const },
120
120
  },
121
121
  } as const;
122
- export const playSettingsSchema = z.object(
123
- Object.fromEntries(
124
- Object.entries(PLAY_SETTING_FIELDS).map(([key, field]) => [
125
- key,
126
- field.schema,
127
- ]),
128
- ) as {
129
- [K in keyof typeof PLAY_SETTING_FIELDS]: (typeof PLAY_SETTING_FIELDS)[K]['schema'];
130
- },
131
- ).passthrough();
122
+ export const playSettingsSchema = z
123
+ .object(
124
+ Object.fromEntries(
125
+ Object.entries(PLAY_SETTING_FIELDS).map(([key, field]) => [
126
+ key,
127
+ field.schema,
128
+ ]),
129
+ ) as {
130
+ [K in keyof typeof PLAY_SETTING_FIELDS]: (typeof PLAY_SETTING_FIELDS)[K]['schema'];
131
+ },
132
+ )
133
+ .passthrough();
132
134
  export const playSettingsPatchSchema = z
133
135
  .object(
134
136
  Object.fromEntries(
@@ -174,3 +176,83 @@ export type PlaySettingsPathsPage = {
174
176
  cursor: string | null;
175
177
  hasMore: boolean;
176
178
  };
179
+
180
+ /** A folder inside one location root. `ownerUserId` scopes personal roots. */
181
+ export type PlayFolderLocation = {
182
+ root: 'person' | 'team';
183
+ ownerUserId?: string | null;
184
+ folders: readonly string[];
185
+ };
186
+ export type PlayFolderMove = {
187
+ playName: string;
188
+ from: PlayPath;
189
+ path: PlayPath;
190
+ };
191
+
192
+ function sameFolderRoot(
193
+ left: PlayFolderLocation,
194
+ right: PlayFolderLocation,
195
+ ): boolean {
196
+ return (
197
+ left.root === right.root &&
198
+ (left.root === 'team' ||
199
+ (left.ownerUserId ?? null) === (right.ownerUserId ?? null))
200
+ );
201
+ }
202
+
203
+ function startsWithFolders(
204
+ folders: readonly string[],
205
+ prefix: readonly string[],
206
+ ): boolean {
207
+ return (
208
+ folders.length >= prefix.length &&
209
+ prefix.every((segment, index) => folders[index] === segment)
210
+ );
211
+ }
212
+
213
+ /**
214
+ * Folders exist only as Play locations, so moving or renaming a folder moves
215
+ * every Play below it: `from.folders` is replaced by `to.folders` and the rest
216
+ * of each path is kept. The dashboard and `deepline plays settings
217
+ * move-folder` both apply this plan through the per-Play settings API, so a
218
+ * retried or interrupted move converges on the same paths.
219
+ */
220
+ export function planPlayFolderMove(
221
+ paths: PlaySettingsPathsPage['paths'],
222
+ from: PlayFolderLocation,
223
+ to: PlayFolderLocation,
224
+ ): PlayFolderMove[] {
225
+ if (from.folders.length === 0)
226
+ throw new Error('Choose a folder to move; a root cannot be moved.');
227
+ if (sameFolderRoot(from, to) && startsWithFolders(to.folders, from.folders))
228
+ throw new Error('A folder cannot be moved into itself.');
229
+ const moves: PlayFolderMove[] = [];
230
+ for (const entry of paths) {
231
+ const location: PlayFolderLocation = {
232
+ root: entry.path?.root ?? 'person',
233
+ ownerUserId: entry.ownerUserId,
234
+ folders: entry.path?.folders ?? [],
235
+ };
236
+ if (!sameFolderRoot(location, from)) continue;
237
+ if (!startsWithFolders(location.folders, from.folders)) continue;
238
+ if (
239
+ to.root === 'person' &&
240
+ (entry.ownerUserId ?? null) !== (to.ownerUserId ?? null)
241
+ )
242
+ throw new Error(
243
+ `${entry.playName} belongs to another person, so it cannot move into this personal root. Move the folder to team instead.`,
244
+ );
245
+ moves.push({
246
+ playName: entry.playName,
247
+ from: entry.path,
248
+ path: playPathSchema.parse({
249
+ root: to.root,
250
+ folders: [
251
+ ...to.folders,
252
+ ...location.folders.slice(from.folders.length),
253
+ ],
254
+ }),
255
+ });
256
+ }
257
+ return moves;
258
+ }
@@ -390,11 +390,13 @@ function truncateStaticSubstepsForStorage(
390
390
  return (substeps ?? []).map((substep) => {
391
391
  const {
392
392
  paramsSource: _paramsSource,
393
+ inputPrelude: _inputPrelude,
393
394
  returnSource: _returnSource,
394
395
  sourceText: _sourceText,
395
396
  ...substepWithoutSourceText
396
397
  } = substep as PlayStaticSubstep & {
397
398
  paramsSource?: string;
399
+ inputPrelude?: string;
398
400
  pipeline?: PlayStaticPipeline | null;
399
401
  returnSource?: string;
400
402
  sourceText?: string;
@@ -1308,6 +1310,9 @@ export type PlayStaticSubstep = PlayStaticSubstepMetadata &
1308
1310
  toolId: string;
1309
1311
  field: string;
1310
1312
  paramsSource?: string;
1313
+ /** The code computing the call's local inputs (`const candidate =
1314
+ * …`), when its inputs are locals of the calling function. */
1315
+ inputPrelude?: string;
1311
1316
  sourceText?: string;
1312
1317
  description?: string;
1313
1318
  inLoop?: boolean;
@@ -0,0 +1,222 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Trigger configuration contract shared by the API route, the SDK/CLI, and the
5
+ * Play canvas. A Play's cron and webhook triggers are SOURCE declarations
6
+ * (`definePlay(..., { cron, webhook })`). A configuration change rewrites that
7
+ * declaration in the live revision's source and publishes the result as a new
8
+ * revision, so the source, the revision's stored bindings, and the scheduler
9
+ * bindings never disagree.
10
+ *
11
+ * The update is declarative: `cron`/`webhook` name the desired declaration,
12
+ * `null` removes it, and an omitted key leaves it unchanged. Repeating the same
13
+ * request after a lost response is a no-op, because the live revision already
14
+ * declares the requested state.
15
+ */
16
+
17
+ const SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]{1,63}$/;
18
+ const secretName = z
19
+ .string()
20
+ .regex(
21
+ SECRET_NAME_PATTERN,
22
+ 'Secret names are uppercase letters, digits, and underscores, starting with a letter.',
23
+ );
24
+
25
+ export const PLAY_TRIGGER_TOLERANCE_SECONDS_MAX = 3600;
26
+
27
+ export const playCronTriggerConfigSchema = z
28
+ .object({
29
+ schedule: z
30
+ .string()
31
+ .trim()
32
+ .min(1, 'Schedule is required.')
33
+ .max(256)
34
+ .describe('Standard 5-field cron expression, e.g. "0 9 * * 1-5".'),
35
+ timezone: z
36
+ .string()
37
+ .trim()
38
+ .min(1)
39
+ .max(64)
40
+ .optional()
41
+ .describe('IANA timezone. Omitted means UTC.'),
42
+ input: z
43
+ .record(z.string(), z.unknown())
44
+ .optional()
45
+ .describe('Static JSON object passed as the input of every cron run.'),
46
+ })
47
+ .strict();
48
+ export type PlayCronTriggerConfig = z.output<
49
+ typeof playCronTriggerConfigSchema
50
+ >;
51
+
52
+ export const playWebhookAuthConfigSchema = z.discriminatedUnion('type', [
53
+ z
54
+ .object({
55
+ type: z.literal('standard-webhooks'),
56
+ headerFamily: z.enum(['standard', 'svix']),
57
+ signingSecrets: z.array(secretName).min(1).max(4),
58
+ toleranceSeconds: z
59
+ .number()
60
+ .int()
61
+ .min(1)
62
+ .max(PLAY_TRIGGER_TOLERANCE_SECONDS_MAX)
63
+ .optional(),
64
+ })
65
+ .strict(),
66
+ z
67
+ .object({
68
+ type: z.literal('hmac'),
69
+ secretEnv: secretName,
70
+ header: z.string().trim().min(1).max(128).optional(),
71
+ signaturePrefix: z.string().max(64).optional(),
72
+ })
73
+ .strict(),
74
+ ]);
75
+ export type PlayWebhookAuthConfig = z.output<
76
+ typeof playWebhookAuthConfigSchema
77
+ >;
78
+
79
+ export const playWebhookTriggerConfigSchema = z
80
+ .object({
81
+ /** Omitted or null: an unsigned webhook. */
82
+ auth: playWebhookAuthConfigSchema.nullable().optional(),
83
+ })
84
+ .strict();
85
+ export type PlayWebhookTriggerConfig = z.output<
86
+ typeof playWebhookTriggerConfigSchema
87
+ >;
88
+
89
+ export const playTriggerConfigUpdateSchema = z
90
+ .object({
91
+ /**
92
+ * Optimistic concurrency guard. When present, the update is refused with
93
+ * 409 if the live revision is no longer this one.
94
+ */
95
+ expectedRevisionId: z.string().trim().min(1).optional(),
96
+ cron: playCronTriggerConfigSchema.nullable().optional(),
97
+ webhook: playWebhookTriggerConfigSchema.nullable().optional(),
98
+ })
99
+ .strict()
100
+ .refine(
101
+ (update) => update.cron !== undefined || update.webhook !== undefined,
102
+ {
103
+ message: 'Provide cron and/or webhook. Use null to remove a trigger.',
104
+ },
105
+ );
106
+ export type PlayTriggerConfigUpdate = z.output<
107
+ typeof playTriggerConfigUpdateSchema
108
+ >;
109
+
110
+ export type PlayTriggerConfigCronState = {
111
+ bindingId: string | null;
112
+ schedule: string;
113
+ timezone: string | null;
114
+ input: Record<string, unknown> | null;
115
+ /** Scheduler binding status: active, inactive (credit hold), or blocked. */
116
+ status: string | null;
117
+ nextScheduledAt: number | null;
118
+ lastScheduledAt: number | null;
119
+ blockedReasonCode: string | null;
120
+ blockedReason: string | null;
121
+ };
122
+
123
+ export type PlayTriggerConfigWebhookState = {
124
+ bindingId: string | null;
125
+ url: string | null;
126
+ status: string | null;
127
+ auth: PlayWebhookAuthConfig | null;
128
+ };
129
+
130
+ export type PlayTriggerConfigReadOnlyReason =
131
+ | 'not_published'
132
+ | 'git_managed'
133
+ | 'archived';
134
+
135
+ export type PlayTriggerConfigView = {
136
+ name: string;
137
+ playDefinitionId: string;
138
+ liveRevisionId: string | null;
139
+ liveVersion: number | null;
140
+ /** Null when the triggers can be changed here; otherwise why not. */
141
+ readOnly: { reason: PlayTriggerConfigReadOnlyReason; message: string } | null;
142
+ cron: PlayTriggerConfigCronState | null;
143
+ webhook: PlayTriggerConfigWebhookState | null;
144
+ };
145
+
146
+ export type PlayTriggerConfigUpdateResult = {
147
+ /** False when the live revision already declared the requested triggers. */
148
+ changed: boolean;
149
+ /** Newly published revision, when `changed`. */
150
+ revisionId: string | null;
151
+ version: number | null;
152
+ triggers: PlayTriggerConfigView;
153
+ };
154
+
155
+ export function formatPlayTriggerConfigError(error: unknown): string {
156
+ if (error instanceof z.ZodError)
157
+ return [...new Set(error.issues.map((issue) => issue.message))].join(' ');
158
+ return error instanceof Error ? error.message : String(error);
159
+ }
160
+
161
+ /*
162
+ * One request for every surface. The dashboard, the SDK client, and the CLI
163
+ * all turn a user's intent into the request below with these functions and
164
+ * send it to the same route; none of them assembles the body itself.
165
+ */
166
+
167
+ export {
168
+ PLAY_TRIGGER_CONFIG_UPDATE_METHOD,
169
+ playTriggerConfigPath,
170
+ } from './trigger-config-route';
171
+
172
+ /** Schedule (cron) intent: off, or on with its expression, zone and input. */
173
+ export type PlayScheduleIntent =
174
+ | { enabled: false }
175
+ | {
176
+ enabled: true;
177
+ schedule: string;
178
+ /** Omitted or null: UTC, left unnamed in source. */
179
+ timezone?: string | null;
180
+ /** Omitted, null, or empty: no static input. */
181
+ input?: Record<string, unknown> | null;
182
+ };
183
+
184
+ /** Webhook intent: off, or on with its authentication (null = unsigned). */
185
+ export type PlayWebhookIntent =
186
+ | { enabled: false }
187
+ | { enabled: true; auth: PlayWebhookAuthConfig | null };
188
+
189
+ /**
190
+ * The one request builder. Validates against the same schema the route
191
+ * parses with, so a surface cannot build a request the server would read
192
+ * differently. Throws a ZodError on an invalid intent.
193
+ */
194
+ export function buildPlayTriggerConfigUpdate(intent: {
195
+ schedule?: PlayScheduleIntent;
196
+ webhook?: PlayWebhookIntent;
197
+ expectedRevisionId?: string | null;
198
+ }): PlayTriggerConfigUpdate {
199
+ const schedule = intent.schedule;
200
+ const webhook = intent.webhook;
201
+ return playTriggerConfigUpdateSchema.parse({
202
+ ...(intent.expectedRevisionId
203
+ ? { expectedRevisionId: intent.expectedRevisionId }
204
+ : {}),
205
+ ...(schedule === undefined
206
+ ? {}
207
+ : {
208
+ cron: schedule.enabled
209
+ ? {
210
+ schedule: schedule.schedule,
211
+ ...(schedule.timezone ? { timezone: schedule.timezone } : {}),
212
+ ...(schedule.input && Object.keys(schedule.input).length > 0
213
+ ? { input: schedule.input }
214
+ : {}),
215
+ }
216
+ : null,
217
+ }),
218
+ ...(webhook === undefined
219
+ ? {}
220
+ : { webhook: webhook.enabled ? { auth: webhook.auth } : null }),
221
+ });
222
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The trigger-config route, kept free of `zod` and every other dependency.
3
+ *
4
+ * The SDK client calls it at runtime, and the SDK client is bundled into
5
+ * authored Plays by the deployed play bundler, which resolves only the traced
6
+ * workspace sources — not their npm dependencies. Importing the schema module
7
+ * (`trigger-config-contract.ts`) from the client for this one path would pull
8
+ * `zod` into every Play bundle and fail it ("Could not resolve \"zod\"").
9
+ */
10
+
11
+ export const PLAY_TRIGGER_CONFIG_UPDATE_METHOD = 'PUT' as const;
12
+
13
+ export function playTriggerConfigPath(playName: string): string {
14
+ return `/api/v2/plays/${encodeURIComponent(playName)}/triggers`;
15
+ }