deepline 0.1.109 → 0.1.111
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 +2634 -1532
- package/dist/cli/index.mjs +2547 -1451
- package/dist/index.d.mts +21 -14
- package/dist/index.d.ts +21 -14
- package/dist/index.js +97 -23
- package/dist/index.mjs +97 -23
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +192 -121
- package/dist/repo/apps/play-runner-workers/src/entry.ts +254 -65
- package/dist/repo/apps/play-runner-workers/src/runtime/receipts.ts +18 -27
- package/dist/repo/apps/play-runner-workers/src/workflow-instance-create.ts +44 -0
- package/dist/repo/apps/play-runner-workers/src/workflow-retry.ts +7 -11
- package/dist/repo/sdk/src/client.ts +35 -12
- package/dist/repo/sdk/src/errors.ts +2 -2
- package/dist/repo/sdk/src/http.ts +87 -7
- package/dist/repo/sdk/src/play.ts +1 -1
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +5 -1
- package/dist/repo/sdk/src/release.ts +13 -10
- package/dist/repo/sdk/src/tool-output.ts +2 -2
- package/dist/repo/sdk/src/types.ts +9 -6
- package/dist/repo/shared_libs/play-runtime/fullenrich-batching.ts +229 -0
- package/dist/repo/shared_libs/play-runtime/governor/policy.ts +1 -1
- package/dist/repo/shared_libs/play-runtime/play-runtime-batching-registry.ts +20 -0
- package/dist/repo/shared_libs/play-runtime/run-failure.ts +20 -12
- package/dist/repo/shared_libs/play-runtime/run-ledger.ts +147 -70
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +6 -2
- package/dist/repo/shared_libs/play-runtime/secret-redaction.ts +15 -0
- package/dist/repo/shared_libs/play-runtime/work-receipts.ts +1 -0
- package/dist/repo/shared_libs/plays/bundling/index.ts +193 -21
- package/dist/repo/shared_libs/plays/static-pipeline.ts +1 -3
- package/dist/repo/shared_libs/security/outbound-url-policy.ts +238 -0
- package/dist/repo/shared_libs/security/safe-fetch.ts +118 -0
- package/dist/viewer/viewer.css +617 -0
- package/dist/viewer/viewer.js +1496 -0
- package/package.json +5 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type WorkflowInstanceLike = {
|
|
2
|
+
id: string;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export type WorkflowInstanceCreateResult<T extends WorkflowInstanceLike> = {
|
|
6
|
+
instance: T;
|
|
7
|
+
startMode: 'created' | 'reattached_existing';
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function isWorkflowInstanceAlreadyExistsError(error: unknown): boolean {
|
|
11
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12
|
+
return /instance[._ -]?already[._ -]?exists|Instance already exists/i.test(
|
|
13
|
+
message,
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function createOrAttachWorkflowInstance<
|
|
18
|
+
T extends WorkflowInstanceLike,
|
|
19
|
+
>(input: {
|
|
20
|
+
create: () => Promise<T>;
|
|
21
|
+
getExisting: () => Promise<T>;
|
|
22
|
+
}): Promise<WorkflowInstanceCreateResult<T>> {
|
|
23
|
+
try {
|
|
24
|
+
return { instance: await input.create(), startMode: 'created' };
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (!isWorkflowInstanceAlreadyExistsError(error)) {
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
return {
|
|
31
|
+
instance: await input.getExisting(),
|
|
32
|
+
startMode: 'reattached_existing',
|
|
33
|
+
};
|
|
34
|
+
} catch (attachError) {
|
|
35
|
+
const message =
|
|
36
|
+
attachError instanceof Error
|
|
37
|
+
? attachError.message
|
|
38
|
+
: String(attachError);
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Workflow instance already exists but could not be reattached: ${message}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isCloudflareDurableObjectCodeUpdatedError,
|
|
3
|
-
normalizePlayRunFailure,
|
|
4
|
-
} from '../../../shared_libs/play-runtime/run-failure';
|
|
1
|
+
import { normalizePlayRunFailure } from '../../../shared_libs/play-runtime/run-failure';
|
|
5
2
|
|
|
6
3
|
export const PLATFORM_DEPLOY_WORKFLOW_RETRY_LIMIT = 1;
|
|
7
4
|
|
|
@@ -26,25 +23,24 @@ export function decideWorkflowPlatformRetry(input: {
|
|
|
26
23
|
if (!input.error) {
|
|
27
24
|
return { action: 'fail', reason: null, message: null };
|
|
28
25
|
}
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
);
|
|
26
|
+
const failure = normalizePlayRunFailure(input.error);
|
|
27
|
+
const retryablePlatformReset = failure.code === 'PLATFORM_DEPLOY_INTERRUPTED';
|
|
32
28
|
if (
|
|
33
29
|
retryablePlatformReset &&
|
|
34
30
|
input.retryAttempts < PLATFORM_DEPLOY_WORKFLOW_RETRY_LIMIT
|
|
35
31
|
) {
|
|
36
32
|
return {
|
|
37
33
|
action: 'retry',
|
|
38
|
-
reason: '
|
|
34
|
+
reason: 'cloudflare_durable_object_reset',
|
|
39
35
|
nextAttempt: input.retryAttempts + 1,
|
|
40
|
-
message:
|
|
36
|
+
message: failure.message,
|
|
41
37
|
};
|
|
42
38
|
}
|
|
43
39
|
return {
|
|
44
40
|
action: 'fail',
|
|
45
41
|
reason: retryablePlatformReset
|
|
46
|
-
? '
|
|
42
|
+
? 'cloudflare_durable_object_reset_retry_exhausted'
|
|
47
43
|
: null,
|
|
48
|
-
message:
|
|
44
|
+
message: failure.message,
|
|
49
45
|
};
|
|
50
46
|
}
|
|
@@ -413,11 +413,14 @@ export type BillingPlanEntry = {
|
|
|
413
413
|
};
|
|
414
414
|
|
|
415
415
|
/** One usage metric published in the billing catalog. */
|
|
416
|
-
export type
|
|
416
|
+
export type BillingMeterEntry = {
|
|
417
417
|
id: string;
|
|
418
418
|
name: string;
|
|
419
419
|
};
|
|
420
420
|
|
|
421
|
+
/** @deprecated Use BillingMeterEntry. Retained for wire/API alias compatibility. */
|
|
422
|
+
export type BillingMetricEntry = BillingMeterEntry;
|
|
423
|
+
|
|
421
424
|
/** The caller's active plan as reported by the plans endpoint. */
|
|
422
425
|
export type BillingActivePlan = {
|
|
423
426
|
plan_family_id: string;
|
|
@@ -440,6 +443,8 @@ export type BillingPlansResult = {
|
|
|
440
443
|
catalog_version: string;
|
|
441
444
|
active_plan: BillingActivePlan;
|
|
442
445
|
plans: BillingPlanEntry[];
|
|
446
|
+
meters: BillingMeterEntry[];
|
|
447
|
+
/** @deprecated Use meters. Retained for installed SDK compatibility. */
|
|
443
448
|
metrics: BillingMetricEntry[];
|
|
444
449
|
};
|
|
445
450
|
|
|
@@ -1075,12 +1080,12 @@ export class DeeplineClient {
|
|
|
1075
1080
|
* Returns everything from {@link ToolDefinition} plus pricing info, sample
|
|
1076
1081
|
* inputs/outputs, failure modes, and cost estimates.
|
|
1077
1082
|
*
|
|
1078
|
-
* @param toolId - Tool identifier (e.g. `"
|
|
1083
|
+
* @param toolId - Tool identifier (e.g. `"dropleads_search_people"`)
|
|
1079
1084
|
* @returns Full tool metadata
|
|
1080
1085
|
*
|
|
1081
1086
|
* @example
|
|
1082
1087
|
* ```typescript
|
|
1083
|
-
* const meta = await client.getTool('
|
|
1088
|
+
* const meta = await client.getTool('dropleads_search_people');
|
|
1084
1089
|
* console.log(`Cost: ${meta.estimatedCreditsRange} credits`);
|
|
1085
1090
|
* console.log(`Input schema:`, meta.inputSchema);
|
|
1086
1091
|
* ```
|
|
@@ -1120,6 +1125,7 @@ export class DeeplineClient {
|
|
|
1120
1125
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
1121
1126
|
{ payload: input },
|
|
1122
1127
|
headers,
|
|
1128
|
+
{ forbiddenAsApiError: true },
|
|
1123
1129
|
);
|
|
1124
1130
|
}
|
|
1125
1131
|
|
|
@@ -1228,7 +1234,7 @@ export class DeeplineClient {
|
|
|
1228
1234
|
? { waitForCompletionMs: request.waitForCompletionMs }
|
|
1229
1235
|
: {}),
|
|
1230
1236
|
// Profile selection is the API's job, not the CLI's. The server
|
|
1231
|
-
//
|
|
1237
|
+
// defaults to workers_edge; tests and runtime probes that want a
|
|
1232
1238
|
// different profile pass `request.profile` explicitly.
|
|
1233
1239
|
...(request.profile ? { profile: request.profile } : {}),
|
|
1234
1240
|
},
|
|
@@ -1338,10 +1344,15 @@ export class DeeplineClient {
|
|
|
1338
1344
|
sourceFiles: input.sourceFiles,
|
|
1339
1345
|
artifact: input.artifact,
|
|
1340
1346
|
}));
|
|
1341
|
-
return this.http.post(
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1347
|
+
return this.http.post(
|
|
1348
|
+
'/api/v2/plays/artifacts',
|
|
1349
|
+
{
|
|
1350
|
+
...input,
|
|
1351
|
+
compilerManifest,
|
|
1352
|
+
},
|
|
1353
|
+
undefined,
|
|
1354
|
+
{ forbiddenAsApiError: true, retryApiErrors: true },
|
|
1355
|
+
);
|
|
1345
1356
|
}
|
|
1346
1357
|
|
|
1347
1358
|
/**
|
|
@@ -1379,7 +1390,12 @@ export class DeeplineClient {
|
|
|
1379
1390
|
}>;
|
|
1380
1391
|
}> {
|
|
1381
1392
|
if (artifacts.length === 0) {
|
|
1382
|
-
return this.http.post(
|
|
1393
|
+
return this.http.post(
|
|
1394
|
+
'/api/v2/plays/artifacts',
|
|
1395
|
+
{ artifacts },
|
|
1396
|
+
undefined,
|
|
1397
|
+
{ forbiddenAsApiError: true, retryApiErrors: true },
|
|
1398
|
+
);
|
|
1383
1399
|
}
|
|
1384
1400
|
const compiledArtifacts = await mapWithConcurrency(
|
|
1385
1401
|
artifacts,
|
|
@@ -1414,9 +1430,14 @@ export class DeeplineClient {
|
|
|
1414
1430
|
triggerMetadata?: unknown;
|
|
1415
1431
|
triggerBindings?: unknown;
|
|
1416
1432
|
}>;
|
|
1417
|
-
}>(
|
|
1418
|
-
artifacts
|
|
1419
|
-
|
|
1433
|
+
}>(
|
|
1434
|
+
'/api/v2/plays/artifacts',
|
|
1435
|
+
{
|
|
1436
|
+
artifacts: chunk,
|
|
1437
|
+
},
|
|
1438
|
+
undefined,
|
|
1439
|
+
{ forbiddenAsApiError: true, retryApiErrors: true },
|
|
1440
|
+
),
|
|
1420
1441
|
);
|
|
1421
1442
|
}
|
|
1422
1443
|
return {
|
|
@@ -2446,6 +2467,8 @@ export class DeeplineClient {
|
|
|
2446
2467
|
return this.http.post<PublishPlayVersionResult>(
|
|
2447
2468
|
`/api/v2/plays/${encodedName}/live`,
|
|
2448
2469
|
request,
|
|
2470
|
+
undefined,
|
|
2471
|
+
{ forbiddenAsApiError: true },
|
|
2449
2472
|
);
|
|
2450
2473
|
}
|
|
2451
2474
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* const client = new DeeplineClient();
|
|
12
12
|
* try {
|
|
13
|
-
* await client.executeTool('
|
|
13
|
+
* await client.executeTool('dropleads_search_people', { query: 'cto' });
|
|
14
14
|
* } catch (err) {
|
|
15
15
|
* if (err instanceof AuthError) {
|
|
16
16
|
* console.error('Bad API key — run: deepline auth register');
|
|
@@ -77,7 +77,7 @@ export class AuthError extends DeeplineError {
|
|
|
77
77
|
* import { RateLimitError } from 'deepline';
|
|
78
78
|
*
|
|
79
79
|
* try {
|
|
80
|
-
* await client.executeTool('
|
|
80
|
+
* await client.executeTool('dropleads_search_people', { query: 'cto' });
|
|
81
81
|
* } catch (err) {
|
|
82
82
|
* if (err instanceof RateLimitError) {
|
|
83
83
|
* console.log(`Retry after ${err.retryAfterMs}ms`);
|
|
@@ -35,6 +35,8 @@ import {
|
|
|
35
35
|
} from '../../shared_libs/play-runtime/coordinator-headers.js';
|
|
36
36
|
|
|
37
37
|
const MAX_DIAGNOSTIC_HEADER_LENGTH = 120;
|
|
38
|
+
const COWORK_NETWORK_HINT =
|
|
39
|
+
'Claude Cowork appears to be running Deepline in a network-restricted sandbox. In Claude Desktop, open Settings > Capabilities, turn on Allow network egress, and set Domain allowlist to All domains for the Cowork session.';
|
|
38
40
|
|
|
39
41
|
interface RequestOptions {
|
|
40
42
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
@@ -51,6 +53,11 @@ interface RequestOptions {
|
|
|
51
53
|
* {@link AuthError}.
|
|
52
54
|
*/
|
|
53
55
|
forbiddenAsApiError?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Retry HTTP 408/425/5xx JSON API responses. Use only for idempotent requests;
|
|
58
|
+
* most mutating API calls must fail loudly after the first server response.
|
|
59
|
+
*/
|
|
60
|
+
retryApiErrors?: boolean;
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
interface StreamOptions {
|
|
@@ -114,6 +121,7 @@ export class HttpClient {
|
|
|
114
121
|
'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,
|
|
115
122
|
'X-Deepline-Client-Family': 'sdk',
|
|
116
123
|
'X-Deepline-CLI-Family': 'sdk',
|
|
124
|
+
'X-Deepline-Agent-Runtime': detectAgentRuntime(),
|
|
117
125
|
'X-Deepline-CLI-Version': SDK_VERSION,
|
|
118
126
|
'X-Deepline-SDK-Version': SDK_VERSION,
|
|
119
127
|
'X-Deepline-API-Contract': SDK_API_CONTRACT,
|
|
@@ -270,6 +278,9 @@ export class HttpClient {
|
|
|
270
278
|
}
|
|
271
279
|
|
|
272
280
|
if (!response.ok) {
|
|
281
|
+
const retryableApiError =
|
|
282
|
+
options?.retryApiErrors === true &&
|
|
283
|
+
isRetryableApiErrorResponse(response.status);
|
|
273
284
|
// A 5xx that escaped a Worker can return Cloudflare's default HTML
|
|
274
285
|
// error page. Never surface raw HTML to CLI users: replace the
|
|
275
286
|
// message with a structured summary and store a short flag in
|
|
@@ -280,7 +291,7 @@ export class HttpClient {
|
|
|
280
291
|
response.headers.get('content-type'),
|
|
281
292
|
);
|
|
282
293
|
if (htmlError) {
|
|
283
|
-
|
|
294
|
+
lastError = new DeeplineError(
|
|
284
295
|
htmlError.message(response.status),
|
|
285
296
|
response.status,
|
|
286
297
|
'API_ERROR',
|
|
@@ -292,6 +303,11 @@ export class HttpClient {
|
|
|
292
303
|
: {}),
|
|
293
304
|
},
|
|
294
305
|
);
|
|
306
|
+
if (retryableApiError && attempt < this.config.maxRetries) {
|
|
307
|
+
retryAfterDelayMs = parseOptionalRetryAfter(response);
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
throw lastError;
|
|
295
311
|
}
|
|
296
312
|
const errorValue =
|
|
297
313
|
typeof parsed === 'object' && parsed && 'error' in parsed
|
|
@@ -313,9 +329,20 @@ export class HttpClient {
|
|
|
313
329
|
'string'
|
|
314
330
|
? (parsed as Record<string, string>).message
|
|
315
331
|
: `HTTP ${response.status}`;
|
|
316
|
-
|
|
332
|
+
const apiErrorCode =
|
|
333
|
+
errorValue &&
|
|
334
|
+
typeof errorValue === 'object' &&
|
|
335
|
+
typeof (errorValue as Record<string, unknown>).code === 'string'
|
|
336
|
+
? (errorValue as Record<string, string>).code
|
|
337
|
+
: 'API_ERROR';
|
|
338
|
+
lastError = new DeeplineError(msg, response.status, apiErrorCode, {
|
|
317
339
|
response: parsed,
|
|
318
340
|
});
|
|
341
|
+
if (retryableApiError && attempt < this.config.maxRetries) {
|
|
342
|
+
retryAfterDelayMs = parseOptionalRetryAfter(response);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
throw lastError;
|
|
319
346
|
}
|
|
320
347
|
|
|
321
348
|
return parsed as T;
|
|
@@ -341,7 +368,7 @@ export class HttpClient {
|
|
|
341
368
|
const errorMessage = lastError?.message
|
|
342
369
|
? `Unable to connect to ${baseUrl}. ${lastError.message}`
|
|
343
370
|
: `Unable to connect to ${baseUrl}. Is the computer able to access the url?`;
|
|
344
|
-
throw new DeeplineError(errorMessage);
|
|
371
|
+
throw new DeeplineError(withCoworkNetworkHint(errorMessage));
|
|
345
372
|
}
|
|
346
373
|
|
|
347
374
|
/**
|
|
@@ -427,9 +454,11 @@ export class HttpClient {
|
|
|
427
454
|
}
|
|
428
455
|
|
|
429
456
|
throw new DeeplineError(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
457
|
+
withCoworkNetworkHint(
|
|
458
|
+
lastError?.message
|
|
459
|
+
? `Unable to stream from ${this.config.baseUrl}. ${lastError.message}`
|
|
460
|
+
: `Unable to stream from ${this.config.baseUrl}.`,
|
|
461
|
+
),
|
|
433
462
|
);
|
|
434
463
|
}
|
|
435
464
|
|
|
@@ -444,11 +473,16 @@ export class HttpClient {
|
|
|
444
473
|
path: string,
|
|
445
474
|
body: unknown,
|
|
446
475
|
headers?: Record<string, string>,
|
|
476
|
+
options?: Pick<
|
|
477
|
+
RequestOptions,
|
|
478
|
+
'forbiddenAsApiError' | 'retryApiErrors' | 'timeout'
|
|
479
|
+
>,
|
|
447
480
|
): Promise<T> {
|
|
448
481
|
return this.request<T>(path, {
|
|
449
482
|
method: 'POST',
|
|
450
483
|
body,
|
|
451
484
|
headers,
|
|
485
|
+
...options,
|
|
452
486
|
});
|
|
453
487
|
}
|
|
454
488
|
|
|
@@ -502,6 +536,10 @@ function parseResponseBody(body: string): unknown {
|
|
|
502
536
|
}
|
|
503
537
|
}
|
|
504
538
|
|
|
539
|
+
function isRetryableApiErrorResponse(status: number): boolean {
|
|
540
|
+
return status === 408 || status === 425 || (status >= 500 && status < 600);
|
|
541
|
+
}
|
|
542
|
+
|
|
505
543
|
/**
|
|
506
544
|
* Detect a raw Cloudflare HTML error page in an error response body.
|
|
507
545
|
*
|
|
@@ -579,6 +617,10 @@ function apiErrorMessage(parsed: unknown, status: number): string {
|
|
|
579
617
|
|
|
580
618
|
/** Parse the `Retry-After` header as milliseconds. Falls back to 5000ms. */
|
|
581
619
|
function parseRetryAfter(response: Response): number {
|
|
620
|
+
return parseOptionalRetryAfter(response) ?? 5000;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
function parseOptionalRetryAfter(response: Response): number | null {
|
|
582
624
|
const header = response.headers.get('retry-after');
|
|
583
625
|
if (header) {
|
|
584
626
|
const seconds = Number(header);
|
|
@@ -586,7 +628,7 @@ function parseRetryAfter(response: Response): number {
|
|
|
586
628
|
return seconds * 1000;
|
|
587
629
|
}
|
|
588
630
|
}
|
|
589
|
-
return
|
|
631
|
+
return null;
|
|
590
632
|
}
|
|
591
633
|
|
|
592
634
|
/**
|
|
@@ -670,3 +712,41 @@ function decodeSseFrame<TEvent extends LiveEventEnvelope>(
|
|
|
670
712
|
function sleep(ms: number): Promise<void> {
|
|
671
713
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
672
714
|
}
|
|
715
|
+
|
|
716
|
+
function isTruthyEnv(name: string): boolean {
|
|
717
|
+
const normalized = process.env[name]?.trim().toLowerCase();
|
|
718
|
+
return ['1', 'true', 'yes', 'on'].includes(normalized ?? '');
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function isCoworkLikeSandbox(): boolean {
|
|
722
|
+
const pluginMode = isTruthyEnv('DEEPLINE_PLUGIN_MODE');
|
|
723
|
+
const claudeRemote = isTruthyEnv('CLAUDE_CODE_REMOTE');
|
|
724
|
+
const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
|
|
725
|
+
const pluginRoot = Boolean(process.env.DEEPLINE_PLUGIN_ROOT?.trim());
|
|
726
|
+
const home = process.env.HOME?.trim() ?? '';
|
|
727
|
+
const sessionHome = home.startsWith('/sessions/');
|
|
728
|
+
return (
|
|
729
|
+
(pluginMode || pluginRoot) && (claudeRemote || projectDir || sessionHome)
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function detectAgentRuntime(): string {
|
|
734
|
+
if (process.env.CODEX_THREAD_ID?.trim()) return 'codex';
|
|
735
|
+
if (isCoworkLikeSandbox()) return 'claude_cowork';
|
|
736
|
+
if (process.env.CLAUDECODE?.trim() === '1') return 'claude_code';
|
|
737
|
+
if (process.env.CLINE_ACTIVE?.trim().toLowerCase() === 'true') return 'cline';
|
|
738
|
+
if (process.env.CURSOR_TRACE_ID?.trim() || process.env.CURSOR_AGENT?.trim()) {
|
|
739
|
+
return 'cursor';
|
|
740
|
+
}
|
|
741
|
+
if (process.env.WINDSURF?.trim() || process.env.CASCADE?.trim()) {
|
|
742
|
+
return 'windsurf';
|
|
743
|
+
}
|
|
744
|
+
return 'unknown';
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function withCoworkNetworkHint(message: string): string {
|
|
748
|
+
if (!isCoworkLikeSandbox() || message.includes(COWORK_NETWORK_HINT)) {
|
|
749
|
+
return message;
|
|
750
|
+
}
|
|
751
|
+
return `${message}\n${COWORK_NETWORK_HINT}`;
|
|
752
|
+
}
|
|
@@ -1456,7 +1456,7 @@ export class DeeplineContext {
|
|
|
1456
1456
|
* @example
|
|
1457
1457
|
* ```typescript
|
|
1458
1458
|
* const tools = await deepline.tools.list();
|
|
1459
|
-
* const meta = await deepline.tools.get('
|
|
1459
|
+
* const meta = await deepline.tools.get('dropleads_search_people');
|
|
1460
1460
|
* const companyLookup = await deepline.tools.execute('test_company_search', { domain: 'stripe.com' });
|
|
1461
1461
|
* const company = companyLookup.toolResponse.raw;
|
|
1462
1462
|
* ```
|
|
@@ -141,6 +141,9 @@ export function createSdkPlayBundlingAdapter(): PlayBundlingAdapter {
|
|
|
141
141
|
sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
|
|
142
142
|
workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
|
|
143
143
|
workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
|
|
144
|
+
workersRuntimeFingerprintDirs: [
|
|
145
|
+
resolve(PROJECT_ROOT, 'shared_libs', 'play-runtime'),
|
|
146
|
+
],
|
|
144
147
|
discoverPackagedLocalFiles,
|
|
145
148
|
warnAboutNonDevelopmentBundling,
|
|
146
149
|
};
|
|
@@ -155,7 +158,8 @@ export async function bundlePlayFile(
|
|
|
155
158
|
exportName: options.exportName,
|
|
156
159
|
adapter: createSdkPlayBundlingAdapter(),
|
|
157
160
|
});
|
|
158
|
-
if (result.success)
|
|
161
|
+
if (result.success)
|
|
162
|
+
validatePlaySourceFilesHaveNoInlineSecrets(result.sourceFiles);
|
|
159
163
|
return result;
|
|
160
164
|
}
|
|
161
165
|
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
* Ordinary SDK PRs do NOT bump `version` here. Patch version selection
|
|
5
5
|
* happens at publish time: on push to main, `.github/workflows/sdk-release.yml`
|
|
6
6
|
* (via `scripts/sdk-release-autobump.ts`) compares the built package against
|
|
7
|
-
* the published npm tarball and, when the content changed, stamps the
|
|
8
|
-
* unpublished patch into `version` + `supportPolicy.latest`
|
|
9
|
-
* in the same run.
|
|
7
|
+
* the latest published npm tarball and, when the content changed, stamps the
|
|
8
|
+
* next unpublished patch into `version` + `supportPolicy.latest` in the CI
|
|
9
|
+
* workspace only and publishes it in the same run. That patch stamp is not
|
|
10
|
+
* committed back to main; production endpoints read npm metadata when they
|
|
11
|
+
* need the newest patch-level SDK/CLI version.
|
|
10
12
|
*
|
|
11
13
|
* Edit THIS file by hand only for deliberate release decisions:
|
|
12
14
|
* - minor/major version bumps (set `version` and `supportPolicy.latest`),
|
|
@@ -23,17 +25,18 @@
|
|
|
23
25
|
* `scripts/sync-sdk-package-version.ts`, which runs as part of
|
|
24
26
|
* `bun run sdk:build`.
|
|
25
27
|
* - `contracts/sdk-api.manifest.json` is regenerated at build time from
|
|
26
|
-
* `src/lib/sdk/api-routes.ts` and the apiContract here; the
|
|
27
|
-
* `contracts/sdk-api.manifest.hash` is
|
|
28
|
+
* `src/lib/sdk/api-routes.ts` and the apiContract here; the matching
|
|
29
|
+
* `contracts/sdk-api.manifest.hash` is an ignored local/CI audit artifact.
|
|
28
30
|
*
|
|
29
|
-
* Any drift between
|
|
30
|
-
* `check:sdk-release-readiness` failure with a one-shot fix command
|
|
31
|
+
* Any drift between release source and derived release locations is a
|
|
32
|
+
* `check:sdk-release-readiness` failure with a one-shot fix command; SDK/API
|
|
33
|
+
* compatibility policy is enforced by `bun run sdk:api-contract:check`.
|
|
31
34
|
*/
|
|
32
35
|
|
|
33
36
|
export type SdkReleaseChannel = 'latest' | 'next' | 'beta';
|
|
34
37
|
|
|
35
38
|
export type SdkSupportPolicy = {
|
|
36
|
-
/**
|
|
39
|
+
/** Checked-in latest policy value; publish-time patch latest is read from npm. */
|
|
37
40
|
latest: string;
|
|
38
41
|
/**
|
|
39
42
|
* Anything strictly below this returns `status: "unsupported"` from
|
|
@@ -96,10 +99,10 @@ export const SDK_RELEASE = {
|
|
|
96
99
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
97
100
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
98
101
|
// the SDK enrich generator's one-second stale policy.
|
|
99
|
-
version: '0.1.
|
|
102
|
+
version: '0.1.111',
|
|
100
103
|
apiContract: '2026-06-dataset-column-cell-stale-hard-cutover',
|
|
101
104
|
supportPolicy: {
|
|
102
|
-
latest: '0.1.
|
|
105
|
+
latest: '0.1.111',
|
|
103
106
|
minimumSupported: '0.1.53',
|
|
104
107
|
deprecatedBelow: '0.1.53',
|
|
105
108
|
commandMinimumSupported: [
|
|
@@ -203,8 +203,8 @@ function findBestArrayCandidate(
|
|
|
203
203
|
*
|
|
204
204
|
* @example Using configured paths (from tool metadata)
|
|
205
205
|
* ```typescript
|
|
206
|
-
* const meta = await client.getTool('
|
|
207
|
-
* const result = await client.executeTool('
|
|
206
|
+
* const meta = await client.getTool('dropleads_search_people');
|
|
207
|
+
* const result = await client.executeTool('dropleads_search_people', { query: 'cto' });
|
|
208
208
|
*
|
|
209
209
|
* const list = tryConvertToList(result, {
|
|
210
210
|
* listExtractorPaths: meta.listExtractorPaths,
|
|
@@ -138,9 +138,9 @@ export type {
|
|
|
138
138
|
* schema, examples, pricing, and extraction guidance before executing.
|
|
139
139
|
*/
|
|
140
140
|
export interface ToolDefinition {
|
|
141
|
-
/** Unique tool identifier used in API calls (e.g. `"
|
|
141
|
+
/** Unique tool identifier used in API calls (e.g. `"dropleads_search_people"`). */
|
|
142
142
|
toolId: string;
|
|
143
|
-
/** Provider that backs this tool (e.g. `"
|
|
143
|
+
/** Provider that backs this tool (e.g. `"hunter"`, `"dropleads"`, `"test"`). */
|
|
144
144
|
provider: string;
|
|
145
145
|
/** Human-readable name for display. */
|
|
146
146
|
displayName: string;
|
|
@@ -154,6 +154,8 @@ export interface ToolDefinition {
|
|
|
154
154
|
operationId?: string;
|
|
155
155
|
/** Alternative names that resolve to this tool. */
|
|
156
156
|
operationAliases?: string[];
|
|
157
|
+
/** Explicit globally runnable play reference for play-backed catalog entries. */
|
|
158
|
+
playReference?: `prebuilt/${string}`;
|
|
157
159
|
/** Whether detailed input schema is available from `tools describe`. */
|
|
158
160
|
hasInputSchema?: boolean;
|
|
159
161
|
/** Whether detailed output schema is available from `tools describe`. */
|
|
@@ -313,8 +315,8 @@ export interface ToolSearchResult {
|
|
|
313
315
|
*
|
|
314
316
|
* @example
|
|
315
317
|
* ```typescript
|
|
316
|
-
* const meta = await client.getTool('
|
|
317
|
-
* console.log(meta.displayName); // "
|
|
318
|
+
* const meta = await client.getTool('dropleads_search_people');
|
|
319
|
+
* console.log(meta.displayName); // "DropLeads People Search"
|
|
318
320
|
* console.log(meta.estimatedCreditsRange); // "1-5"
|
|
319
321
|
* console.log(meta.samples); // { input: {...}, output: {...} }
|
|
320
322
|
* ```
|
|
@@ -933,8 +935,9 @@ export interface StartPlayRunRequest {
|
|
|
933
935
|
/** Optionally let the start request wait briefly and return a terminal result. */
|
|
934
936
|
waitForCompletionMs?: number;
|
|
935
937
|
/**
|
|
936
|
-
* Per-run execution profile override. The server defaults to
|
|
937
|
-
* tests can pass
|
|
938
|
+
* Per-run execution profile override. The server defaults to workers_edge;
|
|
939
|
+
* tests and runtime probes can pass a different profile here. Most callers
|
|
940
|
+
* should leave this unset.
|
|
938
941
|
*/
|
|
939
942
|
profile?: string;
|
|
940
943
|
}
|