deepline 0.1.83 → 0.1.85
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.
- package/dist/cli/index.js +64 -11
- package/dist/cli/index.mjs +64 -11
- package/dist/index.d.mts +230 -10
- package/dist/index.d.ts +230 -10
- package/dist/index.js +115 -2
- package/dist/index.mjs +110 -2
- package/dist/repo/apps/play-runner-workers/src/entry.ts +123 -26
- package/dist/repo/sdk/src/index.ts +11 -0
- package/dist/repo/sdk/src/play.ts +61 -5
- package/dist/repo/sdk/src/plays/harness-stub.ts +2 -1
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/sdk/src/types.ts +4 -0
- package/dist/repo/shared_libs/play-runtime/cell-staleness.ts +156 -7
- package/dist/repo/shared_libs/play-runtime/execution-plan.ts +3 -3
- package/dist/repo/shared_libs/play-runtime/extractor-targets.ts +106 -0
- package/dist/repo/shared_libs/play-runtime/providers.ts +28 -0
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +11 -0
- package/dist/repo/shared_libs/play-runtime/step-program-dataset-builder.ts +96 -6
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +82 -0
- package/dist/repo/shared_libs/plays/static-pipeline.ts +133 -24
- package/package.json +1 -1
|
@@ -81,6 +81,10 @@ import type {
|
|
|
81
81
|
ToolExecuteResult,
|
|
82
82
|
ToolResultMetadataInput,
|
|
83
83
|
} from '../../shared_libs/play-runtime/tool-result-types.js';
|
|
84
|
+
import type {
|
|
85
|
+
AuthoredStaleAfterSeconds,
|
|
86
|
+
PreviousCell,
|
|
87
|
+
} from '../../shared_libs/play-runtime/cell-staleness.js';
|
|
84
88
|
import type {
|
|
85
89
|
DeeplineClientOptions,
|
|
86
90
|
PlayDetail,
|
|
@@ -187,6 +191,22 @@ export type {
|
|
|
187
191
|
ToolResultListAccessor,
|
|
188
192
|
ToolResultTargetAccessor as ToolExtractedValue,
|
|
189
193
|
} from '../../shared_libs/play-runtime/tool-result-types.js';
|
|
194
|
+
export {
|
|
195
|
+
DEEPLINE_EXTRACTOR_TARGETS,
|
|
196
|
+
DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS,
|
|
197
|
+
JOB_CHANGE_STATUS_VALUES,
|
|
198
|
+
PHONE_STATUS_VALUES,
|
|
199
|
+
isDeeplineExtractorTarget,
|
|
200
|
+
} from '../../shared_libs/play-runtime/extractor-targets.js';
|
|
201
|
+
export type {
|
|
202
|
+
DeeplineEmailStatusGetterValue,
|
|
203
|
+
DeeplineExtractorTarget,
|
|
204
|
+
DeeplineGetterValue,
|
|
205
|
+
DeeplineGetterValueMap,
|
|
206
|
+
JobChangeStatus,
|
|
207
|
+
PhoneStatus,
|
|
208
|
+
} from '../../shared_libs/play-runtime/extractor-targets.js';
|
|
209
|
+
export type { PreviousCell } from '../../shared_libs/play-runtime/cell-staleness.js';
|
|
190
210
|
|
|
191
211
|
/**
|
|
192
212
|
* Keyword-style request object for `ctx.tools.execute(...)`.
|
|
@@ -206,12 +226,35 @@ export type ToolExecutionRequest = {
|
|
|
206
226
|
staleAfterSeconds?: number;
|
|
207
227
|
};
|
|
208
228
|
|
|
229
|
+
export type StaleAfterSeconds<Value = unknown> =
|
|
230
|
+
AuthoredStaleAfterSeconds<Value>;
|
|
231
|
+
|
|
209
232
|
export type StepResolver<Row, Value> = (
|
|
210
233
|
row: Row,
|
|
211
234
|
ctx: DeeplinePlayRuntimeContext,
|
|
212
235
|
index: number,
|
|
236
|
+
previousCell?: PreviousCell<Value>,
|
|
213
237
|
) => Value | Promise<Value>;
|
|
214
238
|
|
|
239
|
+
export type DatasetColumnRunInput<Row, Value> = {
|
|
240
|
+
row: Row;
|
|
241
|
+
ctx: DeeplinePlayRuntimeContext;
|
|
242
|
+
index: number;
|
|
243
|
+
/**
|
|
244
|
+
* The prior stored value for this exact row+column when the runtime has
|
|
245
|
+
* decided the cell is due to run again. `previousCell.value` is the same type
|
|
246
|
+
* this column returns; metadata such as `completedAt` and `staleAt` lives
|
|
247
|
+
* beside it and is not mixed into the value.
|
|
248
|
+
*/
|
|
249
|
+
previousCell?: PreviousCell<Value>;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export type DatasetColumnDefinition<Row, Value> = {
|
|
253
|
+
run: (input: DatasetColumnRunInput<Row, Value>) => Value | Promise<Value>;
|
|
254
|
+
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
255
|
+
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
256
|
+
};
|
|
257
|
+
|
|
215
258
|
export type ConditionalStepResolver<Row, Value, Else = null> = {
|
|
216
259
|
readonly kind: 'conditional';
|
|
217
260
|
readonly when: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
@@ -222,9 +265,9 @@ export type ConditionalStepResolver<Row, Value, Else = null> = {
|
|
|
222
265
|
): ConditionalStepResolver<Row, Value, ValueElse>;
|
|
223
266
|
};
|
|
224
267
|
|
|
225
|
-
export type StepOptions<Row> = {
|
|
268
|
+
export type StepOptions<Row, Value = unknown> = {
|
|
226
269
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
227
|
-
readonly staleAfterSeconds?:
|
|
270
|
+
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
228
271
|
};
|
|
229
272
|
|
|
230
273
|
export type StepProgram<Input, Output, Return = Output> = {
|
|
@@ -242,7 +285,7 @@ export type StepProgram<Input, Output, Return = Output> = {
|
|
|
242
285
|
step<Name extends string, Value>(
|
|
243
286
|
name: Name,
|
|
244
287
|
resolver: StepResolver<Output, Value> | StepProgramResolver<Output, Value>,
|
|
245
|
-
options: StepOptions<Output>,
|
|
288
|
+
options: StepOptions<Output, Value>,
|
|
246
289
|
): StepProgram<Input, Output & Record<Name, Value | null>, Return>;
|
|
247
290
|
return<Value>(
|
|
248
291
|
resolver: StepResolver<Output, Value>,
|
|
@@ -258,7 +301,7 @@ export type StepProgramResolver<Input, Return> = {
|
|
|
258
301
|
|
|
259
302
|
export type PlayStepProgramStep = {
|
|
260
303
|
readonly name: string;
|
|
261
|
-
readonly staleAfterSeconds?:
|
|
304
|
+
readonly staleAfterSeconds?: StaleAfterSeconds;
|
|
262
305
|
readonly resolver:
|
|
263
306
|
| StepResolver<Record<string, unknown>, unknown>
|
|
264
307
|
| ConditionalStepResolver<Record<string, unknown>, unknown>
|
|
@@ -294,12 +337,25 @@ export type DatasetBuilder<
|
|
|
294
337
|
name: Name,
|
|
295
338
|
resolver: ColumnResolver<OutputRow, Value>,
|
|
296
339
|
): DatasetBuilder<InputRow, OutputRow & Record<Name, Value>>;
|
|
340
|
+
withColumn<Name extends string, Value>(
|
|
341
|
+
name: Name,
|
|
342
|
+
definition: DatasetColumnDefinition<OutputRow, Value> & {
|
|
343
|
+
readonly runIf: (
|
|
344
|
+
row: OutputRow,
|
|
345
|
+
index: number,
|
|
346
|
+
) => boolean | Promise<boolean>;
|
|
347
|
+
},
|
|
348
|
+
): DatasetBuilder<InputRow, OutputRow & Record<Name, Value | null>>;
|
|
349
|
+
withColumn<Name extends string, Value>(
|
|
350
|
+
name: Name,
|
|
351
|
+
definition: DatasetColumnDefinition<OutputRow, Value>,
|
|
352
|
+
): DatasetBuilder<InputRow, OutputRow & Record<Name, Value>>;
|
|
297
353
|
withColumn<Name extends string, Value>(
|
|
298
354
|
name: Name,
|
|
299
355
|
resolver:
|
|
300
356
|
| StepResolver<OutputRow, Value>
|
|
301
357
|
| StepProgramResolver<OutputRow, Value>,
|
|
302
|
-
options: StepOptions<OutputRow>,
|
|
358
|
+
options: StepOptions<OutputRow, Value>,
|
|
303
359
|
): DatasetBuilder<InputRow, OutputRow & Record<Name, Value | null>>;
|
|
304
360
|
withColumns<Program extends StepProgram<OutputRow, object, unknown>>(
|
|
305
361
|
program: Program,
|
|
@@ -46,6 +46,7 @@ import type {
|
|
|
46
46
|
WorkReceipt,
|
|
47
47
|
WorkReceiptClaim,
|
|
48
48
|
} from '../../../shared_libs/play-runtime/work-receipts';
|
|
49
|
+
import type { CellStalenessPolicy } from '../../../shared_libs/play-runtime/cell-staleness';
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Service-binding RPC stub shape — what `env.HARNESS` looks like inside
|
|
@@ -191,7 +192,7 @@ export async function harnessStartSheetDataset(input: {
|
|
|
191
192
|
runId: string;
|
|
192
193
|
inputOffset?: number;
|
|
193
194
|
userEmail?: string | null;
|
|
194
|
-
cellPolicies?: Record<string,
|
|
195
|
+
cellPolicies?: Record<string, CellStalenessPolicy>;
|
|
195
196
|
}): Promise<{
|
|
196
197
|
inserted: number;
|
|
197
198
|
skipped: number;
|
|
@@ -50,10 +50,10 @@ export type SdkRelease = {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export const SDK_RELEASE = {
|
|
53
|
-
version: '0.1.
|
|
53
|
+
version: '0.1.85',
|
|
54
54
|
apiContract: '2026-06-dataset-column-cell-stale-hard-cutover',
|
|
55
55
|
supportPolicy: {
|
|
56
|
-
latest: '0.1.
|
|
56
|
+
latest: '0.1.85',
|
|
57
57
|
minimumSupported: '0.1.53',
|
|
58
58
|
deprecatedBelow: '0.1.53',
|
|
59
59
|
},
|
|
@@ -505,6 +505,10 @@ export interface PlayRunListItem {
|
|
|
505
505
|
closeTime: string | null;
|
|
506
506
|
/** Duration string (e.g. `'2.5s'`). */
|
|
507
507
|
executionTime: string | null;
|
|
508
|
+
/** Total Deepline credits charged for the run, when available. */
|
|
509
|
+
billingTotalCredits?: number;
|
|
510
|
+
/** Configured per-run Deepline credit cap, when available. */
|
|
511
|
+
billingMaxCreditsPerRun?: number | null;
|
|
508
512
|
/** Metadata attached to the workflow. */
|
|
509
513
|
memo: {
|
|
510
514
|
/** Organization that owns this run. */
|
|
@@ -1,17 +1,43 @@
|
|
|
1
|
+
export type StaleAfterSecondsResolver<Value = unknown> = (
|
|
2
|
+
value: Value,
|
|
3
|
+
) => number | null;
|
|
4
|
+
|
|
5
|
+
export type AuthoredStaleAfterSeconds<Value = unknown> =
|
|
6
|
+
| number
|
|
7
|
+
| StaleAfterSecondsResolver<Value>;
|
|
8
|
+
|
|
9
|
+
export type AuthoredCellStalenessPolicy<Value = unknown> = {
|
|
10
|
+
staleAfterSeconds?: AuthoredStaleAfterSeconds<Value>;
|
|
11
|
+
};
|
|
12
|
+
|
|
1
13
|
export type CellStalenessPolicy = {
|
|
2
14
|
staleAfterSeconds?: number;
|
|
15
|
+
dynamicStaleAfterSeconds?: boolean;
|
|
3
16
|
};
|
|
4
17
|
|
|
5
18
|
export type CellStalenessMeta = {
|
|
6
19
|
status?: string | null;
|
|
7
20
|
completedAt?: number | null;
|
|
21
|
+
staleAt?: number | null;
|
|
22
|
+
staleAfterSeconds?: number | null;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type PreviousCell<Value = unknown> = {
|
|
26
|
+
value: Value;
|
|
27
|
+
completedAt?: number;
|
|
28
|
+
staleAt?: number | null;
|
|
29
|
+
staleAfterSeconds?: number;
|
|
8
30
|
};
|
|
9
31
|
|
|
10
32
|
export type CellStalenessDecision =
|
|
11
33
|
| { action: 'recompute'; reason: 'missing' | 'failed' | 'stale' }
|
|
12
|
-
| { action: 'reuse'; reason: 'fresh' | 'no_policy' };
|
|
34
|
+
| { action: 'reuse'; reason: 'fresh' | 'no_policy' | 'no_expiry' };
|
|
13
35
|
|
|
14
36
|
export type CellStalenessPolicyByField = Record<string, CellStalenessPolicy>;
|
|
37
|
+
export type AuthoredCellStalenessPolicyByField = Record<
|
|
38
|
+
string,
|
|
39
|
+
AuthoredCellStalenessPolicy
|
|
40
|
+
>;
|
|
15
41
|
|
|
16
42
|
export const DEEPLINE_CELL_META_FIELD = '__deeplineCellMeta';
|
|
17
43
|
|
|
@@ -32,12 +58,83 @@ export function validateStaleAfterSeconds(
|
|
|
32
58
|
}
|
|
33
59
|
|
|
34
60
|
export function normalizeCellStalenessPolicy(
|
|
35
|
-
policy:
|
|
61
|
+
policy: AuthoredCellStalenessPolicy | undefined,
|
|
36
62
|
): CellStalenessPolicy {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
63
|
+
const staleAfterSeconds = policy?.staleAfterSeconds;
|
|
64
|
+
if (staleAfterSeconds === undefined) {
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
if (typeof staleAfterSeconds === 'function') {
|
|
68
|
+
return { dynamicStaleAfterSeconds: true };
|
|
69
|
+
}
|
|
70
|
+
validateStaleAfterSeconds(staleAfterSeconds);
|
|
71
|
+
return { staleAfterSeconds };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function resolveCompletedCellStalenessMeta<Value>(input: {
|
|
75
|
+
policy?: AuthoredCellStalenessPolicy<Value>;
|
|
76
|
+
value: Value;
|
|
77
|
+
completedAt: number;
|
|
78
|
+
}): Pick<CellStalenessMeta, 'staleAfterSeconds' | 'staleAt'> {
|
|
79
|
+
const staleAfterSeconds = input.policy?.staleAfterSeconds;
|
|
80
|
+
if (staleAfterSeconds === undefined) {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const resolved =
|
|
85
|
+
typeof staleAfterSeconds === 'function'
|
|
86
|
+
? staleAfterSeconds(input.value)
|
|
87
|
+
: staleAfterSeconds;
|
|
88
|
+
if (resolved === null) {
|
|
89
|
+
return { staleAt: null };
|
|
90
|
+
}
|
|
91
|
+
if (typeof resolved !== 'number') {
|
|
92
|
+
throw new Error(
|
|
93
|
+
'staleAfterSeconds(value) must return a positive whole number of seconds or null.',
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
validateStaleAfterSeconds(resolved, 'staleAfterSeconds(value)');
|
|
97
|
+
return {
|
|
98
|
+
staleAfterSeconds: resolved,
|
|
99
|
+
staleAt: input.completedAt + resolved * 1000,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function previousCellFromValue<Value>(input: {
|
|
104
|
+
hasValue: boolean;
|
|
105
|
+
value: Value;
|
|
106
|
+
meta?: CellStalenessMeta | null;
|
|
107
|
+
}): PreviousCell<Value> | undefined {
|
|
108
|
+
if (!input.hasValue) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const previous: PreviousCell<Value> = {
|
|
113
|
+
value: input.value,
|
|
114
|
+
};
|
|
115
|
+
if (
|
|
116
|
+
typeof input.meta?.completedAt === 'number' &&
|
|
117
|
+
Number.isFinite(input.meta.completedAt)
|
|
118
|
+
) {
|
|
119
|
+
previous.completedAt = input.meta.completedAt;
|
|
120
|
+
}
|
|
121
|
+
if (
|
|
122
|
+
input.meta &&
|
|
123
|
+
Object.prototype.hasOwnProperty.call(input.meta, 'staleAt')
|
|
124
|
+
) {
|
|
125
|
+
previous.staleAt =
|
|
126
|
+
typeof input.meta.staleAt === 'number' &&
|
|
127
|
+
Number.isFinite(input.meta.staleAt)
|
|
128
|
+
? input.meta.staleAt
|
|
129
|
+
: null;
|
|
130
|
+
}
|
|
131
|
+
if (
|
|
132
|
+
typeof input.meta?.staleAfterSeconds === 'number' &&
|
|
133
|
+
Number.isFinite(input.meta.staleAfterSeconds)
|
|
134
|
+
) {
|
|
135
|
+
previous.staleAfterSeconds = input.meta.staleAfterSeconds;
|
|
136
|
+
}
|
|
137
|
+
return previous;
|
|
41
138
|
}
|
|
42
139
|
|
|
43
140
|
export function shouldRecomputeCell(input: {
|
|
@@ -55,6 +152,23 @@ export function shouldRecomputeCell(input: {
|
|
|
55
152
|
return { action: 'recompute', reason: 'failed' };
|
|
56
153
|
}
|
|
57
154
|
|
|
155
|
+
const staleAt =
|
|
156
|
+
input.meta && Object.prototype.hasOwnProperty.call(input.meta, 'staleAt')
|
|
157
|
+
? input.meta.staleAt
|
|
158
|
+
: undefined;
|
|
159
|
+
if (staleAt === null) {
|
|
160
|
+
return { action: 'reuse', reason: 'no_expiry' };
|
|
161
|
+
}
|
|
162
|
+
if (typeof staleAt === 'number' && Number.isFinite(staleAt)) {
|
|
163
|
+
return (input.nowMs ?? Date.now()) > staleAt
|
|
164
|
+
? { action: 'recompute', reason: 'stale' }
|
|
165
|
+
: { action: 'reuse', reason: 'fresh' };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (input.policy?.dynamicStaleAfterSeconds) {
|
|
169
|
+
return { action: 'recompute', reason: 'stale' };
|
|
170
|
+
}
|
|
171
|
+
|
|
58
172
|
const staleAfterSeconds = input.policy?.staleAfterSeconds;
|
|
59
173
|
validateStaleAfterSeconds(staleAfterSeconds);
|
|
60
174
|
if (staleAfterSeconds === undefined) {
|
|
@@ -76,6 +190,37 @@ export function shouldRecomputeCell(input: {
|
|
|
76
190
|
: { action: 'reuse', reason: 'fresh' };
|
|
77
191
|
}
|
|
78
192
|
|
|
193
|
+
export function resolveReusableCellMetaForCurrentPolicy<Value>(input: {
|
|
194
|
+
hasValue: boolean;
|
|
195
|
+
value: Value;
|
|
196
|
+
meta?: CellStalenessMeta | null;
|
|
197
|
+
policy?: AuthoredCellStalenessPolicy<Value>;
|
|
198
|
+
}): Pick<CellStalenessMeta, 'staleAfterSeconds' | 'staleAt'> {
|
|
199
|
+
if (
|
|
200
|
+
!input.hasValue ||
|
|
201
|
+
typeof input.policy?.staleAfterSeconds !== 'function'
|
|
202
|
+
) {
|
|
203
|
+
return {};
|
|
204
|
+
}
|
|
205
|
+
const status = String(input.meta?.status ?? '').trim();
|
|
206
|
+
if (status === 'failed') {
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
const completedAt =
|
|
210
|
+
typeof input.meta?.completedAt === 'number' &&
|
|
211
|
+
Number.isFinite(input.meta.completedAt)
|
|
212
|
+
? input.meta.completedAt
|
|
213
|
+
: null;
|
|
214
|
+
if (completedAt === null) {
|
|
215
|
+
return {};
|
|
216
|
+
}
|
|
217
|
+
return resolveCompletedCellStalenessMeta({
|
|
218
|
+
policy: input.policy,
|
|
219
|
+
value: input.value,
|
|
220
|
+
completedAt,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
79
224
|
export function cellPolicyFields(
|
|
80
225
|
policies: CellStalenessPolicyByField | undefined,
|
|
81
226
|
): string[] {
|
|
@@ -83,6 +228,10 @@ export function cellPolicyFields(
|
|
|
83
228
|
return [];
|
|
84
229
|
}
|
|
85
230
|
return Object.entries(policies)
|
|
86
|
-
.filter(
|
|
231
|
+
.filter(
|
|
232
|
+
([, policy]) =>
|
|
233
|
+
policy.staleAfterSeconds !== undefined ||
|
|
234
|
+
policy.dynamicStaleAfterSeconds === true,
|
|
235
|
+
)
|
|
87
236
|
.map(([field]) => field);
|
|
88
237
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
flattenStaticPipeline,
|
|
3
3
|
type PlayStaticPipeline,
|
|
4
4
|
type PlayStaticSubstep,
|
|
5
5
|
} from '../plays/static-pipeline';
|
|
@@ -189,7 +189,7 @@ function extractPlanMaps(
|
|
|
189
189
|
pipeline: PlayStaticPipeline | null,
|
|
190
190
|
): ExecutionPlanMap[] {
|
|
191
191
|
if (!pipeline) return [];
|
|
192
|
-
const substeps =
|
|
192
|
+
const substeps = flattenStaticPipeline(pipeline);
|
|
193
193
|
const fallbackWaterfalls = substeps.filter(
|
|
194
194
|
(substep): substep is Extract<PlayStaticSubstep, { type: 'waterfall' }> =>
|
|
195
195
|
substep.type === 'waterfall',
|
|
@@ -252,7 +252,7 @@ function extractToolDeclarations(
|
|
|
252
252
|
if (!pipeline) return [];
|
|
253
253
|
const seen = new Set<string>();
|
|
254
254
|
const declarations: ExecutionPlan['toolDeclarations'] = [];
|
|
255
|
-
for (const substep of
|
|
255
|
+
for (const substep of flattenStaticPipeline(pipeline)) {
|
|
256
256
|
if (substep.type === 'tool') {
|
|
257
257
|
const key = `${substep.toolId}:${substep.field}`;
|
|
258
258
|
if (!seen.has(key)) {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { EmailStatus, EmailStatusValue } from './email-status';
|
|
2
|
+
|
|
3
|
+
export const JOB_CHANGE_STATUS_VALUES = [
|
|
4
|
+
'moved',
|
|
5
|
+
'no_change',
|
|
6
|
+
'left_company',
|
|
7
|
+
'unknown',
|
|
8
|
+
'profile_unavailable',
|
|
9
|
+
'no_new_company',
|
|
10
|
+
] as const;
|
|
11
|
+
|
|
12
|
+
export type JobChangeStatus = (typeof JOB_CHANGE_STATUS_VALUES)[number];
|
|
13
|
+
|
|
14
|
+
export type JobChangeGetterValue = {
|
|
15
|
+
status: JobChangeStatus;
|
|
16
|
+
date: string | null;
|
|
17
|
+
new_company: string | null;
|
|
18
|
+
new_title: string | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const PHONE_STATUS_VALUES = ['valid', 'invalid', 'unknown'] as const;
|
|
22
|
+
|
|
23
|
+
export type PhoneStatus = (typeof PHONE_STATUS_VALUES)[number];
|
|
24
|
+
|
|
25
|
+
export const DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS = {
|
|
26
|
+
id: { identity: true, valueKind: 'string' },
|
|
27
|
+
name: { identity: true, valueKind: 'string' },
|
|
28
|
+
email: { identity: true, valueKind: 'string' },
|
|
29
|
+
personal_email: { identity: true, valueKind: 'string' },
|
|
30
|
+
phone: { identity: true, valueKind: 'string' },
|
|
31
|
+
linkedin: { identity: true, valueKind: 'string' },
|
|
32
|
+
linkedin_url: { identity: true, valueKind: 'string' },
|
|
33
|
+
domain: { identity: true, valueKind: 'string' },
|
|
34
|
+
website: { identity: true, valueKind: 'string' },
|
|
35
|
+
first_name: { identity: true, valueKind: 'string' },
|
|
36
|
+
last_name: { identity: true, valueKind: 'string' },
|
|
37
|
+
full_name: { identity: true, valueKind: 'string' },
|
|
38
|
+
company: { identity: true, valueKind: 'string' },
|
|
39
|
+
company_name: { identity: true, valueKind: 'string' },
|
|
40
|
+
organization_name: { identity: true, valueKind: 'string' },
|
|
41
|
+
company_domain: { identity: true, valueKind: 'string' },
|
|
42
|
+
company_website: { identity: true, valueKind: 'string' },
|
|
43
|
+
company_linkedin_url: { identity: true, valueKind: 'string' },
|
|
44
|
+
title: { identity: false, valueKind: 'string' },
|
|
45
|
+
industry: { identity: false, valueKind: 'string' },
|
|
46
|
+
status: { identity: false, valueKind: 'string' },
|
|
47
|
+
job_change: { identity: false, valueKind: 'job_change' },
|
|
48
|
+
job_change_status: {
|
|
49
|
+
identity: false,
|
|
50
|
+
valueKind: 'job_change_status',
|
|
51
|
+
enum: JOB_CHANGE_STATUS_VALUES,
|
|
52
|
+
},
|
|
53
|
+
email_status: { identity: false, valueKind: 'email_status' },
|
|
54
|
+
phone_status: {
|
|
55
|
+
identity: false,
|
|
56
|
+
valueKind: 'phone_status',
|
|
57
|
+
enum: PHONE_STATUS_VALUES,
|
|
58
|
+
},
|
|
59
|
+
} as const;
|
|
60
|
+
|
|
61
|
+
export type DeeplineExtractorTarget =
|
|
62
|
+
keyof typeof DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS;
|
|
63
|
+
|
|
64
|
+
export const DEEPLINE_EXTRACTOR_TARGETS = Object.keys(
|
|
65
|
+
DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS,
|
|
66
|
+
) as DeeplineExtractorTarget[];
|
|
67
|
+
|
|
68
|
+
export type DeeplineEmailStatusGetterValue = EmailStatus | EmailStatusValue;
|
|
69
|
+
|
|
70
|
+
export type DeeplineGetterValueMap = {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
email: string;
|
|
74
|
+
personal_email: string;
|
|
75
|
+
phone: string;
|
|
76
|
+
linkedin: string;
|
|
77
|
+
linkedin_url: string;
|
|
78
|
+
domain: string;
|
|
79
|
+
website: string;
|
|
80
|
+
first_name: string;
|
|
81
|
+
last_name: string;
|
|
82
|
+
full_name: string;
|
|
83
|
+
company: string;
|
|
84
|
+
company_name: string;
|
|
85
|
+
organization_name: string;
|
|
86
|
+
company_domain: string;
|
|
87
|
+
company_website: string;
|
|
88
|
+
company_linkedin_url: string;
|
|
89
|
+
title: string;
|
|
90
|
+
industry: string;
|
|
91
|
+
status: string;
|
|
92
|
+
job_change: JobChangeGetterValue;
|
|
93
|
+
job_change_status: JobChangeStatus;
|
|
94
|
+
email_status: DeeplineEmailStatusGetterValue;
|
|
95
|
+
phone_status: PhoneStatus;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export type DeeplineGetterValue<
|
|
99
|
+
TTarget extends DeeplineExtractorTarget = DeeplineExtractorTarget,
|
|
100
|
+
> = DeeplineGetterValueMap[TTarget];
|
|
101
|
+
|
|
102
|
+
export function isDeeplineExtractorTarget(
|
|
103
|
+
value: string,
|
|
104
|
+
): value is DeeplineExtractorTarget {
|
|
105
|
+
return value in DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS;
|
|
106
|
+
}
|
|
@@ -12,6 +12,9 @@ import {
|
|
|
12
12
|
|
|
13
13
|
export const PLAY_RUNTIME_PROVIDER_IDS = {
|
|
14
14
|
workersEdge: 'workers_edge',
|
|
15
|
+
postgresFast: 'postgres_fast',
|
|
16
|
+
postgresFastSandbox: 'postgres_fast_sandbox',
|
|
17
|
+
postgresFastWorkers: 'postgres_fast_workers',
|
|
15
18
|
local: 'local',
|
|
16
19
|
} as const;
|
|
17
20
|
|
|
@@ -39,6 +42,31 @@ export const PLAY_RUNTIME_PROVIDERS: Record<
|
|
|
39
42
|
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
40
43
|
label: 'Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup',
|
|
41
44
|
},
|
|
45
|
+
postgres_fast: {
|
|
46
|
+
id: PLAY_RUNTIME_PROVIDER_IDS.postgresFast,
|
|
47
|
+
scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
|
|
48
|
+
runner: PLAY_RUNTIME_BACKENDS.daytona,
|
|
49
|
+
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
50
|
+
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
51
|
+
label: 'Experimental Postgres Scheduler + warm sandbox runner + DO dedup',
|
|
52
|
+
},
|
|
53
|
+
postgres_fast_sandbox: {
|
|
54
|
+
id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastSandbox,
|
|
55
|
+
scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
|
|
56
|
+
runner: PLAY_RUNTIME_BACKENDS.daytona,
|
|
57
|
+
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
58
|
+
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
59
|
+
label: 'Experimental Postgres Scheduler + warm sandbox runner + DO dedup',
|
|
60
|
+
},
|
|
61
|
+
postgres_fast_workers: {
|
|
62
|
+
id: PLAY_RUNTIME_PROVIDER_IDS.postgresFastWorkers,
|
|
63
|
+
scheduler: PLAY_SCHEDULER_BACKENDS.postgres,
|
|
64
|
+
runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
|
|
65
|
+
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
66
|
+
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
67
|
+
label:
|
|
68
|
+
'Experimental Postgres Scheduler + Queue/DO-woken Workers + DO dedup',
|
|
69
|
+
},
|
|
42
70
|
local: {
|
|
43
71
|
id: PLAY_RUNTIME_PROVIDER_IDS.local,
|
|
44
72
|
scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
|
|
@@ -22,6 +22,7 @@ import type { PreloadedRuntimeDbSession } from './db-session';
|
|
|
22
22
|
export const PLAY_SCHEDULER_BACKENDS = {
|
|
23
23
|
temporal: 'temporal',
|
|
24
24
|
cfWorkflows: 'cf-workflows',
|
|
25
|
+
postgres: 'postgres',
|
|
25
26
|
inProcess: 'in-process',
|
|
26
27
|
} as const;
|
|
27
28
|
|
|
@@ -65,6 +66,7 @@ export type PlaySchedulerSubmitInput = {
|
|
|
65
66
|
runId: string;
|
|
66
67
|
playId: string;
|
|
67
68
|
playName: string;
|
|
69
|
+
workflowFamilyKey?: string | null;
|
|
68
70
|
artifactStorageKey: string;
|
|
69
71
|
/**
|
|
70
72
|
* Optional inline artifact for schedulers that run the legacy Temporal
|
|
@@ -119,6 +121,8 @@ export type PlaySchedulerSubmitInput = {
|
|
|
119
121
|
orgId: string;
|
|
120
122
|
userEmail: string;
|
|
121
123
|
userId?: string | null;
|
|
124
|
+
source?: 'published' | 'ad_hoc' | 'draft';
|
|
125
|
+
executionProfile?: string | null;
|
|
122
126
|
/** runner backend to use for executing attempts */
|
|
123
127
|
runtimeBackend: string;
|
|
124
128
|
/** dedup backend for cross-attempt cross-process idempotency */
|
|
@@ -200,6 +204,13 @@ export function normalizePlaySchedulerBackend(
|
|
|
200
204
|
if (normalized === 'cf-workflows' || normalized === 'cf_workflows') {
|
|
201
205
|
return PLAY_SCHEDULER_BACKENDS.cfWorkflows;
|
|
202
206
|
}
|
|
207
|
+
if (
|
|
208
|
+
normalized === 'postgres' ||
|
|
209
|
+
normalized === 'postgres-scheduler' ||
|
|
210
|
+
normalized === 'postgres_scheduler'
|
|
211
|
+
) {
|
|
212
|
+
return PLAY_SCHEDULER_BACKENDS.postgres;
|
|
213
|
+
}
|
|
203
214
|
if (normalized === 'in-process' || normalized === 'in_process') {
|
|
204
215
|
return PLAY_SCHEDULER_BACKENDS.inProcess;
|
|
205
216
|
}
|