deepline 0.1.164 → 0.1.166

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.
@@ -35,9 +35,9 @@ export function isCoworkLikeSandbox(): boolean {
35
35
  const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
36
36
  const pluginRoot = Boolean(process.env.DEEPLINE_PLUGIN_ROOT?.trim());
37
37
  const home = process.env.HOME?.trim() || homedir();
38
- const sessionHome = home.startsWith('/sessions/');
38
+ const sessionHome = home === '/sessions' || home.startsWith('/sessions/');
39
39
  return (
40
- (pluginMode || pluginRoot) && (claudeRemote || projectDir || sessionHome)
40
+ claudeRemote || sessionHome || ((pluginMode || pluginRoot) && projectDir)
41
41
  );
42
42
  }
43
43
 
@@ -104,10 +104,10 @@ export const SDK_RELEASE = {
104
104
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
105
105
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
106
106
  // fields shipped in 0.1.153.
107
- version: '0.1.164',
107
+ version: '0.1.166',
108
108
  apiContract: '2026-06-dataset-handle-results-hard-cutover',
109
109
  supportPolicy: {
110
- latest: '0.1.164',
110
+ latest: '0.1.166',
111
111
  minimumSupported: '0.1.53',
112
112
  deprecatedBelow: '0.1.53',
113
113
  commandMinimumSupported: [
@@ -319,6 +319,15 @@ export interface ToolSearchResult {
319
319
  search_mode?: 'v1' | 'v2';
320
320
  /** Whether search fell back to category matching. */
321
321
  search_fallback_to_category?: boolean;
322
+ /** Explanation and next commands when filters/search succeed but match zero tools. */
323
+ emptyResult?: {
324
+ reason: string;
325
+ message: string;
326
+ suggestions: Array<{
327
+ label: string;
328
+ command: string;
329
+ }>;
330
+ };
322
331
  /** Hint explaining omitted play results when searching tools only. */
323
332
  omitted_plays_hint?: string;
324
333
  /** Copyable CLI command templates for follow-up discovery/execution. */
@@ -16,7 +16,6 @@ import type {
16
16
  import type { PlayBundleArtifact } from '../plays/artifact-types';
17
17
  import {
18
18
  augmentSheetContractWithDatasetFields,
19
- outputPhysicalSheetColumnNames,
20
19
  outputPhysicalSheetColumnProjections,
21
20
  physicalSheetColumnNames,
22
21
  physicalSheetColumnProjections,
@@ -1633,15 +1632,17 @@ function nextRuntimeSheetVersionExpression(
1633
1632
 
1634
1633
  function missingOutputCellSql(
1635
1634
  tableAlias: string,
1636
- outputPhysicalColumns: readonly string[],
1635
+ outputPhysicalColumns: readonly PhysicalSheetColumnProjection[],
1637
1636
  ): string {
1638
1637
  if (outputPhysicalColumns.length === 0) {
1639
1638
  return 'false';
1640
1639
  }
1641
1640
  return outputPhysicalColumns
1642
1641
  .map((column) => {
1643
- const quoted = `${tableAlias}.${quoteIdentifier(column)}`;
1644
- return `(${quoted} IS NULL OR ${quoted} = 'null'::jsonb OR ${quoted} = '""'::jsonb)`;
1642
+ const quoted = `${tableAlias}.${quoteIdentifier(column.sqlName)}`;
1643
+ const staleAt = `${tableAlias}._cell_meta -> ${quoteLiteral(column.fieldName)} -> 'staleAt'`;
1644
+ const staleAtMs = `(CASE WHEN jsonb_typeof(${staleAt}) = 'number' THEN (${staleAt})::text::double precision ELSE NULL END)`;
1645
+ return `(${quoted} IS NULL OR ${quoted} = 'null'::jsonb OR ${quoted} = '""'::jsonb OR (${staleAtMs} IS NOT NULL AND ${staleAtMs} <= extract(epoch from now()) * 1000))`;
1645
1646
  })
1646
1647
  .join(' OR ');
1647
1648
  }
@@ -2186,7 +2187,7 @@ async function prepareRuntimeSheetDatasetRows(
2186
2187
  normalizedTableNamespace: string;
2187
2188
  physicalInsertColumnsSql: string;
2188
2189
  physicalInsertValuesSql: string;
2189
- outputPhysicalColumns: string[];
2190
+ outputPhysicalColumns: PhysicalSheetColumnProjection[];
2190
2191
  },
2191
2192
  ): Promise<{ inserted: number; pendingKeys: string[] }> {
2192
2193
  let inserted = 0;
@@ -2363,7 +2364,6 @@ async function buildRuntimeSheetDatasetStartResult(
2363
2364
  timings?: RuntimeSheetTiming[];
2364
2365
  },
2365
2366
  ): Promise<PrepareRuntimeSheetResult> {
2366
- void input.pendingKeys;
2367
2367
  if (input.inserted === input.rowEntries.length) {
2368
2368
  const datasetFields = input.sheetContract.columns.flatMap((column) =>
2369
2369
  column.source === 'datasetColumn' && typeof column.field === 'string'
@@ -2390,47 +2390,55 @@ async function buildRuntimeSheetDatasetStartResult(
2390
2390
  };
2391
2391
  }
2392
2392
 
2393
+ const pendingKeys = new Set(input.pendingKeys);
2393
2394
  const startedAt = Date.now();
2394
2395
  await markRuntimeRowsPendingForRecompute(client, session, {
2395
- keys: input.rowEntries.map((entry) => entry.key),
2396
+ keys: [...pendingKeys],
2396
2397
  runId: input.runId,
2397
2398
  normalizedPlayName: input.normalizedPlayName,
2398
2399
  normalizedTableNamespace: input.normalizedTableNamespace,
2399
2400
  });
2400
- const persistedPendingRows = await readRuntimeRowsByKey(
2401
+ const persistedRows = await readRuntimeRowsByKey(
2401
2402
  client,
2402
2403
  session,
2403
2404
  input.rowEntries.map((entry) => entry.key),
2404
2405
  input.sheetContract,
2405
2406
  );
2406
2407
  const persistedRowsByKey = new Map(
2407
- persistedPendingRows.map((row) => [row.key, row.data]),
2408
+ persistedRows.map((row) => [row.key, row.data]),
2408
2409
  );
2409
- input.timings?.push({
2410
- phase: 'mark_rows_pending_for_recompute',
2411
- ms: Date.now() - startedAt,
2412
- rows: input.rowEntries.length,
2413
- });
2410
+ if (pendingKeys.size > 0) {
2411
+ input.timings?.push({
2412
+ phase: 'mark_rows_pending_for_recompute',
2413
+ ms: Date.now() - startedAt,
2414
+ rows: pendingKeys.size,
2415
+ });
2416
+ }
2417
+ const buildMergedRow = (entry: RuntimeDatasetRowEntry) => {
2418
+ const merged = { ...entry.row };
2419
+ for (const [field, value] of Object.entries(
2420
+ persistedRowsByKey.get(entry.key) ?? {},
2421
+ )) {
2422
+ if (
2423
+ value !== null ||
2424
+ !Object.prototype.hasOwnProperty.call(merged, field)
2425
+ ) {
2426
+ merged[field] = value;
2427
+ }
2428
+ }
2429
+ return {
2430
+ ...merged,
2431
+ __deeplineRowKey: entry.key,
2432
+ };
2433
+ };
2434
+ const pendingRows: Record<string, unknown>[] = [];
2435
+ for (const entry of input.rowEntries) {
2436
+ pendingRows.push(buildMergedRow(entry));
2437
+ }
2414
2438
  return {
2415
2439
  inserted: input.inserted,
2416
2440
  skipped: input.sourceRowsLength - input.rowEntries.length,
2417
- pendingRows: input.rowEntries.map((entry) => {
2418
- const merged = { ...entry.row };
2419
- for (const [field, value] of Object.entries(
2420
- persistedRowsByKey.get(entry.key) ?? {},
2421
- )) {
2422
- if (
2423
- value !== null ||
2424
- !Object.prototype.hasOwnProperty.call(merged, field)
2425
- ) {
2426
- merged[field] = value;
2427
- }
2428
- }
2429
- return {
2430
- ...merged,
2431
- __deeplineRowKey: entry.key,
2432
- };
2433
- }),
2441
+ pendingRows,
2434
2442
  completedRows: [],
2435
2443
  tableNamespace: input.tableNamespace,
2436
2444
  };
@@ -3289,7 +3297,7 @@ export async function startRuntimeSheetDataset(
3289
3297
  .map((column) => `payload -> ${quoteLiteral(column)}`)
3290
3298
  .join(', ')}`
3291
3299
  : '';
3292
- const outputPhysicalColumns = outputPhysicalSheetColumnNames(
3300
+ const outputPhysicalColumns = outputPhysicalSheetColumnProjections(
3293
3301
  input.sheetContract,
3294
3302
  );
3295
3303
  const normalizedPlayName = normalizePlayNameForSheet(playName);
@@ -4271,9 +4279,7 @@ export async function readRuntimeSheetDatasetRowKeys(
4271
4279
  ): Promise<{ keys: string[] }> {
4272
4280
  const keys = [
4273
4281
  ...new Set(
4274
- input.keys
4275
- .map((key) => key.trim())
4276
- .filter((key) => key.length > 0),
4282
+ input.keys.map((key) => key.trim()).filter((key) => key.length > 0),
4277
4283
  ),
4278
4284
  ];
4279
4285
  if (keys.length === 0) {
package/dist/cli/index.js CHANGED
@@ -622,10 +622,10 @@ var SDK_RELEASE = {
622
622
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
623
623
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
624
624
  // fields shipped in 0.1.153.
625
- version: "0.1.164",
625
+ version: "0.1.166",
626
626
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
627
627
  supportPolicy: {
628
- latest: "0.1.164",
628
+ latest: "0.1.166",
629
629
  minimumSupported: "0.1.53",
630
630
  deprecatedBelow: "0.1.53",
631
631
  commandMinimumSupported: [
@@ -749,8 +749,8 @@ function isCoworkLikeSandbox2() {
749
749
  const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
750
750
  const pluginRoot = Boolean(process.env.DEEPLINE_PLUGIN_ROOT?.trim());
751
751
  const home = process.env.HOME?.trim() || (0, import_node_os2.homedir)();
752
- const sessionHome = home.startsWith("/sessions/");
753
- return (pluginMode || pluginRoot) && (claudeRemote || projectDir || sessionHome);
752
+ const sessionHome = home === "/sessions" || home.startsWith("/sessions/");
753
+ return claudeRemote || sessionHome || (pluginMode || pluginRoot) && projectDir;
754
754
  }
755
755
  function detectAgentRuntime(options = {}) {
756
756
  const explicit = normalizeAgentRuntime(process.env.DEEPLINE_AGENT_RUNTIME);
@@ -4419,10 +4419,11 @@ function sleep3(ms) {
4419
4419
  return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
4420
4420
  }
4421
4421
  function collectLocalEnvInfo() {
4422
+ const homeDir2 = process.env.HOME?.trim() || (0, import_node_os5.homedir)();
4422
4423
  const info = {
4423
4424
  os: `${process.platform} ${process.arch}`,
4424
4425
  node_version: process.version,
4425
- home_dir: (0, import_node_os5.homedir)(),
4426
+ home_dir: homeDir2,
4426
4427
  agent_runtime: detectAgentRuntime()
4427
4428
  };
4428
4429
  const env = process.env;
@@ -4442,7 +4443,7 @@ function collectLocalEnvInfo() {
4442
4443
  if (env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim()) {
4443
4444
  info.deepline_plugin_skills_dir_present = "true";
4444
4445
  }
4445
- if (info.home_dir.startsWith("/sessions/")) {
4446
+ if (info.home_dir === "/sessions" || info.home_dir.startsWith("/sessions/")) {
4446
4447
  info.home_scope = "sessions";
4447
4448
  }
4448
4449
  return info;
@@ -4707,6 +4708,27 @@ function clearPendingClaimToken(baseUrl) {
4707
4708
  } catch {
4708
4709
  }
4709
4710
  }
4711
+ function parseRegisterWaitMode(args) {
4712
+ let mode = "auto";
4713
+ for (let i = 0; i < args.length; i++) {
4714
+ if (args[i] === "--no-wait") {
4715
+ mode = "no";
4716
+ } else if (args[i] === "--wait" && args[i + 1]) {
4717
+ const value = args[++i].trim().toLowerCase();
4718
+ if (value === "auto" || value === "yes" || value === "no") {
4719
+ mode = value;
4720
+ } else {
4721
+ throw new Error("--wait must be one of: auto, yes, no");
4722
+ }
4723
+ }
4724
+ }
4725
+ return mode;
4726
+ }
4727
+ function shouldWaitForRegisterClaim(mode) {
4728
+ if (mode === "yes") return true;
4729
+ if (mode === "no") return false;
4730
+ return detectAgentRuntime() !== "claude_cowork";
4731
+ }
4710
4732
  function saveEnvValues(values, baseUrl) {
4711
4733
  const filtered = {
4712
4734
  ...values[HOST_URL_ENV] ? { [HOST_URL_ENV]: values[HOST_URL_ENV] } : {},
@@ -4835,11 +4857,16 @@ async function handleRegister(args) {
4835
4857
  const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
4836
4858
  let orgName = "";
4837
4859
  let agentName = "";
4838
- let noWait = false;
4860
+ let waitMode;
4861
+ try {
4862
+ waitMode = parseRegisterWaitMode(args);
4863
+ } catch (error) {
4864
+ console.error(error instanceof Error ? error.message : String(error));
4865
+ return 2;
4866
+ }
4839
4867
  for (let i = 0; i < args.length; i++) {
4840
4868
  if (args[i] === "--org-name" && args[i + 1]) orgName = args[++i];
4841
4869
  else if (args[i] === "--agent-name" && args[i + 1]) agentName = args[++i];
4842
- else if (args[i] === "--no-wait") noWait = true;
4843
4870
  }
4844
4871
  if (!agentName) {
4845
4872
  try {
@@ -4881,7 +4908,7 @@ async function handleRegister(args) {
4881
4908
  if (data.cli_message) {
4882
4909
  console.log(String(data.cli_message));
4883
4910
  }
4884
- if (noWait) return EXIT_OK;
4911
+ if (!shouldWaitForRegisterClaim(waitMode)) return EXIT_OK;
4885
4912
  if (!claimToken) {
4886
4913
  console.error("Missing claim token from register response.");
4887
4914
  return EXIT_SERVER;
@@ -4949,7 +4976,7 @@ async function handleWait(args) {
4949
4976
  console.log("Already connected.");
4950
4977
  return EXIT_OK;
4951
4978
  }
4952
- console.error("No pending approval. Run: deepline auth register --no-wait");
4979
+ console.error("No pending approval. Run: deepline auth register --wait no");
4953
4980
  return EXIT_AUTH;
4954
4981
  }
4955
4982
  const deadline = Date.now() + timeoutSeconds * 1e3;
@@ -5059,7 +5086,7 @@ async function handleStatus(args) {
5059
5086
  ...hostStatusPayload ?? { host: baseUrl },
5060
5087
  status: "not connected",
5061
5088
  connected: false,
5062
- next: "deepline auth register --no-wait && deepline auth wait",
5089
+ next: "deepline auth register --wait auto && deepline auth wait",
5063
5090
  render: {
5064
5091
  sections: [
5065
5092
  {
@@ -5068,7 +5095,10 @@ async function handleStatus(args) {
5068
5095
  }
5069
5096
  ],
5070
5097
  actions: [
5071
- { label: "Register", command: "deepline auth register --no-wait" },
5098
+ {
5099
+ label: "Register",
5100
+ command: "deepline auth register --wait auto"
5101
+ },
5072
5102
  { label: "Wait", command: "deepline auth wait" }
5073
5103
  ]
5074
5104
  }
@@ -5092,7 +5122,7 @@ async function handleStatus(args) {
5092
5122
  ...hostStatusPayload ?? { host: baseUrl },
5093
5123
  status: "unauthorized",
5094
5124
  connected: false,
5095
- next: "deepline auth register --no-wait && deepline auth wait",
5125
+ next: "deepline auth register --wait auto && deepline auth wait",
5096
5126
  render: {
5097
5127
  sections: [
5098
5128
  {
@@ -5101,7 +5131,10 @@ async function handleStatus(args) {
5101
5131
  }
5102
5132
  ],
5103
5133
  actions: [
5104
- { label: "Register", command: "deepline auth register --no-wait" },
5134
+ {
5135
+ label: "Register",
5136
+ command: "deepline auth register --wait auto"
5137
+ },
5105
5138
  { label: "Wait", command: "deepline auth wait" }
5106
5139
  ]
5107
5140
  }
@@ -5180,14 +5213,15 @@ function registerAuthCommands(program) {
5180
5213
  `
5181
5214
  Common commands:
5182
5215
  deepline auth register
5183
- deepline auth register --no-wait
5216
+ deepline auth register --wait no
5184
5217
  deepline auth wait --timeout 300
5185
5218
  deepline auth status
5186
5219
  deepline auth status --json
5187
5220
 
5188
5221
  Notes:
5189
- Registration opens a browser approval page by default. Use --no-wait in CI
5190
- or agent runs, then finish with deepline auth wait.
5222
+ Registration uses --wait auto by default: it waits locally and returns after
5223
+ opening the approval page in Cowork. Use --wait no in CI or agent runs, then
5224
+ finish with deepline auth wait.
5191
5225
  Auth status shows the target host and active workspace without printing secrets.
5192
5226
  `
5193
5227
  );
@@ -5197,26 +5231,27 @@ Notes:
5197
5231
  "after",
5198
5232
  `
5199
5233
  Notes:
5200
- Opens a browser approval page and waits for approval unless --no-wait is set.
5234
+ Opens a browser approval page. --wait auto waits locally and returns after
5235
+ opening the approval page in Cowork.
5201
5236
  The saved API key is scoped to the selected workspace and host.
5202
5237
 
5203
5238
  Examples:
5204
5239
  deepline auth register
5205
5240
  deepline auth register --org-name Acme --agent-name local-cli
5206
- deepline auth register --no-wait
5241
+ deepline auth register --wait no
5207
5242
  `
5208
- ).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--no-wait", "Return immediately after opening the approval page").action(async (options) => {
5243
+ ).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--wait <mode>", "Wait mode: auto, yes, or no", "auto").option("--no-wait", "Alias for --wait no").action(async (options) => {
5209
5244
  process.exitCode = await handleRegister([
5210
5245
  ...options.orgName ? ["--org-name", options.orgName] : [],
5211
5246
  ...options.agentName ? ["--agent-name", options.agentName] : [],
5212
- ...options.noWait || options.wait === false ? ["--no-wait"] : []
5247
+ ...options.noWait || options.wait === false ? ["--wait", "no"] : ["--wait", String(options.wait ?? "auto")]
5213
5248
  ]);
5214
5249
  });
5215
5250
  auth.command("wait").description("Wait for a pending browser approval and save the API key.").addHelpText(
5216
5251
  "after",
5217
5252
  `
5218
5253
  Notes:
5219
- Completes a previous deepline auth register --no-wait flow.
5254
+ Completes a previous deepline auth register --wait no flow.
5220
5255
  Saves the approved API key into the host auth file.
5221
5256
 
5222
5257
  Examples:
@@ -22039,6 +22074,63 @@ function matchesGrepQuery(value, query, mode) {
22039
22074
  if (mode === "any") return terms.some((term) => haystack.includes(term));
22040
22075
  return terms.every((term) => haystack.includes(term));
22041
22076
  }
22077
+ function shellCommandArg(value) {
22078
+ return `'${value.replace(/'/g, `'\\''`)}'`;
22079
+ }
22080
+ function zeroMatchToolGuidance(options) {
22081
+ const categories = options.categories ?? [];
22082
+ const query = options.query?.trim() ?? "";
22083
+ const filterText = [
22084
+ categories.length ? `categories=${categories.join(",")}` : null,
22085
+ query ? `grep=${query}` : null,
22086
+ query ? `grep_mode=${options.mode ?? "all"}` : null
22087
+ ].filter(Boolean).join(" ");
22088
+ const suggestions = [
22089
+ ...query ? [
22090
+ {
22091
+ label: "Use ranked semantic search for intent-style queries",
22092
+ command: `deepline tools search -- ${shellCommandArg(query)}`
22093
+ },
22094
+ ...options.mode === "all" ? [
22095
+ {
22096
+ label: "Relax literal grep from AND to OR matching",
22097
+ command: `deepline tools grep --mode any -- ${shellCommandArg(query)}`
22098
+ }
22099
+ ] : []
22100
+ ] : [],
22101
+ {
22102
+ label: "List the current atomic tool catalog",
22103
+ command: "deepline tools list --json"
22104
+ },
22105
+ ...query ? [
22106
+ {
22107
+ label: "Search composed Deepline plays separately",
22108
+ command: `deepline plays search -- ${shellCommandArg(query)}`
22109
+ }
22110
+ ] : []
22111
+ ];
22112
+ return {
22113
+ reason: "filters_matched_no_atomic_tools",
22114
+ message: `The tools catalog responded successfully, but no atomic provider tools matched ${filterText || "the current filters"}. This is a zero-match filter result, not a registry outage.`,
22115
+ suggestions
22116
+ };
22117
+ }
22118
+ function zeroMatchRender(emptyResult) {
22119
+ return {
22120
+ sections: [
22121
+ {
22122
+ title: "0 tools available:",
22123
+ lines: [emptyResult.message]
22124
+ },
22125
+ {
22126
+ title: "suggestions",
22127
+ lines: emptyResult.suggestions.map(
22128
+ (suggestion) => `${suggestion.label}: ${suggestion.command}`
22129
+ )
22130
+ }
22131
+ ]
22132
+ };
22133
+ }
22042
22134
  async function listTools(args) {
22043
22135
  const client2 = new DeeplineClient();
22044
22136
  const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
@@ -22053,8 +22145,9 @@ async function listTools(args) {
22053
22145
  (category) => item.categories.includes(category)
22054
22146
  )
22055
22147
  );
22148
+ const emptyResult = items.length === 0 && requestedCategories.length > 0 ? zeroMatchToolGuidance({ categories: requestedCategories }) : null;
22056
22149
  const render = {
22057
- sections: [
22150
+ sections: emptyResult ? zeroMatchRender(emptyResult).sections : [
22058
22151
  {
22059
22152
  title: `${items.length} tools available:`,
22060
22153
  lines: items.map((item) => {
@@ -22076,6 +22169,7 @@ async function listTools(args) {
22076
22169
  {
22077
22170
  tools: outputItems,
22078
22171
  count: outputItems.length,
22172
+ ...emptyResult ? { emptyResult } : {},
22079
22173
  filters: {
22080
22174
  categories: requestedCategories
22081
22175
  },
@@ -22147,6 +22241,11 @@ async function grepTools(queryInput, options = {}) {
22147
22241
  );
22148
22242
  const shouldCompact = options.compact || !options.json;
22149
22243
  const outputTools = shouldCompact ? tools.slice(0, 8).map(compactTool) : tools;
22244
+ const emptyResult = tools.length === 0 ? zeroMatchToolGuidance({
22245
+ categories: requestedCategories,
22246
+ query,
22247
+ mode
22248
+ }) : null;
22150
22249
  printCommandEnvelope(
22151
22250
  {
22152
22251
  tools: outputTools,
@@ -22159,6 +22258,10 @@ async function grepTools(queryInput, options = {}) {
22159
22258
  filters: {
22160
22259
  categories: requestedCategories
22161
22260
  },
22261
+ ...emptyResult ? {
22262
+ emptyResult,
22263
+ render: zeroMatchRender(emptyResult)
22264
+ } : {},
22162
22265
  commandTemplates: TOOL_COMMAND_TEMPLATES
22163
22266
  },
22164
22267
  { json: options.json || shouldEmitJson() }
@@ -24184,6 +24287,9 @@ function sdkNpmGlobalInstallCommand() {
24184
24287
  var CHECK_TIMEOUT_MS2 = 3e3;
24185
24288
  var attemptedSync = false;
24186
24289
  function shouldSkipSkillsSync() {
24290
+ if (detectAgentRuntime() === "claude_cowork") {
24291
+ return true;
24292
+ }
24187
24293
  const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
24188
24294
  return value === "1" || value === "true" || value === "yes" || value === "on";
24189
24295
  }
@@ -24409,6 +24515,7 @@ function runLegacySkillsCleanup() {
24409
24515
  for (const candidate of candidates) {
24410
24516
  const result = (0, import_node_child_process3.spawnSync)(candidate.command, candidate.args, {
24411
24517
  stdio: "ignore",
24518
+ env: process.env,
24412
24519
  shell: process.platform === "win32"
24413
24520
  });
24414
24521
  if (result.status === 0) return;
@@ -607,10 +607,10 @@ var SDK_RELEASE = {
607
607
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
608
608
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
609
609
  // fields shipped in 0.1.153.
610
- version: "0.1.164",
610
+ version: "0.1.166",
611
611
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
612
612
  supportPolicy: {
613
- latest: "0.1.164",
613
+ latest: "0.1.166",
614
614
  minimumSupported: "0.1.53",
615
615
  deprecatedBelow: "0.1.53",
616
616
  commandMinimumSupported: [
@@ -734,8 +734,8 @@ function isCoworkLikeSandbox2() {
734
734
  const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
735
735
  const pluginRoot = Boolean(process.env.DEEPLINE_PLUGIN_ROOT?.trim());
736
736
  const home = process.env.HOME?.trim() || homedir2();
737
- const sessionHome = home.startsWith("/sessions/");
738
- return (pluginMode || pluginRoot) && (claudeRemote || projectDir || sessionHome);
737
+ const sessionHome = home === "/sessions" || home.startsWith("/sessions/");
738
+ return claudeRemote || sessionHome || (pluginMode || pluginRoot) && projectDir;
739
739
  }
740
740
  function detectAgentRuntime(options = {}) {
741
741
  const explicit = normalizeAgentRuntime(process.env.DEEPLINE_AGENT_RUNTIME);
@@ -4416,10 +4416,11 @@ function sleep3(ms) {
4416
4416
  return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
4417
4417
  }
4418
4418
  function collectLocalEnvInfo() {
4419
+ const homeDir2 = process.env.HOME?.trim() || homedir5();
4419
4420
  const info = {
4420
4421
  os: `${process.platform} ${process.arch}`,
4421
4422
  node_version: process.version,
4422
- home_dir: homedir5(),
4423
+ home_dir: homeDir2,
4423
4424
  agent_runtime: detectAgentRuntime()
4424
4425
  };
4425
4426
  const env = process.env;
@@ -4439,7 +4440,7 @@ function collectLocalEnvInfo() {
4439
4440
  if (env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim()) {
4440
4441
  info.deepline_plugin_skills_dir_present = "true";
4441
4442
  }
4442
- if (info.home_dir.startsWith("/sessions/")) {
4443
+ if (info.home_dir === "/sessions" || info.home_dir.startsWith("/sessions/")) {
4443
4444
  info.home_scope = "sessions";
4444
4445
  }
4445
4446
  return info;
@@ -4704,6 +4705,27 @@ function clearPendingClaimToken(baseUrl) {
4704
4705
  } catch {
4705
4706
  }
4706
4707
  }
4708
+ function parseRegisterWaitMode(args) {
4709
+ let mode = "auto";
4710
+ for (let i = 0; i < args.length; i++) {
4711
+ if (args[i] === "--no-wait") {
4712
+ mode = "no";
4713
+ } else if (args[i] === "--wait" && args[i + 1]) {
4714
+ const value = args[++i].trim().toLowerCase();
4715
+ if (value === "auto" || value === "yes" || value === "no") {
4716
+ mode = value;
4717
+ } else {
4718
+ throw new Error("--wait must be one of: auto, yes, no");
4719
+ }
4720
+ }
4721
+ }
4722
+ return mode;
4723
+ }
4724
+ function shouldWaitForRegisterClaim(mode) {
4725
+ if (mode === "yes") return true;
4726
+ if (mode === "no") return false;
4727
+ return detectAgentRuntime() !== "claude_cowork";
4728
+ }
4707
4729
  function saveEnvValues(values, baseUrl) {
4708
4730
  const filtered = {
4709
4731
  ...values[HOST_URL_ENV] ? { [HOST_URL_ENV]: values[HOST_URL_ENV] } : {},
@@ -4832,11 +4854,16 @@ async function handleRegister(args) {
4832
4854
  const baseUrl = autoDetectBaseUrl().replace(/\/$/, "");
4833
4855
  let orgName = "";
4834
4856
  let agentName = "";
4835
- let noWait = false;
4857
+ let waitMode;
4858
+ try {
4859
+ waitMode = parseRegisterWaitMode(args);
4860
+ } catch (error) {
4861
+ console.error(error instanceof Error ? error.message : String(error));
4862
+ return 2;
4863
+ }
4836
4864
  for (let i = 0; i < args.length; i++) {
4837
4865
  if (args[i] === "--org-name" && args[i + 1]) orgName = args[++i];
4838
4866
  else if (args[i] === "--agent-name" && args[i + 1]) agentName = args[++i];
4839
- else if (args[i] === "--no-wait") noWait = true;
4840
4867
  }
4841
4868
  if (!agentName) {
4842
4869
  try {
@@ -4878,7 +4905,7 @@ async function handleRegister(args) {
4878
4905
  if (data.cli_message) {
4879
4906
  console.log(String(data.cli_message));
4880
4907
  }
4881
- if (noWait) return EXIT_OK;
4908
+ if (!shouldWaitForRegisterClaim(waitMode)) return EXIT_OK;
4882
4909
  if (!claimToken) {
4883
4910
  console.error("Missing claim token from register response.");
4884
4911
  return EXIT_SERVER;
@@ -4946,7 +4973,7 @@ async function handleWait(args) {
4946
4973
  console.log("Already connected.");
4947
4974
  return EXIT_OK;
4948
4975
  }
4949
- console.error("No pending approval. Run: deepline auth register --no-wait");
4976
+ console.error("No pending approval. Run: deepline auth register --wait no");
4950
4977
  return EXIT_AUTH;
4951
4978
  }
4952
4979
  const deadline = Date.now() + timeoutSeconds * 1e3;
@@ -5056,7 +5083,7 @@ async function handleStatus(args) {
5056
5083
  ...hostStatusPayload ?? { host: baseUrl },
5057
5084
  status: "not connected",
5058
5085
  connected: false,
5059
- next: "deepline auth register --no-wait && deepline auth wait",
5086
+ next: "deepline auth register --wait auto && deepline auth wait",
5060
5087
  render: {
5061
5088
  sections: [
5062
5089
  {
@@ -5065,7 +5092,10 @@ async function handleStatus(args) {
5065
5092
  }
5066
5093
  ],
5067
5094
  actions: [
5068
- { label: "Register", command: "deepline auth register --no-wait" },
5095
+ {
5096
+ label: "Register",
5097
+ command: "deepline auth register --wait auto"
5098
+ },
5069
5099
  { label: "Wait", command: "deepline auth wait" }
5070
5100
  ]
5071
5101
  }
@@ -5089,7 +5119,7 @@ async function handleStatus(args) {
5089
5119
  ...hostStatusPayload ?? { host: baseUrl },
5090
5120
  status: "unauthorized",
5091
5121
  connected: false,
5092
- next: "deepline auth register --no-wait && deepline auth wait",
5122
+ next: "deepline auth register --wait auto && deepline auth wait",
5093
5123
  render: {
5094
5124
  sections: [
5095
5125
  {
@@ -5098,7 +5128,10 @@ async function handleStatus(args) {
5098
5128
  }
5099
5129
  ],
5100
5130
  actions: [
5101
- { label: "Register", command: "deepline auth register --no-wait" },
5131
+ {
5132
+ label: "Register",
5133
+ command: "deepline auth register --wait auto"
5134
+ },
5102
5135
  { label: "Wait", command: "deepline auth wait" }
5103
5136
  ]
5104
5137
  }
@@ -5177,14 +5210,15 @@ function registerAuthCommands(program) {
5177
5210
  `
5178
5211
  Common commands:
5179
5212
  deepline auth register
5180
- deepline auth register --no-wait
5213
+ deepline auth register --wait no
5181
5214
  deepline auth wait --timeout 300
5182
5215
  deepline auth status
5183
5216
  deepline auth status --json
5184
5217
 
5185
5218
  Notes:
5186
- Registration opens a browser approval page by default. Use --no-wait in CI
5187
- or agent runs, then finish with deepline auth wait.
5219
+ Registration uses --wait auto by default: it waits locally and returns after
5220
+ opening the approval page in Cowork. Use --wait no in CI or agent runs, then
5221
+ finish with deepline auth wait.
5188
5222
  Auth status shows the target host and active workspace without printing secrets.
5189
5223
  `
5190
5224
  );
@@ -5194,26 +5228,27 @@ Notes:
5194
5228
  "after",
5195
5229
  `
5196
5230
  Notes:
5197
- Opens a browser approval page and waits for approval unless --no-wait is set.
5231
+ Opens a browser approval page. --wait auto waits locally and returns after
5232
+ opening the approval page in Cowork.
5198
5233
  The saved API key is scoped to the selected workspace and host.
5199
5234
 
5200
5235
  Examples:
5201
5236
  deepline auth register
5202
5237
  deepline auth register --org-name Acme --agent-name local-cli
5203
- deepline auth register --no-wait
5238
+ deepline auth register --wait no
5204
5239
  `
5205
- ).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--no-wait", "Return immediately after opening the approval page").action(async (options) => {
5240
+ ).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--wait <mode>", "Wait mode: auto, yes, or no", "auto").option("--no-wait", "Alias for --wait no").action(async (options) => {
5206
5241
  process.exitCode = await handleRegister([
5207
5242
  ...options.orgName ? ["--org-name", options.orgName] : [],
5208
5243
  ...options.agentName ? ["--agent-name", options.agentName] : [],
5209
- ...options.noWait || options.wait === false ? ["--no-wait"] : []
5244
+ ...options.noWait || options.wait === false ? ["--wait", "no"] : ["--wait", String(options.wait ?? "auto")]
5210
5245
  ]);
5211
5246
  });
5212
5247
  auth.command("wait").description("Wait for a pending browser approval and save the API key.").addHelpText(
5213
5248
  "after",
5214
5249
  `
5215
5250
  Notes:
5216
- Completes a previous deepline auth register --no-wait flow.
5251
+ Completes a previous deepline auth register --wait no flow.
5217
5252
  Saves the approved API key into the host auth file.
5218
5253
 
5219
5254
  Examples:
@@ -22085,6 +22120,63 @@ function matchesGrepQuery(value, query, mode) {
22085
22120
  if (mode === "any") return terms.some((term) => haystack.includes(term));
22086
22121
  return terms.every((term) => haystack.includes(term));
22087
22122
  }
22123
+ function shellCommandArg(value) {
22124
+ return `'${value.replace(/'/g, `'\\''`)}'`;
22125
+ }
22126
+ function zeroMatchToolGuidance(options) {
22127
+ const categories = options.categories ?? [];
22128
+ const query = options.query?.trim() ?? "";
22129
+ const filterText = [
22130
+ categories.length ? `categories=${categories.join(",")}` : null,
22131
+ query ? `grep=${query}` : null,
22132
+ query ? `grep_mode=${options.mode ?? "all"}` : null
22133
+ ].filter(Boolean).join(" ");
22134
+ const suggestions = [
22135
+ ...query ? [
22136
+ {
22137
+ label: "Use ranked semantic search for intent-style queries",
22138
+ command: `deepline tools search -- ${shellCommandArg(query)}`
22139
+ },
22140
+ ...options.mode === "all" ? [
22141
+ {
22142
+ label: "Relax literal grep from AND to OR matching",
22143
+ command: `deepline tools grep --mode any -- ${shellCommandArg(query)}`
22144
+ }
22145
+ ] : []
22146
+ ] : [],
22147
+ {
22148
+ label: "List the current atomic tool catalog",
22149
+ command: "deepline tools list --json"
22150
+ },
22151
+ ...query ? [
22152
+ {
22153
+ label: "Search composed Deepline plays separately",
22154
+ command: `deepline plays search -- ${shellCommandArg(query)}`
22155
+ }
22156
+ ] : []
22157
+ ];
22158
+ return {
22159
+ reason: "filters_matched_no_atomic_tools",
22160
+ message: `The tools catalog responded successfully, but no atomic provider tools matched ${filterText || "the current filters"}. This is a zero-match filter result, not a registry outage.`,
22161
+ suggestions
22162
+ };
22163
+ }
22164
+ function zeroMatchRender(emptyResult) {
22165
+ return {
22166
+ sections: [
22167
+ {
22168
+ title: "0 tools available:",
22169
+ lines: [emptyResult.message]
22170
+ },
22171
+ {
22172
+ title: "suggestions",
22173
+ lines: emptyResult.suggestions.map(
22174
+ (suggestion) => `${suggestion.label}: ${suggestion.command}`
22175
+ )
22176
+ }
22177
+ ]
22178
+ };
22179
+ }
22088
22180
  async function listTools(args) {
22089
22181
  const client2 = new DeeplineClient();
22090
22182
  const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
@@ -22099,8 +22191,9 @@ async function listTools(args) {
22099
22191
  (category) => item.categories.includes(category)
22100
22192
  )
22101
22193
  );
22194
+ const emptyResult = items.length === 0 && requestedCategories.length > 0 ? zeroMatchToolGuidance({ categories: requestedCategories }) : null;
22102
22195
  const render = {
22103
- sections: [
22196
+ sections: emptyResult ? zeroMatchRender(emptyResult).sections : [
22104
22197
  {
22105
22198
  title: `${items.length} tools available:`,
22106
22199
  lines: items.map((item) => {
@@ -22122,6 +22215,7 @@ async function listTools(args) {
22122
22215
  {
22123
22216
  tools: outputItems,
22124
22217
  count: outputItems.length,
22218
+ ...emptyResult ? { emptyResult } : {},
22125
22219
  filters: {
22126
22220
  categories: requestedCategories
22127
22221
  },
@@ -22193,6 +22287,11 @@ async function grepTools(queryInput, options = {}) {
22193
22287
  );
22194
22288
  const shouldCompact = options.compact || !options.json;
22195
22289
  const outputTools = shouldCompact ? tools.slice(0, 8).map(compactTool) : tools;
22290
+ const emptyResult = tools.length === 0 ? zeroMatchToolGuidance({
22291
+ categories: requestedCategories,
22292
+ query,
22293
+ mode
22294
+ }) : null;
22196
22295
  printCommandEnvelope(
22197
22296
  {
22198
22297
  tools: outputTools,
@@ -22205,6 +22304,10 @@ async function grepTools(queryInput, options = {}) {
22205
22304
  filters: {
22206
22305
  categories: requestedCategories
22207
22306
  },
22307
+ ...emptyResult ? {
22308
+ emptyResult,
22309
+ render: zeroMatchRender(emptyResult)
22310
+ } : {},
22208
22311
  commandTemplates: TOOL_COMMAND_TEMPLATES
22209
22312
  },
22210
22313
  { json: options.json || shouldEmitJson() }
@@ -24239,6 +24342,9 @@ function sdkNpmGlobalInstallCommand() {
24239
24342
  var CHECK_TIMEOUT_MS2 = 3e3;
24240
24343
  var attemptedSync = false;
24241
24344
  function shouldSkipSkillsSync() {
24345
+ if (detectAgentRuntime() === "claude_cowork") {
24346
+ return true;
24347
+ }
24242
24348
  const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
24243
24349
  return value === "1" || value === "true" || value === "yes" || value === "on";
24244
24350
  }
@@ -24464,6 +24570,7 @@ function runLegacySkillsCleanup() {
24464
24570
  for (const candidate of candidates) {
24465
24571
  const result = spawnSync2(candidate.command, candidate.args, {
24466
24572
  stdio: "ignore",
24573
+ env: process.env,
24467
24574
  shell: process.platform === "win32"
24468
24575
  });
24469
24576
  if (result.status === 0) return;
package/dist/index.d.mts CHANGED
@@ -295,6 +295,15 @@ interface ToolSearchResult {
295
295
  search_mode?: 'v1' | 'v2';
296
296
  /** Whether search fell back to category matching. */
297
297
  search_fallback_to_category?: boolean;
298
+ /** Explanation and next commands when filters/search succeed but match zero tools. */
299
+ emptyResult?: {
300
+ reason: string;
301
+ message: string;
302
+ suggestions: Array<{
303
+ label: string;
304
+ command: string;
305
+ }>;
306
+ };
298
307
  /** Hint explaining omitted play results when searching tools only. */
299
308
  omitted_plays_hint?: string;
300
309
  /** Copyable CLI command templates for follow-up discovery/execution. */
package/dist/index.d.ts CHANGED
@@ -295,6 +295,15 @@ interface ToolSearchResult {
295
295
  search_mode?: 'v1' | 'v2';
296
296
  /** Whether search fell back to category matching. */
297
297
  search_fallback_to_category?: boolean;
298
+ /** Explanation and next commands when filters/search succeed but match zero tools. */
299
+ emptyResult?: {
300
+ reason: string;
301
+ message: string;
302
+ suggestions: Array<{
303
+ label: string;
304
+ command: string;
305
+ }>;
306
+ };
298
307
  /** Hint explaining omitted play results when searching tools only. */
299
308
  omitted_plays_hint?: string;
300
309
  /** Copyable CLI command templates for follow-up discovery/execution. */
package/dist/index.js CHANGED
@@ -421,10 +421,10 @@ var SDK_RELEASE = {
421
421
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
422
422
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
423
423
  // fields shipped in 0.1.153.
424
- version: "0.1.164",
424
+ version: "0.1.166",
425
425
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
426
426
  supportPolicy: {
427
- latest: "0.1.164",
427
+ latest: "0.1.166",
428
428
  minimumSupported: "0.1.53",
429
429
  deprecatedBelow: "0.1.53",
430
430
  commandMinimumSupported: [
@@ -548,8 +548,8 @@ function isCoworkLikeSandbox2() {
548
548
  const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
549
549
  const pluginRoot = Boolean(process.env.DEEPLINE_PLUGIN_ROOT?.trim());
550
550
  const home = process.env.HOME?.trim() || (0, import_node_os2.homedir)();
551
- const sessionHome = home.startsWith("/sessions/");
552
- return (pluginMode || pluginRoot) && (claudeRemote || projectDir || sessionHome);
551
+ const sessionHome = home === "/sessions" || home.startsWith("/sessions/");
552
+ return claudeRemote || sessionHome || (pluginMode || pluginRoot) && projectDir;
553
553
  }
554
554
  function detectAgentRuntime(options = {}) {
555
555
  const explicit = normalizeAgentRuntime(process.env.DEEPLINE_AGENT_RUNTIME);
package/dist/index.mjs CHANGED
@@ -351,10 +351,10 @@ var SDK_RELEASE = {
351
351
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
352
352
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
353
353
  // fields shipped in 0.1.153.
354
- version: "0.1.164",
354
+ version: "0.1.166",
355
355
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
356
356
  supportPolicy: {
357
- latest: "0.1.164",
357
+ latest: "0.1.166",
358
358
  minimumSupported: "0.1.53",
359
359
  deprecatedBelow: "0.1.53",
360
360
  commandMinimumSupported: [
@@ -478,8 +478,8 @@ function isCoworkLikeSandbox2() {
478
478
  const projectDir = Boolean(process.env.CLAUDE_PROJECT_DIR?.trim());
479
479
  const pluginRoot = Boolean(process.env.DEEPLINE_PLUGIN_ROOT?.trim());
480
480
  const home = process.env.HOME?.trim() || homedir2();
481
- const sessionHome = home.startsWith("/sessions/");
482
- return (pluginMode || pluginRoot) && (claudeRemote || projectDir || sessionHome);
481
+ const sessionHome = home === "/sessions" || home.startsWith("/sessions/");
482
+ return claudeRemote || sessionHome || (pluginMode || pluginRoot) && projectDir;
483
483
  }
484
484
  function detectAgentRuntime(options = {}) {
485
485
  const explicit = normalizeAgentRuntime(process.env.DEEPLINE_AGENT_RUNTIME);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.164",
3
+ "version": "0.1.166",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {