deepline 0.1.261 → 0.1.263
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/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/row-isolation.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +19 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +26 -2
- package/dist/bundling-sources/shared_libs/plays/tool-category-descriptions.ts +51 -0
- package/dist/cli/index.js +260 -21
- package/dist/cli/index.mjs +260 -21
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -123,7 +123,7 @@ export const SDK_RELEASE = {
|
|
|
123
123
|
// Deepline-native radars. Older clients must update before discovering,
|
|
124
124
|
// checking, or deploying an unlaunched monitor integration.
|
|
125
125
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
126
|
-
version: '0.1.
|
|
126
|
+
version: '0.1.263',
|
|
127
127
|
apiContract: '2026-07-native-monitor-launch-hard-cutover',
|
|
128
128
|
supportPolicy: {
|
|
129
129
|
minimumSupported: '0.1.53',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isHardBillingToolHttpError } from './tool-http-errors';
|
|
2
2
|
import { isRuntimePersistenceCircuitOpenError } from './persistence-latch';
|
|
3
|
+
import { isWorkspaceStorageNotReadyFailure } from './run-failure';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Thrown by runner Adapters when a Play Run is externally cancelled. Row
|
|
@@ -41,6 +42,7 @@ export function isRowIsolationExemptError(error: unknown): boolean {
|
|
|
41
42
|
if (isRuntimeReceiptPersistenceError(error)) return true;
|
|
42
43
|
if (isRuntimeStoragePersistenceError(error)) return true;
|
|
43
44
|
if (isRuntimePersistenceCircuitOpenError(error)) return true;
|
|
45
|
+
if (isWorkspaceStorageNotReadyFailure(error)) return true;
|
|
44
46
|
return isHardBillingToolHttpError(error);
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -59,6 +59,24 @@ export class WorkspaceStorageNotReadyError extends Error {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
export function isWorkspaceStorageNotReadyFailure(error: unknown): boolean {
|
|
63
|
+
if (error instanceof WorkspaceStorageNotReadyError) return true;
|
|
64
|
+
if (!error) return false;
|
|
65
|
+
if (typeof error === 'object') {
|
|
66
|
+
const code = (error as { code?: unknown }).code;
|
|
67
|
+
if (code === WORKSPACE_STORAGE_NOT_READY_CODE) return true;
|
|
68
|
+
const nestedErrors = (error as { errors?: unknown }).errors;
|
|
69
|
+
if (
|
|
70
|
+
Array.isArray(nestedErrors) &&
|
|
71
|
+
nestedErrors.some(isWorkspaceStorageNotReadyFailure)
|
|
72
|
+
) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
77
|
+
return /\bWORKSPACE_STORAGE_NOT_READY\b/.test(message);
|
|
78
|
+
}
|
|
79
|
+
|
|
62
80
|
export const PROVIDER_EXHAUSTED_CODE = 'PROVIDER_EXHAUSTED';
|
|
63
81
|
|
|
64
82
|
/**
|
|
@@ -331,7 +349,7 @@ export function normalizePlayRunFailure(error: unknown): PlayRunFailureDetails {
|
|
|
331
349
|
};
|
|
332
350
|
}
|
|
333
351
|
if (
|
|
334
|
-
error
|
|
352
|
+
isWorkspaceStorageNotReadyFailure(error) ||
|
|
335
353
|
/\bWORKSPACE_STORAGE_NOT_READY\b/.test(rawCause)
|
|
336
354
|
) {
|
|
337
355
|
return {
|
|
@@ -490,6 +490,25 @@ function isRetryableDaytonaInfrastructureFailure(error: unknown): boolean {
|
|
|
490
490
|
return DAYTONA_INFRASTRUCTURE_RETRY_PATTERN.test(message);
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
+
function isRetryableUnstartedDaytonaRunner(
|
|
494
|
+
error: unknown,
|
|
495
|
+
): error is DaytonaRunnerInitializationError {
|
|
496
|
+
if (!(error instanceof DaytonaRunnerInitializationError)) return false;
|
|
497
|
+
const diagnostic = error.startupDiagnostic;
|
|
498
|
+
// The sandbox runner cannot execute customer code until the worker observes
|
|
499
|
+
// its heartbeat, parks the scheduler attempt, and the gateway acknowledges
|
|
500
|
+
// that waiting state. If no heartbeat was observed and Daytona has no exit
|
|
501
|
+
// evidence, deleting this fenced sandbox and retrying once cannot duplicate
|
|
502
|
+
// customer side effects.
|
|
503
|
+
return (
|
|
504
|
+
diagnostic.commandFound &&
|
|
505
|
+
diagnostic.sessionFound &&
|
|
506
|
+
diagnostic.exitCode === null &&
|
|
507
|
+
diagnostic.exitCodeFile === null &&
|
|
508
|
+
!diagnostic.schedulerReadinessObserved
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
493
512
|
function prepareDaytonaExecution(
|
|
494
513
|
input: PlayRunnerPrepareInput,
|
|
495
514
|
callbacks: Parameters<PlayRunnerBackend['execute']>[1],
|
|
@@ -930,14 +949,19 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
|
|
|
930
949
|
onCancel();
|
|
931
950
|
throw new Error(DAYTONA_CANCELLED_ERROR);
|
|
932
951
|
}
|
|
952
|
+
const retryReason = isRetryableUnstartedDaytonaRunner(error)
|
|
953
|
+
? 'runner_startup_not_live'
|
|
954
|
+
: isRetryableDaytonaInfrastructureFailure(error)
|
|
955
|
+
? 'daytona_infrastructure'
|
|
956
|
+
: null;
|
|
933
957
|
if (
|
|
934
958
|
executionAttempt < DAYTONA_INFRASTRUCTURE_MAX_ATTEMPTS &&
|
|
935
|
-
|
|
959
|
+
retryReason
|
|
936
960
|
) {
|
|
937
961
|
emitDaytonaStage(callbacks, config.context, 'execute:retry', {
|
|
938
962
|
sandboxId: sandboxForAttempt?.id ?? null,
|
|
939
963
|
attempt: executionAttempt + 1,
|
|
940
|
-
reason:
|
|
964
|
+
reason: retryReason,
|
|
941
965
|
error: error instanceof Error ? error.message : String(error),
|
|
942
966
|
elapsedMs: Date.now() - startedAt,
|
|
943
967
|
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// One-line definitions for the tool categories surfaced by `deepline tools list`.
|
|
2
|
+
//
|
|
3
|
+
// Tool categories are free-form strings that each provider tool declares in the
|
|
4
|
+
// generated catalog (see `src/lib/integrations/**`), not a single closed enum.
|
|
5
|
+
// The canonical set of well-known category slugs lives next to this file in
|
|
6
|
+
// `DEEPLINE_TOOL_CATEGORIES` (bootstrap-routes.ts) and in the richer
|
|
7
|
+
// `IntegrationCatalogTag` enum (src/lib/integrations/catalog-tags.ts). This map
|
|
8
|
+
// MUST track the categories that actually appear on live tools. The CLI derives
|
|
9
|
+
// the category enumeration from the live catalog, so a new category slug shows
|
|
10
|
+
// up automatically; only its human-readable definition comes from here. When a
|
|
11
|
+
// category has no entry the CLI renders it without a definition (never invents
|
|
12
|
+
// one), which is the loud signal to add it here.
|
|
13
|
+
//
|
|
14
|
+
// Keep each definition to a single, plain sentence fragment.
|
|
15
|
+
|
|
16
|
+
export const TOOL_CATEGORY_DESCRIPTIONS: Readonly<Record<string, string>> = {
|
|
17
|
+
company_search: 'Find companies matching firmographic, ad, or web criteria.',
|
|
18
|
+
people_search: 'Find people matching role, company, or persona criteria.',
|
|
19
|
+
people_enrich:
|
|
20
|
+
'Enrich a known person with contact, social, and profile data.',
|
|
21
|
+
company_enrich: 'Enrich a known company with firmographic and account data.',
|
|
22
|
+
email_finder: 'Find work or personal email addresses for a person.',
|
|
23
|
+
email_verify: 'Validate email deliverability and catch-all status.',
|
|
24
|
+
phone_finder: 'Find mobile or direct phone numbers for a person.',
|
|
25
|
+
phone_verify: 'Validate phone-number reachability and line type.',
|
|
26
|
+
research:
|
|
27
|
+
'Research accounts, people, news, and signals for context and scoring.',
|
|
28
|
+
autocomplete: 'Resolve names and entities to canonical catalog records.',
|
|
29
|
+
automation:
|
|
30
|
+
'Kick off provider-side jobs, exports, and asynchronous workflows.',
|
|
31
|
+
outbound_tools:
|
|
32
|
+
'Run outbound sequencing, deliverability, and campaign operations.',
|
|
33
|
+
admin:
|
|
34
|
+
'Provider-side status, metadata, and account operations behind other tools.',
|
|
35
|
+
smb: 'Look up small-business listings, local records, and public filings.',
|
|
36
|
+
identity_resolution:
|
|
37
|
+
'Match a partial identity to a single resolved person or company.',
|
|
38
|
+
reverse_lookup: 'Resolve an email, phone, or profile back to a person.',
|
|
39
|
+
enrichment: 'General-purpose record enrichment across people and companies.',
|
|
40
|
+
batch: 'Run an enrichment or search operation over many rows at once.',
|
|
41
|
+
premium: 'Higher-cost tools with premium provider coverage.',
|
|
42
|
+
free: 'Free tools that do not spend Deepline credits.',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* One-line definition for a tool category slug, or null when none is declared.
|
|
47
|
+
* Never fabricates a definition for unknown slugs.
|
|
48
|
+
*/
|
|
49
|
+
export function describeToolCategory(category: string): string | null {
|
|
50
|
+
return TOOL_CATEGORY_DESCRIPTIONS[category] ?? null;
|
|
51
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -716,7 +716,7 @@ var SDK_RELEASE = {
|
|
|
716
716
|
// Deepline-native radars. Older clients must update before discovering,
|
|
717
717
|
// checking, or deploying an unlaunched monitor integration.
|
|
718
718
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
719
|
-
version: "0.1.
|
|
719
|
+
version: "0.1.263",
|
|
720
720
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
721
721
|
supportPolicy: {
|
|
722
722
|
minimumSupported: "0.1.53",
|
|
@@ -12465,13 +12465,21 @@ function getStatusFromLiveEvent(event) {
|
|
|
12465
12465
|
const payload = getEventPayload(event);
|
|
12466
12466
|
return playStatusValue(payload.status) ?? playStatusValue(getRunRecordFromPackage(payload)?.status);
|
|
12467
12467
|
}
|
|
12468
|
+
function getWaitKindFromLiveEvent(event) {
|
|
12469
|
+
const payload = getEventPayload(event);
|
|
12470
|
+
const progress = payload.progress && typeof payload.progress === "object" ? payload.progress : null;
|
|
12471
|
+
const waitKind = payload.waitKind ?? progress?.waitKind;
|
|
12472
|
+
return typeof waitKind === "string" && waitKind.trim() ? waitKind.trim() : null;
|
|
12473
|
+
}
|
|
12468
12474
|
function writePlayWaitingHint(input2) {
|
|
12469
12475
|
if (getStatusFromLiveEvent(input2.event) !== "waiting") return;
|
|
12470
12476
|
const runId = getRunIdFromLiveEvent(input2.event);
|
|
12471
12477
|
if (!runId || input2.state.waitingRunId === runId) return;
|
|
12472
12478
|
input2.state.waitingRunId = runId;
|
|
12479
|
+
const waitKind = getWaitKindFromLiveEvent(input2.event);
|
|
12480
|
+
const message = waitKind === "integration_event" || waitKind === "integration_event_batch" ? "is waiting for an external event." : waitKind === "sleep" ? "is waiting for its scheduled resume." : waitKind === "detached_runner" ? "is executing in the runtime." : "is waiting on a durable runtime boundary.";
|
|
12473
12481
|
input2.progress.writeLine(
|
|
12474
|
-
`[play waiting] ${runId}
|
|
12482
|
+
`[play waiting] ${runId} ${message} The command will continue watching; inspect it with 'deepline runs get ${runId} --full --json'.`
|
|
12475
12483
|
);
|
|
12476
12484
|
}
|
|
12477
12485
|
function getFinalStatusFromLiveEvent(event) {
|
|
@@ -12734,6 +12742,9 @@ function getRunningHeartbeatLine(input2) {
|
|
|
12734
12742
|
return `queued ${target}: waiting for worker capacity`;
|
|
12735
12743
|
}
|
|
12736
12744
|
if (status === "waiting") {
|
|
12745
|
+
if (getWaitKindFromLiveEvent(input2.event) === "detached_runner") {
|
|
12746
|
+
return `running ${target}: executing in detached runtime`;
|
|
12747
|
+
}
|
|
12737
12748
|
return `waiting ${target}: waiting on external work`;
|
|
12738
12749
|
}
|
|
12739
12750
|
return `running ${target}: still processing`;
|
|
@@ -26616,6 +26627,33 @@ function extractSummaryFields(payload) {
|
|
|
26616
26627
|
return {};
|
|
26617
26628
|
}
|
|
26618
26629
|
|
|
26630
|
+
// ../shared_libs/plays/tool-category-descriptions.ts
|
|
26631
|
+
var TOOL_CATEGORY_DESCRIPTIONS = {
|
|
26632
|
+
company_search: "Find companies matching firmographic, ad, or web criteria.",
|
|
26633
|
+
people_search: "Find people matching role, company, or persona criteria.",
|
|
26634
|
+
people_enrich: "Enrich a known person with contact, social, and profile data.",
|
|
26635
|
+
company_enrich: "Enrich a known company with firmographic and account data.",
|
|
26636
|
+
email_finder: "Find work or personal email addresses for a person.",
|
|
26637
|
+
email_verify: "Validate email deliverability and catch-all status.",
|
|
26638
|
+
phone_finder: "Find mobile or direct phone numbers for a person.",
|
|
26639
|
+
phone_verify: "Validate phone-number reachability and line type.",
|
|
26640
|
+
research: "Research accounts, people, news, and signals for context and scoring.",
|
|
26641
|
+
autocomplete: "Resolve names and entities to canonical catalog records.",
|
|
26642
|
+
automation: "Kick off provider-side jobs, exports, and asynchronous workflows.",
|
|
26643
|
+
outbound_tools: "Run outbound sequencing, deliverability, and campaign operations.",
|
|
26644
|
+
admin: "Provider-side status, metadata, and account operations behind other tools.",
|
|
26645
|
+
smb: "Look up small-business listings, local records, and public filings.",
|
|
26646
|
+
identity_resolution: "Match a partial identity to a single resolved person or company.",
|
|
26647
|
+
reverse_lookup: "Resolve an email, phone, or profile back to a person.",
|
|
26648
|
+
enrichment: "General-purpose record enrichment across people and companies.",
|
|
26649
|
+
batch: "Run an enrichment or search operation over many rows at once.",
|
|
26650
|
+
premium: "Higher-cost tools with premium provider coverage.",
|
|
26651
|
+
free: "Free tools that do not spend Deepline credits."
|
|
26652
|
+
};
|
|
26653
|
+
function describeToolCategory(category) {
|
|
26654
|
+
return TOOL_CATEGORY_DESCRIPTIONS[category] ?? null;
|
|
26655
|
+
}
|
|
26656
|
+
|
|
26619
26657
|
// src/cli/commands/model-description.ts
|
|
26620
26658
|
function formatModelDescription(description) {
|
|
26621
26659
|
const lines = [];
|
|
@@ -26782,21 +26820,181 @@ function zeroMatchRender(emptyResult) {
|
|
|
26782
26820
|
]
|
|
26783
26821
|
};
|
|
26784
26822
|
}
|
|
26785
|
-
|
|
26823
|
+
function firstSentence(text) {
|
|
26824
|
+
const clean = (text ?? "").replace(/\s+/g, " ").trim();
|
|
26825
|
+
if (!clean) return "";
|
|
26826
|
+
const match = clean.match(/^.*?[.!?](?=\s|$)/);
|
|
26827
|
+
return (match ? match[0] : clean).trim();
|
|
26828
|
+
}
|
|
26829
|
+
function requiredInputIds(tool) {
|
|
26830
|
+
const inputSchema = recordField2(
|
|
26831
|
+
tool,
|
|
26832
|
+
"inputSchema",
|
|
26833
|
+
"input_schema"
|
|
26834
|
+
);
|
|
26835
|
+
return toolInputFieldsForDisplay(inputSchema).filter((field) => field.required === true).map((field) => String(field.name ?? "")).filter(Boolean);
|
|
26836
|
+
}
|
|
26837
|
+
function shortPricingHint(tool) {
|
|
26838
|
+
const pricing = recordField2(
|
|
26839
|
+
tool,
|
|
26840
|
+
"pricing"
|
|
26841
|
+
);
|
|
26842
|
+
const credits = numberField2(pricing, "creditsPerUnit", "credits_per_unit");
|
|
26843
|
+
const unit = stringField2(pricing, "unit");
|
|
26844
|
+
if (credits !== null) {
|
|
26845
|
+
return `${formatDecimal(credits)} cr/${unit || "unit"}`;
|
|
26846
|
+
}
|
|
26847
|
+
const summary = stringField2(pricing, "summary");
|
|
26848
|
+
if (summary) return summary;
|
|
26849
|
+
const displayText = stringField2(pricing, "displayText", "display_text");
|
|
26850
|
+
return displayText || null;
|
|
26851
|
+
}
|
|
26852
|
+
function aggregateCategorySummaries(tools) {
|
|
26853
|
+
const counts = /* @__PURE__ */ new Map();
|
|
26854
|
+
for (const tool of tools) {
|
|
26855
|
+
for (const category of tool.categories ?? []) {
|
|
26856
|
+
counts.set(category, (counts.get(category) ?? 0) + 1);
|
|
26857
|
+
}
|
|
26858
|
+
}
|
|
26859
|
+
return [...counts.entries()].map(([name, count]) => ({
|
|
26860
|
+
name,
|
|
26861
|
+
count,
|
|
26862
|
+
description: describeToolCategory(name)
|
|
26863
|
+
})).sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
|
|
26864
|
+
}
|
|
26865
|
+
function categoryEnumerationRender(summaries) {
|
|
26866
|
+
const nameWidth = summaries.reduce(
|
|
26867
|
+
(max, item) => Math.max(max, item.name.length),
|
|
26868
|
+
0
|
|
26869
|
+
);
|
|
26870
|
+
const countWidth = summaries.reduce(
|
|
26871
|
+
(max, item) => Math.max(max, String(item.count).length),
|
|
26872
|
+
0
|
|
26873
|
+
);
|
|
26874
|
+
return {
|
|
26875
|
+
sections: [
|
|
26876
|
+
{
|
|
26877
|
+
title: `${summaries.length} tool categories:`,
|
|
26878
|
+
lines: summaries.map((item) => {
|
|
26879
|
+
const name = item.name.padEnd(nameWidth);
|
|
26880
|
+
const count = String(item.count).padStart(countWidth);
|
|
26881
|
+
const definition = item.description ? ` - ${item.description}` : "";
|
|
26882
|
+
return `${name} ${count}${definition}`;
|
|
26883
|
+
})
|
|
26884
|
+
},
|
|
26885
|
+
{
|
|
26886
|
+
title: "next",
|
|
26887
|
+
lines: ["Pass a category: deepline tools list email_finder"]
|
|
26888
|
+
}
|
|
26889
|
+
]
|
|
26890
|
+
};
|
|
26891
|
+
}
|
|
26892
|
+
async function listToolCategories(emitJson, compact) {
|
|
26893
|
+
const client2 = new DeeplineClient();
|
|
26894
|
+
const rawTools = await client2.listTools({ compact });
|
|
26895
|
+
const items = rawTools.map(toListedTool);
|
|
26896
|
+
const summaries = aggregateCategorySummaries(rawTools);
|
|
26897
|
+
const outputItems = compact ? items.map(compactTool) : items;
|
|
26898
|
+
printCommandEnvelope(
|
|
26899
|
+
{
|
|
26900
|
+
tools: outputItems,
|
|
26901
|
+
count: outputItems.length,
|
|
26902
|
+
categories: summaries,
|
|
26903
|
+
filters: {
|
|
26904
|
+
categories: []
|
|
26905
|
+
},
|
|
26906
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26907
|
+
render: categoryEnumerationRender(summaries)
|
|
26908
|
+
},
|
|
26909
|
+
{ json: emitJson }
|
|
26910
|
+
);
|
|
26911
|
+
return 0;
|
|
26912
|
+
}
|
|
26913
|
+
function unknownCategoryError(category, summaries, emitJson) {
|
|
26914
|
+
const known = summaries.map((item) => item.name);
|
|
26915
|
+
const message = `Unknown tool category "${category}". Run \`deepline tools list\` to browse categories.`;
|
|
26916
|
+
if (emitJson) {
|
|
26917
|
+
printJson({
|
|
26918
|
+
ok: false,
|
|
26919
|
+
exitCode: 4,
|
|
26920
|
+
code: "TOOL_CATEGORY_NOT_FOUND",
|
|
26921
|
+
message,
|
|
26922
|
+
category,
|
|
26923
|
+
categories: summaries,
|
|
26924
|
+
next: "deepline tools list"
|
|
26925
|
+
});
|
|
26926
|
+
return 4;
|
|
26927
|
+
}
|
|
26928
|
+
const render = categoryEnumerationRender(summaries);
|
|
26929
|
+
console.error(message);
|
|
26930
|
+
console.error("");
|
|
26931
|
+
console.error(renderCommandEnvelopeText({ render }).trimEnd());
|
|
26932
|
+
console.error("");
|
|
26933
|
+
console.error(`Valid categories: ${known.join(", ")}`);
|
|
26934
|
+
return 4;
|
|
26935
|
+
}
|
|
26936
|
+
async function listToolsInCategory(category, emitJson) {
|
|
26937
|
+
const client2 = new DeeplineClient();
|
|
26938
|
+
const rawTools = await client2.listTools({
|
|
26939
|
+
categories: category,
|
|
26940
|
+
compact: false
|
|
26941
|
+
});
|
|
26942
|
+
const allTools = await client2.listTools({ compact: true });
|
|
26943
|
+
const summaries = aggregateCategorySummaries(allTools);
|
|
26944
|
+
if (!summaries.some((item) => item.name === category)) {
|
|
26945
|
+
return unknownCategoryError(category, summaries, emitJson);
|
|
26946
|
+
}
|
|
26947
|
+
const rows = rawTools.filter((tool) => tool.categories?.includes(category)).map((tool) => ({
|
|
26948
|
+
id: tool.toolId,
|
|
26949
|
+
provider: tool.provider,
|
|
26950
|
+
required: requiredInputIds(tool),
|
|
26951
|
+
pricing: shortPricingHint(tool),
|
|
26952
|
+
description: firstSentence(tool.description)
|
|
26953
|
+
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
26954
|
+
const idWidth = rows.reduce((max, row) => Math.max(max, row.id.length), 0);
|
|
26955
|
+
const render = {
|
|
26956
|
+
sections: [
|
|
26957
|
+
{
|
|
26958
|
+
title: `${rows.length} tools in ${category}:`,
|
|
26959
|
+
lines: rows.map((row) => {
|
|
26960
|
+
const id = row.id.padEnd(idWidth);
|
|
26961
|
+
const required = row.required.length ? `(${row.required.join(", ")})` : "(no required inputs)";
|
|
26962
|
+
const pricing = row.pricing ? ` [${row.pricing}]` : "";
|
|
26963
|
+
const description = row.description ? ` - ${row.description}` : "";
|
|
26964
|
+
return `${id} ${required}${pricing}${description}`;
|
|
26965
|
+
})
|
|
26966
|
+
},
|
|
26967
|
+
{
|
|
26968
|
+
title: "next",
|
|
26969
|
+
lines: [
|
|
26970
|
+
"Run `deepline tools describe <toolId>` for the full contract."
|
|
26971
|
+
]
|
|
26972
|
+
}
|
|
26973
|
+
]
|
|
26974
|
+
};
|
|
26975
|
+
printCommandEnvelope(
|
|
26976
|
+
{
|
|
26977
|
+
category,
|
|
26978
|
+
total: rows.length,
|
|
26979
|
+
tools: rows,
|
|
26980
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26981
|
+
render
|
|
26982
|
+
},
|
|
26983
|
+
{ json: emitJson }
|
|
26984
|
+
);
|
|
26985
|
+
return 0;
|
|
26986
|
+
}
|
|
26987
|
+
async function listToolsForCategoryFilter(requestedCategories, emitJson, compact) {
|
|
26786
26988
|
const client2 = new DeeplineClient();
|
|
26787
|
-
const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
|
|
26788
|
-
const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
|
|
26789
|
-
const compact = !args.includes("--full");
|
|
26790
|
-
const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
26791
26989
|
const items = (await client2.listTools({
|
|
26792
|
-
|
|
26990
|
+
categories: requestedCategories.join(","),
|
|
26793
26991
|
compact
|
|
26794
26992
|
})).map(toListedTool).filter(
|
|
26795
|
-
(item) => requestedCategories.
|
|
26993
|
+
(item) => requestedCategories.some(
|
|
26796
26994
|
(category) => item.categories.includes(category)
|
|
26797
26995
|
)
|
|
26798
26996
|
);
|
|
26799
|
-
const emptyResult = items.length === 0
|
|
26997
|
+
const emptyResult = items.length === 0 ? zeroMatchToolGuidance({ categories: requestedCategories }) : null;
|
|
26800
26998
|
const render = {
|
|
26801
26999
|
sections: emptyResult ? zeroMatchRender(emptyResult).sections : [
|
|
26802
27000
|
{
|
|
@@ -26827,10 +27025,41 @@ async function listTools(args) {
|
|
|
26827
27025
|
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26828
27026
|
render
|
|
26829
27027
|
},
|
|
26830
|
-
{ json:
|
|
27028
|
+
{ json: emitJson }
|
|
26831
27029
|
);
|
|
26832
27030
|
return 0;
|
|
26833
27031
|
}
|
|
27032
|
+
async function listTools(category, options = {}) {
|
|
27033
|
+
const positional = category?.trim() ?? "";
|
|
27034
|
+
const flagCategories = (options.categories ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
27035
|
+
const compact = options.compact !== false;
|
|
27036
|
+
const emitJson = options.json === true || shouldEmitJson();
|
|
27037
|
+
if (positional && flagCategories.length > 0) {
|
|
27038
|
+
const flagIsSameSingle = flagCategories.length === 1 && flagCategories[0] === positional;
|
|
27039
|
+
if (!flagIsSameSingle) {
|
|
27040
|
+
const message = `Category "${positional}" and --categories ${flagCategories.join(",")} disagree. Pass one: deepline tools list ${positional}`;
|
|
27041
|
+
if (emitJson) {
|
|
27042
|
+
printJson({
|
|
27043
|
+
ok: false,
|
|
27044
|
+
exitCode: 2,
|
|
27045
|
+
code: "TOOL_LIST_CATEGORY_CONFLICT",
|
|
27046
|
+
message,
|
|
27047
|
+
next: `deepline tools list ${positional}`
|
|
27048
|
+
});
|
|
27049
|
+
} else {
|
|
27050
|
+
console.error(message);
|
|
27051
|
+
}
|
|
27052
|
+
return 2;
|
|
27053
|
+
}
|
|
27054
|
+
}
|
|
27055
|
+
if (positional) {
|
|
27056
|
+
return listToolsInCategory(positional, emitJson);
|
|
27057
|
+
}
|
|
27058
|
+
if (flagCategories.length > 0) {
|
|
27059
|
+
return listToolsForCategoryFilter(flagCategories, emitJson, compact);
|
|
27060
|
+
}
|
|
27061
|
+
return listToolCategories(emitJson, compact);
|
|
27062
|
+
}
|
|
26834
27063
|
async function searchTools(queryInput, options = {}) {
|
|
26835
27064
|
const query = queryInput?.trim() ?? "";
|
|
26836
27065
|
const hasStructuredSearch = Boolean(
|
|
@@ -27029,27 +27258,37 @@ Output:
|
|
|
27029
27258
|
Use execute to run a tool.
|
|
27030
27259
|
`
|
|
27031
27260
|
);
|
|
27032
|
-
tools.command("list").description("
|
|
27261
|
+
tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
|
|
27033
27262
|
"after",
|
|
27034
27263
|
`
|
|
27035
27264
|
Notes:
|
|
27036
|
-
|
|
27037
|
-
|
|
27265
|
+
Bare \`tools list\` prints the category enumeration: one line per category with
|
|
27266
|
+
its tool count and definition. Pass a category to list every tool in it, one
|
|
27267
|
+
succinct row each (required inputs, Deepline pricing hint, first sentence).
|
|
27268
|
+
The listing is exhaustive and never truncated. Use search for ranked discovery
|
|
27269
|
+
by intent, aliases, descriptions, and schema fields.
|
|
27270
|
+
|
|
27271
|
+
--categories is a back-compat inventory filter. Passing it alone returns the
|
|
27272
|
+
legacy flat inventory envelope (one row per tool). The positional category is
|
|
27273
|
+
the newer exhaustive per-category view. If both are given they must name the
|
|
27274
|
+
same category (the positional view wins); otherwise it is a usage error.
|
|
27038
27275
|
|
|
27039
27276
|
Examples:
|
|
27040
27277
|
deepline tools list
|
|
27278
|
+
deepline tools list email_finder
|
|
27279
|
+
deepline tools list email_finder --json
|
|
27041
27280
|
deepline tools list --categories email_finder --json
|
|
27042
27281
|
deepline tools search email --json
|
|
27043
27282
|
`
|
|
27044
27283
|
).option(
|
|
27045
27284
|
"--categories <categories>",
|
|
27046
|
-
"Comma-separated categories
|
|
27047
|
-
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
27048
|
-
process.exitCode = await listTools(
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27285
|
+
"Comma-separated categories filter (back-compat alias for the positional)"
|
|
27286
|
+
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (category, options) => {
|
|
27287
|
+
process.exitCode = await listTools(category, {
|
|
27288
|
+
categories: typeof options.categories === "string" ? options.categories : void 0,
|
|
27289
|
+
compact: options.compact !== false,
|
|
27290
|
+
json: Boolean(options.json)
|
|
27291
|
+
});
|
|
27053
27292
|
});
|
|
27054
27293
|
const addToolSearchCommand = (command) => command.description(
|
|
27055
27294
|
"Search available tools by intent query or structured filters."
|
package/dist/cli/index.mjs
CHANGED
|
@@ -701,7 +701,7 @@ var SDK_RELEASE = {
|
|
|
701
701
|
// Deepline-native radars. Older clients must update before discovering,
|
|
702
702
|
// checking, or deploying an unlaunched monitor integration.
|
|
703
703
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
704
|
-
version: "0.1.
|
|
704
|
+
version: "0.1.263",
|
|
705
705
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
706
706
|
supportPolicy: {
|
|
707
707
|
minimumSupported: "0.1.53",
|
|
@@ -12494,13 +12494,21 @@ function getStatusFromLiveEvent(event) {
|
|
|
12494
12494
|
const payload = getEventPayload(event);
|
|
12495
12495
|
return playStatusValue(payload.status) ?? playStatusValue(getRunRecordFromPackage(payload)?.status);
|
|
12496
12496
|
}
|
|
12497
|
+
function getWaitKindFromLiveEvent(event) {
|
|
12498
|
+
const payload = getEventPayload(event);
|
|
12499
|
+
const progress = payload.progress && typeof payload.progress === "object" ? payload.progress : null;
|
|
12500
|
+
const waitKind = payload.waitKind ?? progress?.waitKind;
|
|
12501
|
+
return typeof waitKind === "string" && waitKind.trim() ? waitKind.trim() : null;
|
|
12502
|
+
}
|
|
12497
12503
|
function writePlayWaitingHint(input2) {
|
|
12498
12504
|
if (getStatusFromLiveEvent(input2.event) !== "waiting") return;
|
|
12499
12505
|
const runId = getRunIdFromLiveEvent(input2.event);
|
|
12500
12506
|
if (!runId || input2.state.waitingRunId === runId) return;
|
|
12501
12507
|
input2.state.waitingRunId = runId;
|
|
12508
|
+
const waitKind = getWaitKindFromLiveEvent(input2.event);
|
|
12509
|
+
const message = waitKind === "integration_event" || waitKind === "integration_event_batch" ? "is waiting for an external event." : waitKind === "sleep" ? "is waiting for its scheduled resume." : waitKind === "detached_runner" ? "is executing in the runtime." : "is waiting on a durable runtime boundary.";
|
|
12502
12510
|
input2.progress.writeLine(
|
|
12503
|
-
`[play waiting] ${runId}
|
|
12511
|
+
`[play waiting] ${runId} ${message} The command will continue watching; inspect it with 'deepline runs get ${runId} --full --json'.`
|
|
12504
12512
|
);
|
|
12505
12513
|
}
|
|
12506
12514
|
function getFinalStatusFromLiveEvent(event) {
|
|
@@ -12763,6 +12771,9 @@ function getRunningHeartbeatLine(input2) {
|
|
|
12763
12771
|
return `queued ${target}: waiting for worker capacity`;
|
|
12764
12772
|
}
|
|
12765
12773
|
if (status === "waiting") {
|
|
12774
|
+
if (getWaitKindFromLiveEvent(input2.event) === "detached_runner") {
|
|
12775
|
+
return `running ${target}: executing in detached runtime`;
|
|
12776
|
+
}
|
|
12766
12777
|
return `waiting ${target}: waiting on external work`;
|
|
12767
12778
|
}
|
|
12768
12779
|
return `running ${target}: still processing`;
|
|
@@ -26664,6 +26675,33 @@ function extractSummaryFields(payload) {
|
|
|
26664
26675
|
return {};
|
|
26665
26676
|
}
|
|
26666
26677
|
|
|
26678
|
+
// ../shared_libs/plays/tool-category-descriptions.ts
|
|
26679
|
+
var TOOL_CATEGORY_DESCRIPTIONS = {
|
|
26680
|
+
company_search: "Find companies matching firmographic, ad, or web criteria.",
|
|
26681
|
+
people_search: "Find people matching role, company, or persona criteria.",
|
|
26682
|
+
people_enrich: "Enrich a known person with contact, social, and profile data.",
|
|
26683
|
+
company_enrich: "Enrich a known company with firmographic and account data.",
|
|
26684
|
+
email_finder: "Find work or personal email addresses for a person.",
|
|
26685
|
+
email_verify: "Validate email deliverability and catch-all status.",
|
|
26686
|
+
phone_finder: "Find mobile or direct phone numbers for a person.",
|
|
26687
|
+
phone_verify: "Validate phone-number reachability and line type.",
|
|
26688
|
+
research: "Research accounts, people, news, and signals for context and scoring.",
|
|
26689
|
+
autocomplete: "Resolve names and entities to canonical catalog records.",
|
|
26690
|
+
automation: "Kick off provider-side jobs, exports, and asynchronous workflows.",
|
|
26691
|
+
outbound_tools: "Run outbound sequencing, deliverability, and campaign operations.",
|
|
26692
|
+
admin: "Provider-side status, metadata, and account operations behind other tools.",
|
|
26693
|
+
smb: "Look up small-business listings, local records, and public filings.",
|
|
26694
|
+
identity_resolution: "Match a partial identity to a single resolved person or company.",
|
|
26695
|
+
reverse_lookup: "Resolve an email, phone, or profile back to a person.",
|
|
26696
|
+
enrichment: "General-purpose record enrichment across people and companies.",
|
|
26697
|
+
batch: "Run an enrichment or search operation over many rows at once.",
|
|
26698
|
+
premium: "Higher-cost tools with premium provider coverage.",
|
|
26699
|
+
free: "Free tools that do not spend Deepline credits."
|
|
26700
|
+
};
|
|
26701
|
+
function describeToolCategory(category) {
|
|
26702
|
+
return TOOL_CATEGORY_DESCRIPTIONS[category] ?? null;
|
|
26703
|
+
}
|
|
26704
|
+
|
|
26667
26705
|
// src/cli/commands/model-description.ts
|
|
26668
26706
|
function formatModelDescription(description) {
|
|
26669
26707
|
const lines = [];
|
|
@@ -26830,21 +26868,181 @@ function zeroMatchRender(emptyResult) {
|
|
|
26830
26868
|
]
|
|
26831
26869
|
};
|
|
26832
26870
|
}
|
|
26833
|
-
|
|
26871
|
+
function firstSentence(text) {
|
|
26872
|
+
const clean = (text ?? "").replace(/\s+/g, " ").trim();
|
|
26873
|
+
if (!clean) return "";
|
|
26874
|
+
const match = clean.match(/^.*?[.!?](?=\s|$)/);
|
|
26875
|
+
return (match ? match[0] : clean).trim();
|
|
26876
|
+
}
|
|
26877
|
+
function requiredInputIds(tool) {
|
|
26878
|
+
const inputSchema = recordField2(
|
|
26879
|
+
tool,
|
|
26880
|
+
"inputSchema",
|
|
26881
|
+
"input_schema"
|
|
26882
|
+
);
|
|
26883
|
+
return toolInputFieldsForDisplay(inputSchema).filter((field) => field.required === true).map((field) => String(field.name ?? "")).filter(Boolean);
|
|
26884
|
+
}
|
|
26885
|
+
function shortPricingHint(tool) {
|
|
26886
|
+
const pricing = recordField2(
|
|
26887
|
+
tool,
|
|
26888
|
+
"pricing"
|
|
26889
|
+
);
|
|
26890
|
+
const credits = numberField2(pricing, "creditsPerUnit", "credits_per_unit");
|
|
26891
|
+
const unit = stringField2(pricing, "unit");
|
|
26892
|
+
if (credits !== null) {
|
|
26893
|
+
return `${formatDecimal(credits)} cr/${unit || "unit"}`;
|
|
26894
|
+
}
|
|
26895
|
+
const summary = stringField2(pricing, "summary");
|
|
26896
|
+
if (summary) return summary;
|
|
26897
|
+
const displayText = stringField2(pricing, "displayText", "display_text");
|
|
26898
|
+
return displayText || null;
|
|
26899
|
+
}
|
|
26900
|
+
function aggregateCategorySummaries(tools) {
|
|
26901
|
+
const counts = /* @__PURE__ */ new Map();
|
|
26902
|
+
for (const tool of tools) {
|
|
26903
|
+
for (const category of tool.categories ?? []) {
|
|
26904
|
+
counts.set(category, (counts.get(category) ?? 0) + 1);
|
|
26905
|
+
}
|
|
26906
|
+
}
|
|
26907
|
+
return [...counts.entries()].map(([name, count]) => ({
|
|
26908
|
+
name,
|
|
26909
|
+
count,
|
|
26910
|
+
description: describeToolCategory(name)
|
|
26911
|
+
})).sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
|
|
26912
|
+
}
|
|
26913
|
+
function categoryEnumerationRender(summaries) {
|
|
26914
|
+
const nameWidth = summaries.reduce(
|
|
26915
|
+
(max, item) => Math.max(max, item.name.length),
|
|
26916
|
+
0
|
|
26917
|
+
);
|
|
26918
|
+
const countWidth = summaries.reduce(
|
|
26919
|
+
(max, item) => Math.max(max, String(item.count).length),
|
|
26920
|
+
0
|
|
26921
|
+
);
|
|
26922
|
+
return {
|
|
26923
|
+
sections: [
|
|
26924
|
+
{
|
|
26925
|
+
title: `${summaries.length} tool categories:`,
|
|
26926
|
+
lines: summaries.map((item) => {
|
|
26927
|
+
const name = item.name.padEnd(nameWidth);
|
|
26928
|
+
const count = String(item.count).padStart(countWidth);
|
|
26929
|
+
const definition = item.description ? ` - ${item.description}` : "";
|
|
26930
|
+
return `${name} ${count}${definition}`;
|
|
26931
|
+
})
|
|
26932
|
+
},
|
|
26933
|
+
{
|
|
26934
|
+
title: "next",
|
|
26935
|
+
lines: ["Pass a category: deepline tools list email_finder"]
|
|
26936
|
+
}
|
|
26937
|
+
]
|
|
26938
|
+
};
|
|
26939
|
+
}
|
|
26940
|
+
async function listToolCategories(emitJson, compact) {
|
|
26941
|
+
const client2 = new DeeplineClient();
|
|
26942
|
+
const rawTools = await client2.listTools({ compact });
|
|
26943
|
+
const items = rawTools.map(toListedTool);
|
|
26944
|
+
const summaries = aggregateCategorySummaries(rawTools);
|
|
26945
|
+
const outputItems = compact ? items.map(compactTool) : items;
|
|
26946
|
+
printCommandEnvelope(
|
|
26947
|
+
{
|
|
26948
|
+
tools: outputItems,
|
|
26949
|
+
count: outputItems.length,
|
|
26950
|
+
categories: summaries,
|
|
26951
|
+
filters: {
|
|
26952
|
+
categories: []
|
|
26953
|
+
},
|
|
26954
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26955
|
+
render: categoryEnumerationRender(summaries)
|
|
26956
|
+
},
|
|
26957
|
+
{ json: emitJson }
|
|
26958
|
+
);
|
|
26959
|
+
return 0;
|
|
26960
|
+
}
|
|
26961
|
+
function unknownCategoryError(category, summaries, emitJson) {
|
|
26962
|
+
const known = summaries.map((item) => item.name);
|
|
26963
|
+
const message = `Unknown tool category "${category}". Run \`deepline tools list\` to browse categories.`;
|
|
26964
|
+
if (emitJson) {
|
|
26965
|
+
printJson({
|
|
26966
|
+
ok: false,
|
|
26967
|
+
exitCode: 4,
|
|
26968
|
+
code: "TOOL_CATEGORY_NOT_FOUND",
|
|
26969
|
+
message,
|
|
26970
|
+
category,
|
|
26971
|
+
categories: summaries,
|
|
26972
|
+
next: "deepline tools list"
|
|
26973
|
+
});
|
|
26974
|
+
return 4;
|
|
26975
|
+
}
|
|
26976
|
+
const render = categoryEnumerationRender(summaries);
|
|
26977
|
+
console.error(message);
|
|
26978
|
+
console.error("");
|
|
26979
|
+
console.error(renderCommandEnvelopeText({ render }).trimEnd());
|
|
26980
|
+
console.error("");
|
|
26981
|
+
console.error(`Valid categories: ${known.join(", ")}`);
|
|
26982
|
+
return 4;
|
|
26983
|
+
}
|
|
26984
|
+
async function listToolsInCategory(category, emitJson) {
|
|
26985
|
+
const client2 = new DeeplineClient();
|
|
26986
|
+
const rawTools = await client2.listTools({
|
|
26987
|
+
categories: category,
|
|
26988
|
+
compact: false
|
|
26989
|
+
});
|
|
26990
|
+
const allTools = await client2.listTools({ compact: true });
|
|
26991
|
+
const summaries = aggregateCategorySummaries(allTools);
|
|
26992
|
+
if (!summaries.some((item) => item.name === category)) {
|
|
26993
|
+
return unknownCategoryError(category, summaries, emitJson);
|
|
26994
|
+
}
|
|
26995
|
+
const rows = rawTools.filter((tool) => tool.categories?.includes(category)).map((tool) => ({
|
|
26996
|
+
id: tool.toolId,
|
|
26997
|
+
provider: tool.provider,
|
|
26998
|
+
required: requiredInputIds(tool),
|
|
26999
|
+
pricing: shortPricingHint(tool),
|
|
27000
|
+
description: firstSentence(tool.description)
|
|
27001
|
+
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
27002
|
+
const idWidth = rows.reduce((max, row) => Math.max(max, row.id.length), 0);
|
|
27003
|
+
const render = {
|
|
27004
|
+
sections: [
|
|
27005
|
+
{
|
|
27006
|
+
title: `${rows.length} tools in ${category}:`,
|
|
27007
|
+
lines: rows.map((row) => {
|
|
27008
|
+
const id = row.id.padEnd(idWidth);
|
|
27009
|
+
const required = row.required.length ? `(${row.required.join(", ")})` : "(no required inputs)";
|
|
27010
|
+
const pricing = row.pricing ? ` [${row.pricing}]` : "";
|
|
27011
|
+
const description = row.description ? ` - ${row.description}` : "";
|
|
27012
|
+
return `${id} ${required}${pricing}${description}`;
|
|
27013
|
+
})
|
|
27014
|
+
},
|
|
27015
|
+
{
|
|
27016
|
+
title: "next",
|
|
27017
|
+
lines: [
|
|
27018
|
+
"Run `deepline tools describe <toolId>` for the full contract."
|
|
27019
|
+
]
|
|
27020
|
+
}
|
|
27021
|
+
]
|
|
27022
|
+
};
|
|
27023
|
+
printCommandEnvelope(
|
|
27024
|
+
{
|
|
27025
|
+
category,
|
|
27026
|
+
total: rows.length,
|
|
27027
|
+
tools: rows,
|
|
27028
|
+
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
27029
|
+
render
|
|
27030
|
+
},
|
|
27031
|
+
{ json: emitJson }
|
|
27032
|
+
);
|
|
27033
|
+
return 0;
|
|
27034
|
+
}
|
|
27035
|
+
async function listToolsForCategoryFilter(requestedCategories, emitJson, compact) {
|
|
26834
27036
|
const client2 = new DeeplineClient();
|
|
26835
|
-
const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
|
|
26836
|
-
const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
|
|
26837
|
-
const compact = !args.includes("--full");
|
|
26838
|
-
const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
26839
27037
|
const items = (await client2.listTools({
|
|
26840
|
-
|
|
27038
|
+
categories: requestedCategories.join(","),
|
|
26841
27039
|
compact
|
|
26842
27040
|
})).map(toListedTool).filter(
|
|
26843
|
-
(item) => requestedCategories.
|
|
27041
|
+
(item) => requestedCategories.some(
|
|
26844
27042
|
(category) => item.categories.includes(category)
|
|
26845
27043
|
)
|
|
26846
27044
|
);
|
|
26847
|
-
const emptyResult = items.length === 0
|
|
27045
|
+
const emptyResult = items.length === 0 ? zeroMatchToolGuidance({ categories: requestedCategories }) : null;
|
|
26848
27046
|
const render = {
|
|
26849
27047
|
sections: emptyResult ? zeroMatchRender(emptyResult).sections : [
|
|
26850
27048
|
{
|
|
@@ -26875,10 +27073,41 @@ async function listTools(args) {
|
|
|
26875
27073
|
commandTemplates: TOOL_COMMAND_TEMPLATES,
|
|
26876
27074
|
render
|
|
26877
27075
|
},
|
|
26878
|
-
{ json:
|
|
27076
|
+
{ json: emitJson }
|
|
26879
27077
|
);
|
|
26880
27078
|
return 0;
|
|
26881
27079
|
}
|
|
27080
|
+
async function listTools(category, options = {}) {
|
|
27081
|
+
const positional = category?.trim() ?? "";
|
|
27082
|
+
const flagCategories = (options.categories ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
27083
|
+
const compact = options.compact !== false;
|
|
27084
|
+
const emitJson = options.json === true || shouldEmitJson();
|
|
27085
|
+
if (positional && flagCategories.length > 0) {
|
|
27086
|
+
const flagIsSameSingle = flagCategories.length === 1 && flagCategories[0] === positional;
|
|
27087
|
+
if (!flagIsSameSingle) {
|
|
27088
|
+
const message = `Category "${positional}" and --categories ${flagCategories.join(",")} disagree. Pass one: deepline tools list ${positional}`;
|
|
27089
|
+
if (emitJson) {
|
|
27090
|
+
printJson({
|
|
27091
|
+
ok: false,
|
|
27092
|
+
exitCode: 2,
|
|
27093
|
+
code: "TOOL_LIST_CATEGORY_CONFLICT",
|
|
27094
|
+
message,
|
|
27095
|
+
next: `deepline tools list ${positional}`
|
|
27096
|
+
});
|
|
27097
|
+
} else {
|
|
27098
|
+
console.error(message);
|
|
27099
|
+
}
|
|
27100
|
+
return 2;
|
|
27101
|
+
}
|
|
27102
|
+
}
|
|
27103
|
+
if (positional) {
|
|
27104
|
+
return listToolsInCategory(positional, emitJson);
|
|
27105
|
+
}
|
|
27106
|
+
if (flagCategories.length > 0) {
|
|
27107
|
+
return listToolsForCategoryFilter(flagCategories, emitJson, compact);
|
|
27108
|
+
}
|
|
27109
|
+
return listToolCategories(emitJson, compact);
|
|
27110
|
+
}
|
|
26882
27111
|
async function searchTools(queryInput, options = {}) {
|
|
26883
27112
|
const query = queryInput?.trim() ?? "";
|
|
26884
27113
|
const hasStructuredSearch = Boolean(
|
|
@@ -27077,27 +27306,37 @@ Output:
|
|
|
27077
27306
|
Use execute to run a tool.
|
|
27078
27307
|
`
|
|
27079
27308
|
);
|
|
27080
|
-
tools.command("list").description("
|
|
27309
|
+
tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
|
|
27081
27310
|
"after",
|
|
27082
27311
|
`
|
|
27083
27312
|
Notes:
|
|
27084
|
-
|
|
27085
|
-
|
|
27313
|
+
Bare \`tools list\` prints the category enumeration: one line per category with
|
|
27314
|
+
its tool count and definition. Pass a category to list every tool in it, one
|
|
27315
|
+
succinct row each (required inputs, Deepline pricing hint, first sentence).
|
|
27316
|
+
The listing is exhaustive and never truncated. Use search for ranked discovery
|
|
27317
|
+
by intent, aliases, descriptions, and schema fields.
|
|
27318
|
+
|
|
27319
|
+
--categories is a back-compat inventory filter. Passing it alone returns the
|
|
27320
|
+
legacy flat inventory envelope (one row per tool). The positional category is
|
|
27321
|
+
the newer exhaustive per-category view. If both are given they must name the
|
|
27322
|
+
same category (the positional view wins); otherwise it is a usage error.
|
|
27086
27323
|
|
|
27087
27324
|
Examples:
|
|
27088
27325
|
deepline tools list
|
|
27326
|
+
deepline tools list email_finder
|
|
27327
|
+
deepline tools list email_finder --json
|
|
27089
27328
|
deepline tools list --categories email_finder --json
|
|
27090
27329
|
deepline tools search email --json
|
|
27091
27330
|
`
|
|
27092
27331
|
).option(
|
|
27093
27332
|
"--categories <categories>",
|
|
27094
|
-
"Comma-separated categories
|
|
27095
|
-
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
27096
|
-
process.exitCode = await listTools(
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
|
|
27333
|
+
"Comma-separated categories filter (back-compat alias for the positional)"
|
|
27334
|
+
).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (category, options) => {
|
|
27335
|
+
process.exitCode = await listTools(category, {
|
|
27336
|
+
categories: typeof options.categories === "string" ? options.categories : void 0,
|
|
27337
|
+
compact: options.compact !== false,
|
|
27338
|
+
json: Boolean(options.json)
|
|
27339
|
+
});
|
|
27101
27340
|
});
|
|
27102
27341
|
const addToolSearchCommand = (command) => command.description(
|
|
27103
27342
|
"Search available tools by intent query or structured filters."
|
package/dist/index.js
CHANGED
|
@@ -435,7 +435,7 @@ var SDK_RELEASE = {
|
|
|
435
435
|
// Deepline-native radars. Older clients must update before discovering,
|
|
436
436
|
// checking, or deploying an unlaunched monitor integration.
|
|
437
437
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
438
|
-
version: "0.1.
|
|
438
|
+
version: "0.1.263",
|
|
439
439
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
440
440
|
supportPolicy: {
|
|
441
441
|
minimumSupported: "0.1.53",
|
package/dist/index.mjs
CHANGED
|
@@ -365,7 +365,7 @@ var SDK_RELEASE = {
|
|
|
365
365
|
// Deepline-native radars. Older clients must update before discovering,
|
|
366
366
|
// checking, or deploying an unlaunched monitor integration.
|
|
367
367
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
368
|
-
version: "0.1.
|
|
368
|
+
version: "0.1.263",
|
|
369
369
|
apiContract: "2026-07-native-monitor-launch-hard-cutover",
|
|
370
370
|
supportPolicy: {
|
|
371
371
|
minimumSupported: "0.1.53",
|