autotouch-cli 0.2.92__tar.gz → 0.2.94__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/PKG-INFO +2 -2
  2. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/README.md +1 -1
  3. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/cli.py +2 -0
  4. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/agents.py +123 -1
  5. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/sequences.py +69 -0
  6. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/data/CLI_REFERENCE.md +42 -11
  7. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/data/cli-manifest.json +227 -4
  8. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/parser.py +1 -0
  9. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/templates.py +14 -13
  10. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli.egg-info/PKG-INFO +2 -2
  11. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/pyproject.toml +1 -1
  12. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/MANIFEST.in +0 -0
  13. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/__init__.py +0 -0
  14. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/cli_contracts.py +0 -0
  15. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/__init__.py +0 -0
  16. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/auth.py +0 -0
  17. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/cells.py +0 -0
  18. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/columns.py +0 -0
  19. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/jobs.py +0 -0
  20. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/leads.py +0 -0
  21. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/linkedin.py +0 -0
  22. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/list_build.py +0 -0
  23. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/prompts.py +0 -0
  24. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/rows.py +0 -0
  25. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/search.py +0 -0
  26. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/tables.py +0 -0
  27. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/tasks.py +0 -0
  28. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/webhooks.py +0 -0
  29. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/commands/workspace_secrets.py +0 -0
  30. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/__init__.py +0 -0
  31. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/auth.py +0 -0
  32. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/config.py +0 -0
  33. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/csv_import.py +0 -0
  34. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/http.py +0 -0
  35. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/io.py +0 -0
  36. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/output.py +0 -0
  37. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/polling.py +0 -0
  38. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/run.py +0 -0
  39. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/core/validation.py +0 -0
  40. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/exceptions.py +0 -0
  41. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/mongo_status.py +0 -0
  42. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/parser_groups.py +0 -0
  43. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli/sequence_support.py +0 -0
  44. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli.egg-info/SOURCES.txt +0 -0
  45. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli.egg-info/dependency_links.txt +0 -0
  46. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli.egg-info/entry_points.txt +0 -0
  47. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli.egg-info/requires.txt +0 -0
  48. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_cli.egg-info/top_level.txt +0 -0
  49. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_shared/__init__.py +0 -0
  50. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_shared/linkedin_contract.py +0 -0
  51. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_shared/linkedin_filters.py +0 -0
  52. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_shared/list_build_contract.py +0 -0
  53. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_shared/provider_registry.py +0 -0
  54. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/autotouch_shared/search_contract.py +0 -0
  55. {autotouch_cli-0.2.92 → autotouch_cli-0.2.94}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autotouch-cli
3
- Version: 0.2.92
3
+ Version: 0.2.94
4
4
  Summary: Autotouch Smart Table CLI
5
5
  Project-URL: Homepage, https://app.autotouch.ai
6
6
  Project-URL: Documentation, https://github.com/nicolonic/autotouch_main/tree/main/docs/research-table/reference
@@ -178,7 +178,7 @@ For automation or agent-driven setup, use:
178
178
  - `autotouch cli-manifest --output json` for the local machine-readable command contract
179
179
  - `autotouch cli-reference` for the shipped parser-generated reference
180
180
  - `autotouch capabilities --output json` for provider/workflow contracts
181
- - `autotouch --version` should be `0.2.92` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, paced HTTP Request column contracts, V2 sequence flowGraph recipes, real agent soft-delete with associated-table handling, and research-table sequence handoff assignee config
181
+ - `autotouch --version` should be `0.2.94` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, paced HTTP Request column contracts, branch-aware LinkedIn sequence recipes, real agent soft-delete with associated-table handling, and research-table sequence handoff assignee config
182
182
  - `autotouch capabilities --output json --select list_builds` for documented list-build inputs such as geography IDs, company size buckets, profile language, and company IDs
183
183
  - `autotouch list-build inputs` and `autotouch list-build pricing` before creating durable list-build jobs
184
184
  - `autotouch list-build companies` and `autotouch list-build leads` for durable LinkedIn-sourced company and lead list builds with Smart Table-owned background workers, visible progress, and no user-owned LinkedIn connection requirement
@@ -153,7 +153,7 @@ For automation or agent-driven setup, use:
153
153
  - `autotouch cli-manifest --output json` for the local machine-readable command contract
154
154
  - `autotouch cli-reference` for the shipped parser-generated reference
155
155
  - `autotouch capabilities --output json` for provider/workflow contracts
156
- - `autotouch --version` should be `0.2.92` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, paced HTTP Request column contracts, V2 sequence flowGraph recipes, real agent soft-delete with associated-table handling, and research-table sequence handoff assignee config
156
+ - `autotouch --version` should be `0.2.94` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, paced HTTP Request column contracts, branch-aware LinkedIn sequence recipes, real agent soft-delete with associated-table handling, and research-table sequence handoff assignee config
157
157
  - `autotouch capabilities --output json --select list_builds` for documented list-build inputs such as geography IDs, company size buckets, profile language, and company IDs
158
158
  - `autotouch list-build inputs` and `autotouch list-build pricing` before creating durable list-build jobs
159
159
  - `autotouch list-build companies` and `autotouch list-build leads` for durable LinkedIn-sourced company and lead list builds with Smart Table-owned background workers, visible progress, and no user-owned LinkedIn connection requirement
@@ -141,6 +141,7 @@ from autotouch_cli.commands.agents import (
141
141
  cmd_agents_get as cmd_agents_get_impl,
142
142
  cmd_agents_create as cmd_agents_create_impl,
143
143
  cmd_agents_update as cmd_agents_update_impl,
144
+ cmd_agents_diff as cmd_agents_diff_impl,
144
145
  cmd_agents_delete as cmd_agents_delete_impl,
145
146
  cmd_agents_run as cmd_agents_run_impl,
146
147
  cmd_agents_runs as cmd_agents_runs_impl,
@@ -1478,6 +1479,7 @@ _register("agents_list", cmd_agents_list_impl, _agent_command_runtime)
1478
1479
  _register("agents_get", cmd_agents_get_impl, _agent_command_runtime)
1479
1480
  _register("agents_create", cmd_agents_create_impl, _agent_command_runtime)
1480
1481
  _register("agents_update", cmd_agents_update_impl, _agent_command_runtime)
1482
+ _register("agents_diff", cmd_agents_diff_impl, _agent_command_runtime)
1481
1483
  _register("agents_delete", cmd_agents_delete_impl, _agent_command_runtime)
1482
1484
  _register("agents_run", cmd_agents_run_impl, _agent_command_runtime)
1483
1485
  _register("agents_runs", cmd_agents_runs_impl, _agent_command_runtime)
@@ -3,17 +3,32 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import argparse
6
+ import difflib
6
7
  import json
7
8
  import sys
8
9
  import time
9
10
  from dataclasses import dataclass
10
- from typing import Any, Callable, Dict, Optional, Sequence
11
+ from typing import Any, Callable, Dict, List, Optional, Sequence
11
12
 
12
13
  from autotouch_cli.exceptions import AutotouchInputError
13
14
 
14
15
 
15
16
  AGENT_TARGET_CHOICES = ["LEADS", "ACCOUNTS"]
16
17
 
18
+ AGENT_READ_ONLY_FIELDS = {
19
+ "id",
20
+ "configVersion",
21
+ "createdAt",
22
+ "updatedAt",
23
+ "nextRunAt",
24
+ "lastRunAt",
25
+ "sourceTableName",
26
+ "outputTableName",
27
+ "leadCounts",
28
+ "outputCounts",
29
+ "qualifiedColumnId",
30
+ }
31
+
17
32
 
18
33
  @dataclass(frozen=True)
19
34
  class AgentCommandRuntime:
@@ -29,6 +44,76 @@ class AgentCommandRuntime:
29
44
  # CRUD
30
45
  # ---------------------------------------------------------------------------
31
46
 
47
+ def _write_json_file(path: str, data: Any) -> None:
48
+ with open(path, "w", encoding="utf-8") as handle:
49
+ json.dump(data, handle, indent=2, ensure_ascii=False)
50
+ handle.write("\n")
51
+
52
+
53
+ def _editable_agent_payload(agent: Dict[str, Any]) -> Dict[str, Any]:
54
+ return {key: value for key, value in agent.items() if key not in AGENT_READ_ONLY_FIELDS}
55
+
56
+
57
+ def _json_lines(data: Any) -> List[str]:
58
+ return json.dumps(data, indent=2, sort_keys=True, ensure_ascii=False).splitlines()
59
+
60
+
61
+ def _diff_payload(current: Dict[str, Any], patch: Dict[str, Any]) -> Dict[str, Any]:
62
+ before = {key: current.get(key) for key in patch.keys()}
63
+ after = dict(before)
64
+ after.update(patch)
65
+ changes = [
66
+ {"field": key, "before": before.get(key), "after": after.get(key)}
67
+ for key in sorted(patch.keys())
68
+ if before.get(key) != after.get(key)
69
+ ]
70
+ unified_diff = "\n".join(
71
+ difflib.unified_diff(
72
+ _json_lines(before),
73
+ _json_lines(after),
74
+ fromfile="current",
75
+ tofile="proposed",
76
+ lineterm="",
77
+ )
78
+ )
79
+ return {"changed": bool(changes), "changes": changes, "diff": unified_diff}
80
+
81
+
82
+ def _diff_from_agents(current: Dict[str, Any], proposed: Dict[str, Any], fields: Sequence[str]) -> Dict[str, Any]:
83
+ before = {key: current.get(key) for key in fields}
84
+ after = {key: proposed.get(key) for key in fields}
85
+ changes = [
86
+ {"field": key, "before": before.get(key), "after": after.get(key)}
87
+ for key in sorted(fields)
88
+ if before.get(key) != after.get(key)
89
+ ]
90
+ unified_diff = "\n".join(
91
+ difflib.unified_diff(
92
+ _json_lines(before),
93
+ _json_lines(after),
94
+ fromfile="current",
95
+ tofile="proposed",
96
+ lineterm="",
97
+ )
98
+ )
99
+ return {"changed": bool(changes), "changes": changes, "diff": unified_diff}
100
+
101
+
102
+ def _validate_update_remote(args: argparse.Namespace, payload: Dict[str, Any], *, runtime: AgentCommandRuntime, token: Optional[str]) -> Dict[str, Any]:
103
+ data = runtime.request_api(
104
+ "POST", f"/api/agents/{args.agent_id}/validate-update",
105
+ base_url=args.base_url, token=token,
106
+ use_x_api_key=args.use_x_api_key,
107
+ payload=payload,
108
+ timeout=args.timeout, verbose=args.verbose,
109
+ )
110
+ if not isinstance(data, dict):
111
+ raise AutotouchInputError("agent update validation response must be a JSON object")
112
+ fields = data.get("changedFields") or []
113
+ if isinstance(fields, list) and isinstance(data.get("currentAgent"), dict) and isinstance(data.get("agent"), dict):
114
+ data.update(_diff_from_agents(data["currentAgent"], data["agent"], [str(field) for field in fields]))
115
+ return data
116
+
32
117
  def cmd_agents_list(args: argparse.Namespace, *, runtime: AgentCommandRuntime) -> None:
33
118
  token = runtime.resolve_token(args.token, required=True)
34
119
  data = runtime.request_api(
@@ -48,6 +133,10 @@ def cmd_agents_get(args: argparse.Namespace, *, runtime: AgentCommandRuntime) ->
48
133
  use_x_api_key=args.use_x_api_key,
49
134
  timeout=args.timeout, verbose=args.verbose,
50
135
  )
136
+ out_file = getattr(args, "out_file", None)
137
+ if out_file:
138
+ payload = _editable_agent_payload(data if isinstance(data, dict) else {})
139
+ _write_json_file(out_file, payload)
51
140
  runtime.print_json(data, args.compact)
52
141
 
53
142
 
@@ -258,6 +347,14 @@ def cmd_agents_update(args: argparse.Namespace, *, runtime: AgentCommandRuntime)
258
347
  merged_schedule[key] = value
259
348
  payload["schedule"] = merged_schedule
260
349
 
350
+ if getattr(args, "dry_run", False):
351
+ data = _validate_update_remote(args, payload, runtime=runtime, token=token)
352
+ data.setdefault("dryRun", True)
353
+ data.setdefault("patch", payload)
354
+ data.setdefault("next", "Run again without --dry-run to apply this patch.")
355
+ runtime.print_json(data, args.compact)
356
+ return
357
+
261
358
  data = runtime.request_api(
262
359
  "PATCH", f"/api/agents/{args.agent_id}",
263
360
  base_url=args.base_url, token=token,
@@ -268,6 +365,22 @@ def cmd_agents_update(args: argparse.Namespace, *, runtime: AgentCommandRuntime)
268
365
  runtime.print_json(data, args.compact)
269
366
 
270
367
 
368
+ def cmd_agents_diff(args: argparse.Namespace, *, runtime: AgentCommandRuntime) -> None:
369
+ token = runtime.resolve_token(args.token, required=True)
370
+ patch = runtime.load_json_input(
371
+ inline_json=None,
372
+ file_path=args.from_file,
373
+ context="agent patch",
374
+ default={},
375
+ )
376
+ if not isinstance(patch, dict):
377
+ raise AutotouchInputError("agent patch must be a JSON object")
378
+ result = _validate_update_remote(args, patch, runtime=runtime, token=token)
379
+ result.setdefault("agentId", args.agent_id)
380
+ result.setdefault("patch", patch)
381
+ runtime.print_json(result, args.compact)
382
+
383
+
271
384
  def cmd_agents_delete(args: argparse.Namespace, *, runtime: AgentCommandRuntime) -> None:
272
385
  delete_associated_tables = bool(getattr(args, "delete_associated_tables", False))
273
386
  if delete_associated_tables and not bool(getattr(args, "yes", False)):
@@ -465,6 +578,7 @@ def register_agents_subcommands(
465
578
  # -- get --
466
579
  pag = agents_sub.add_parser("get", help="Get one agent by id")
467
580
  pag.add_argument("agent_id", help="Agent ID")
581
+ pag.add_argument("--out-file", dest="out_file", help="Write editable agent config JSON to file")
468
582
  add_api_common_arguments(pag)
469
583
  pag.set_defaults(func=handlers["get"])
470
584
 
@@ -577,9 +691,17 @@ def register_agents_subcommands(
577
691
  help="Active-hours window end (HH:MM) — used by hourly/every_6h/every_12h",
578
692
  )
579
693
  pau.add_argument("--from-file", dest="from_file", help="Path to JSON patch payload file")
694
+ pau.add_argument("--dry-run", action="store_true", help="Preview the patch and diff without applying it")
580
695
  add_api_common_arguments(pau)
581
696
  pau.set_defaults(func=handlers["update"])
582
697
 
698
+ # -- diff --
699
+ padiff = agents_sub.add_parser("diff", help="Preview changes from a JSON patch without applying them")
700
+ padiff.add_argument("agent_id", help="Agent ID")
701
+ padiff.add_argument("--from-file", dest="from_file", required=True, help="Path to JSON patch payload file")
702
+ add_api_common_arguments(padiff)
703
+ padiff.set_defaults(func=handlers["diff"])
704
+
583
705
  # -- delete --
584
706
  pad = agents_sub.add_parser("delete", help="Soft-delete an agent and detach its associated tables")
585
707
  pad.add_argument("agent_id", help="Agent ID")
@@ -77,6 +77,71 @@ def _attach_sequence_enroll_hints(output: Dict[str, Any], payload: Dict[str, Any
77
77
  return enriched
78
78
 
79
79
 
80
+ def _sequence_shape(sequence: Dict[str, Any]) -> Dict[str, Any]:
81
+ steps = sequence.get("steps") if isinstance(sequence.get("steps"), list) else []
82
+ flow_graph = sequence.get("flowGraph") if isinstance(sequence.get("flowGraph"), dict) else {}
83
+ nodes = flow_graph.get("nodes") if isinstance(flow_graph.get("nodes"), list) else []
84
+ edges = flow_graph.get("edges") if isinstance(flow_graph.get("edges"), list) else []
85
+ return {
86
+ "step_count": len(steps),
87
+ "step_kinds": [str((step or {}).get("kind") or "") for step in steps if isinstance(step, dict)],
88
+ "flow_graph_present": bool(flow_graph),
89
+ "flow_graph_node_count": len(nodes),
90
+ "flow_graph_edge_count": len(edges),
91
+ "has_branching": any(str((node or {}).get("kind") or "").lower() in {"condition", "branch"} for node in nodes if isinstance(node, dict)),
92
+ }
93
+
94
+
95
+ def _fetch_sequence_readback(
96
+ sequence_id: str,
97
+ args: argparse.Namespace,
98
+ *,
99
+ runtime: SequenceCommandRuntime,
100
+ token: Optional[str],
101
+ ) -> Optional[Dict[str, Any]]:
102
+ if not sequence_id:
103
+ return None
104
+ data = runtime.request_api(
105
+ "GET",
106
+ f"/api/sequences/{sequence_id}",
107
+ base_url=args.base_url,
108
+ token=token,
109
+ use_x_api_key=args.use_x_api_key,
110
+ timeout=args.timeout,
111
+ verbose=args.verbose,
112
+ )
113
+ return data if isinstance(data, dict) else None
114
+
115
+
116
+ def _sequence_mutation_output(
117
+ mutation_result: Dict[str, Any],
118
+ args: argparse.Namespace,
119
+ *,
120
+ runtime: SequenceCommandRuntime,
121
+ token: Optional[str],
122
+ submitted_payload: Optional[Dict[str, Any]] = None,
123
+ sequence_id: Optional[str] = None,
124
+ ) -> Dict[str, Any]:
125
+ output = dict(mutation_result)
126
+ submitted_shape = _sequence_shape(submitted_payload) if isinstance(submitted_payload, dict) else None
127
+ if submitted_shape:
128
+ output["submitted_shape"] = submitted_shape
129
+ readback_id = str(sequence_id or output.get("id") or output.get("sequenceId") or "").strip()
130
+ readback = _fetch_sequence_readback(readback_id, args, runtime=runtime, token=token)
131
+ if readback:
132
+ readback_shape = _sequence_shape(readback)
133
+ output["sequence"] = readback
134
+ output["verified_readback"] = True
135
+ output["readback_shape"] = readback_shape
136
+ if submitted_shape:
137
+ output["readback_shape_matches_submitted"] = readback_shape == submitted_shape
138
+ output["verification_hint"] = "This output includes the sequence as saved by the API; summarize this readback, not only the submitted payload."
139
+ else:
140
+ output["verified_readback"] = False
141
+ output["verification_hint"] = "Could not read back the saved sequence; verify with `autotouch sequences get --sequence-id <id>` before summarizing."
142
+ return output
143
+
144
+
80
145
  def _sequence_mutation_params(args: argparse.Namespace) -> Optional[Dict[str, Any]]:
81
146
  return sequence_mutation_params_impl(args)
82
147
 
@@ -181,6 +246,8 @@ def cmd_sequences_create(args: argparse.Namespace, *, runtime: SequenceCommandRu
181
246
  timeout=args.timeout,
182
247
  verbose=args.verbose,
183
248
  )
249
+ if isinstance(data, dict):
250
+ data = _sequence_mutation_output(data, args, runtime=runtime, token=token, submitted_payload=payload)
184
251
  runtime.print_json(data, args.compact)
185
252
 
186
253
 
@@ -230,6 +297,8 @@ def cmd_sequences_update(args: argparse.Namespace, *, runtime: SequenceCommandRu
230
297
  )
231
298
  raise AutotouchAPIError(message, status_code=exc.status_code, response_body=exc.response_body) from exc
232
299
  raise
300
+ if isinstance(data, dict):
301
+ data = _sequence_mutation_output(data, args, runtime=runtime, token=token, submitted_payload=payload, sequence_id=args.sequence_id)
233
302
  runtime.print_json(data, args.compact)
234
303
 
235
304
 
@@ -1,6 +1,6 @@
1
1
  # Autotouch CLI Reference
2
2
 
3
- Generated from the installed parser for `autotouch-cli` `0.2.92`.
3
+ Generated from the installed parser for `autotouch-cli` `0.2.94`.
4
4
  Manifest schema version: `2`.
5
5
 
6
6
  ## Output Modes
@@ -20,10 +20,10 @@ Scheduled agent management
20
20
  - Auth: `varies_by_subcommand`
21
21
  - Stability: `stable`
22
22
  - Destructive: `no`
23
- - Subcommands: `list, get, create, update, delete, run, runs, watch, generate-persona, generate-topics, generate-job-signal, signals`
23
+ - Subcommands: `list, get, create, update, diff, delete, run, runs, watch, generate-persona, generate-topics, generate-job-signal, signals`
24
24
  - Example:
25
25
  - `autotouch agents [-h]
26
- {list,get,create,update,delete,run,runs,watch,generate-persona,generate-topics,generate-job-signal,signals} ...`
26
+ {list,get,create,update,diff,delete,run,runs,watch,generate-persona,generate-topics,generate-job-signal,signals} ...`
27
27
 
28
28
  #### `autotouch agents create`
29
29
 
@@ -112,6 +112,35 @@ Soft-delete an agent and detach its associated tables
112
112
  - `--json-pointer` (kind=string): Extract a JSON pointer from the final result (for example: /id)
113
113
  - `--verbose` (kind=boolean; when omitted=False; when present=True): Print request metadata to stderr
114
114
 
115
+ #### `autotouch agents diff`
116
+
117
+ Preview changes from a JSON patch without applying them
118
+
119
+ - Auth: `developer_key_or_user_session`
120
+ - Stability: `stable`
121
+ - Destructive: `no`
122
+ - Required flags: `--from-file`
123
+ - Output modes: `json, ndjson, human`
124
+ - Example:
125
+ - `autotouch agents diff [-h] --from-file FROM_FILE [--base-url BASE_URL]
126
+ [--token TOKEN] [--use-x-api-key]
127
+ [--timeout TIMEOUT]
128
+ [--output {json,ndjson,human}] [--compact]
129
+ [--select SELECT | --json-pointer JSON_POINTER]
130
+ [--verbose]
131
+ agent_id`
132
+ - Options:
133
+ - `--from-file` (required; kind=file; input=file): Path to JSON patch payload file
134
+ - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
135
+ - `--token` (kind=string; sensitive): Developer API key / JWT token
136
+ - `--use-x-api-key` (kind=boolean; when omitted=False; when present=True): Send token via X-API-Key header
137
+ - `--timeout` (kind=integer; default=30): HTTP timeout in seconds
138
+ - `--output` (kind=string; choices=json,ndjson,human; default=json): Output mode
139
+ - `--compact` (kind=boolean; when omitted=False; when present=True): Print compact JSON
140
+ - `--select` (kind=string): Extract a dotted field path from the final result (for example: id or items.0.id)
141
+ - `--json-pointer` (kind=string): Extract a JSON pointer from the final result (for example: /id)
142
+ - `--verbose` (kind=boolean; when omitted=False; when present=True): Print request metadata to stderr
143
+
115
144
  #### `autotouch agents generate-job-signal`
116
145
 
117
146
  Generate job signal config via AI
@@ -218,13 +247,14 @@ Get one agent by id
218
247
  - Destructive: `no`
219
248
  - Output modes: `json, ndjson, human`
220
249
  - Example:
221
- - `autotouch agents get [-h] [--base-url BASE_URL] [--token TOKEN]
222
- [--use-x-api-key] [--timeout TIMEOUT]
223
- [--output {json,ndjson,human}] [--compact]
224
- [--select SELECT | --json-pointer JSON_POINTER]
225
- [--verbose]
250
+ - `autotouch agents get [-h] [--out-file OUT_FILE] [--base-url BASE_URL]
251
+ [--token TOKEN] [--use-x-api-key]
252
+ [--timeout TIMEOUT] [--output {json,ndjson,human}]
253
+ [--compact] [--select SELECT |
254
+ --json-pointer JSON_POINTER] [--verbose]
226
255
  agent_id`
227
256
  - Options:
257
+ - `--out-file` (kind=file; input=file): Write editable agent config JSON to file
228
258
  - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
229
259
  - `--token` (kind=string; sensitive): Developer API key / JWT token
230
260
  - `--use-x-api-key` (kind=boolean; when omitted=False; when present=True): Send token via X-API-Key header
@@ -362,9 +392,9 @@ Update an existing agent
362
392
  [--schedule-day-of-week 0-6]
363
393
  [--schedule-window-start SCHEDULE_WINDOW_START]
364
394
  [--schedule-window-end SCHEDULE_WINDOW_END]
365
- [--from-file FROM_FILE] [--base-url BASE_URL]
366
- [--token TOKEN] [--use-x-api-key]
367
- [--timeout TIMEOUT]
395
+ [--from-file FROM_FILE] [--dry-run]
396
+ [--base-url BASE_URL] [--token TOKEN]
397
+ [--use-x-api-key] [--timeout TIMEOUT]
368
398
  [--output {json,ndjson,human}] [--compact]
369
399
  [--select SELECT | --json-pointer JSON_POINTER]
370
400
  [--verbose]
@@ -385,6 +415,7 @@ Update an existing agent
385
415
  - `--schedule-window-start` (kind=string): Active-hours window start (HH:MM) — used by hourly/every_6h/every_12h
386
416
  - `--schedule-window-end` (kind=string): Active-hours window end (HH:MM) — used by hourly/every_6h/every_12h
387
417
  - `--from-file` (kind=file; input=file): Path to JSON patch payload file
418
+ - `--dry-run` (kind=boolean; when omitted=False; when present=True): Preview the patch and diff without applying it
388
419
  - `--base-url` (kind=string; default=https://app.autotouch.ai): API base URL (default: https://app.autotouch.ai)
389
420
  - `--token` (kind=string; sensitive): Developer API key / JWT token
390
421
  - `--use-x-api-key` (kind=boolean; when omitted=False; when present=True): Send token via X-API-Key header
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.92",
2
+ "version": "0.2.94",
3
3
  "manifest_schema_version": 2,
4
4
  "entry_points": {
5
5
  "autotouch": "autotouch_cli.cli:main",
@@ -34390,6 +34390,7 @@
34390
34390
  "get",
34391
34391
  "create",
34392
34392
  "update",
34393
+ "diff",
34393
34394
  "delete",
34394
34395
  "run",
34395
34396
  "runs",
@@ -34405,7 +34406,7 @@
34405
34406
  "output_contract": null,
34406
34407
  "availability": null,
34407
34408
  "examples": [
34408
- "autotouch agents [-h]\n {list,get,create,update,delete,run,runs,watch,generate-persona,generate-topics,generate-job-signal,signals} ..."
34409
+ "autotouch agents [-h]\n {list,get,create,update,diff,delete,run,runs,watch,generate-persona,generate-topics,generate-job-signal,signals} ..."
34409
34410
  ],
34410
34411
  "stability": "stable",
34411
34412
  "handler": null
@@ -34606,6 +34607,18 @@
34606
34607
  }
34607
34608
  ],
34608
34609
  "options": [
34610
+ {
34611
+ "dest": "out_file",
34612
+ "required": false,
34613
+ "help": "Write editable agent config JSON to file",
34614
+ "kind": "file",
34615
+ "action": "store",
34616
+ "input_kind": "file",
34617
+ "flags": [
34618
+ "--out-file"
34619
+ ],
34620
+ "takes_value": true
34621
+ },
34609
34622
  {
34610
34623
  "dest": "base_url",
34611
34624
  "required": false,
@@ -34759,7 +34772,7 @@
34759
34772
  },
34760
34773
  "availability": null,
34761
34774
  "examples": [
34762
- "autotouch agents get [-h] [--base-url BASE_URL] [--token TOKEN]\n [--use-x-api-key] [--timeout TIMEOUT]\n [--output {json,ndjson,human}] [--compact]\n [--select SELECT | --json-pointer JSON_POINTER]\n [--verbose]\n agent_id"
34775
+ "autotouch agents get [-h] [--out-file OUT_FILE] [--base-url BASE_URL]\n [--token TOKEN] [--use-x-api-key]\n [--timeout TIMEOUT] [--output {json,ndjson,human}]\n [--compact] [--select SELECT |\n --json-pointer JSON_POINTER] [--verbose]\n agent_id"
34763
34776
  ],
34764
34777
  "stability": "stable",
34765
34778
  "handler": "_fn"
@@ -35403,6 +35416,216 @@
35403
35416
  ],
35404
35417
  "takes_value": true
35405
35418
  },
35419
+ {
35420
+ "dest": "dry_run",
35421
+ "required": false,
35422
+ "help": "Preview the patch and diff without applying it",
35423
+ "kind": "boolean",
35424
+ "action": "store_true",
35425
+ "nargs": 0,
35426
+ "default_when_omitted": false,
35427
+ "value_when_present": true,
35428
+ "flags": [
35429
+ "--dry-run"
35430
+ ],
35431
+ "takes_value": false
35432
+ },
35433
+ {
35434
+ "dest": "base_url",
35435
+ "required": false,
35436
+ "help": "API base URL (default: https://app.autotouch.ai)",
35437
+ "kind": "string",
35438
+ "action": "store",
35439
+ "default_when_omitted": "https://app.autotouch.ai",
35440
+ "default": "https://app.autotouch.ai",
35441
+ "flags": [
35442
+ "--base-url"
35443
+ ],
35444
+ "takes_value": true
35445
+ },
35446
+ {
35447
+ "dest": "token",
35448
+ "required": false,
35449
+ "help": "Developer API key / JWT token",
35450
+ "kind": "string",
35451
+ "action": "store",
35452
+ "sensitive": true,
35453
+ "flags": [
35454
+ "--token"
35455
+ ],
35456
+ "takes_value": true
35457
+ },
35458
+ {
35459
+ "dest": "use_x_api_key",
35460
+ "required": false,
35461
+ "help": "Send token via X-API-Key header",
35462
+ "kind": "boolean",
35463
+ "action": "store_true",
35464
+ "nargs": 0,
35465
+ "default_when_omitted": false,
35466
+ "value_when_present": true,
35467
+ "flags": [
35468
+ "--use-x-api-key"
35469
+ ],
35470
+ "takes_value": false
35471
+ },
35472
+ {
35473
+ "dest": "timeout",
35474
+ "required": false,
35475
+ "help": "HTTP timeout in seconds",
35476
+ "kind": "integer",
35477
+ "action": "store",
35478
+ "default_when_omitted": 30,
35479
+ "default": 30,
35480
+ "flags": [
35481
+ "--timeout"
35482
+ ],
35483
+ "takes_value": true
35484
+ },
35485
+ {
35486
+ "dest": "output",
35487
+ "required": false,
35488
+ "help": "Output mode",
35489
+ "kind": "string",
35490
+ "action": "store",
35491
+ "choices": [
35492
+ "json",
35493
+ "ndjson",
35494
+ "human"
35495
+ ],
35496
+ "default_when_omitted": "json",
35497
+ "default": "json",
35498
+ "flags": [
35499
+ "--output"
35500
+ ],
35501
+ "takes_value": true
35502
+ },
35503
+ {
35504
+ "dest": "compact",
35505
+ "required": false,
35506
+ "help": "Print compact JSON",
35507
+ "kind": "boolean",
35508
+ "action": "store_true",
35509
+ "nargs": 0,
35510
+ "default_when_omitted": false,
35511
+ "value_when_present": true,
35512
+ "flags": [
35513
+ "--compact"
35514
+ ],
35515
+ "takes_value": false
35516
+ },
35517
+ {
35518
+ "dest": "select",
35519
+ "required": false,
35520
+ "help": "Extract a dotted field path from the final result (for example: id or items.0.id)",
35521
+ "kind": "string",
35522
+ "action": "store",
35523
+ "flags": [
35524
+ "--select"
35525
+ ],
35526
+ "takes_value": true
35527
+ },
35528
+ {
35529
+ "dest": "json_pointer",
35530
+ "required": false,
35531
+ "help": "Extract a JSON pointer from the final result (for example: /id)",
35532
+ "kind": "string",
35533
+ "action": "store",
35534
+ "flags": [
35535
+ "--json-pointer"
35536
+ ],
35537
+ "takes_value": true
35538
+ },
35539
+ {
35540
+ "dest": "verbose",
35541
+ "required": false,
35542
+ "help": "Print request metadata to stderr",
35543
+ "kind": "boolean",
35544
+ "action": "store_true",
35545
+ "nargs": 0,
35546
+ "default_when_omitted": false,
35547
+ "value_when_present": true,
35548
+ "flags": [
35549
+ "--verbose"
35550
+ ],
35551
+ "takes_value": false
35552
+ }
35553
+ ],
35554
+ "mutually_exclusive_groups": [
35555
+ {
35556
+ "required": false,
35557
+ "options": [
35558
+ "--select",
35559
+ "--json-pointer"
35560
+ ]
35561
+ }
35562
+ ],
35563
+ "subcommands": [],
35564
+ "leaf_command": true,
35565
+ "auth_mode": "developer_key_or_user_session",
35566
+ "destructive": false,
35567
+ "output_contract": {
35568
+ "modes": [
35569
+ "json",
35570
+ "ndjson",
35571
+ "human"
35572
+ ],
35573
+ "json": {
35574
+ "single_document": true
35575
+ },
35576
+ "ndjson": {
35577
+ "streaming": true,
35578
+ "recommended_for": "progress updates / watch flows"
35579
+ },
35580
+ "human": {
35581
+ "interactive": true
35582
+ }
35583
+ },
35584
+ "availability": null,
35585
+ "examples": [
35586
+ "autotouch agents update [-h] [--name NAME]\n [--status {DRAFT,ACTIVE,PAUSED}]\n [--auto-find-email AUTO_FIND_EMAIL]\n [--auto-find-phone AUTO_FIND_PHONE]\n [--auto-broaden AUTO_BROADEN]\n [--auto-create-lead-mode {qualified_only,everyone,manual_only}]\n [--auto-sequence-id AUTO_SEQUENCE_ID]\n [--schedule-time SCHEDULE_TIME]\n [--schedule-tz SCHEDULE_TZ]\n [--schedule-frequency {hourly,every_6h,every_12h,daily,weekly}]\n [--schedule-days {all,weekdays}]\n [--schedule-day-of-week 0-6]\n [--schedule-window-start SCHEDULE_WINDOW_START]\n [--schedule-window-end SCHEDULE_WINDOW_END]\n [--from-file FROM_FILE] [--dry-run]\n [--base-url BASE_URL] [--token TOKEN]\n [--use-x-api-key] [--timeout TIMEOUT]\n [--output {json,ndjson,human}] [--compact]\n [--select SELECT | --json-pointer JSON_POINTER]\n [--verbose]\n agent_id"
35587
+ ],
35588
+ "stability": "stable",
35589
+ "handler": "_fn"
35590
+ },
35591
+ "agents.diff": {
35592
+ "canonical": [
35593
+ "autotouch",
35594
+ "agents",
35595
+ "diff"
35596
+ ],
35597
+ "aliases": [],
35598
+ "group": "agents",
35599
+ "help": "Preview changes from a JSON patch without applying them",
35600
+ "description": null,
35601
+ "notes": null,
35602
+ "required_flags": [
35603
+ "--from-file"
35604
+ ],
35605
+ "positionals": [
35606
+ {
35607
+ "dest": "agent_id",
35608
+ "required": true,
35609
+ "help": "Agent ID",
35610
+ "kind": "string",
35611
+ "action": "store",
35612
+ "name": "agent_id",
35613
+ "positional": true
35614
+ }
35615
+ ],
35616
+ "options": [
35617
+ {
35618
+ "dest": "from_file",
35619
+ "required": true,
35620
+ "help": "Path to JSON patch payload file",
35621
+ "kind": "file",
35622
+ "action": "store",
35623
+ "input_kind": "file",
35624
+ "flags": [
35625
+ "--from-file"
35626
+ ],
35627
+ "takes_value": true
35628
+ },
35406
35629
  {
35407
35630
  "dest": "base_url",
35408
35631
  "required": false,
@@ -35556,7 +35779,7 @@
35556
35779
  },
35557
35780
  "availability": null,
35558
35781
  "examples": [
35559
- "autotouch agents update [-h] [--name NAME]\n [--status {DRAFT,ACTIVE,PAUSED}]\n [--auto-find-email AUTO_FIND_EMAIL]\n [--auto-find-phone AUTO_FIND_PHONE]\n [--auto-broaden AUTO_BROADEN]\n [--auto-create-lead-mode {qualified_only,everyone,manual_only}]\n [--auto-sequence-id AUTO_SEQUENCE_ID]\n [--schedule-time SCHEDULE_TIME]\n [--schedule-tz SCHEDULE_TZ]\n [--schedule-frequency {hourly,every_6h,every_12h,daily,weekly}]\n [--schedule-days {all,weekdays}]\n [--schedule-day-of-week 0-6]\n [--schedule-window-start SCHEDULE_WINDOW_START]\n [--schedule-window-end SCHEDULE_WINDOW_END]\n [--from-file FROM_FILE] [--base-url BASE_URL]\n [--token TOKEN] [--use-x-api-key]\n [--timeout TIMEOUT]\n [--output {json,ndjson,human}] [--compact]\n [--select SELECT | --json-pointer JSON_POINTER]\n [--verbose]\n agent_id"
35782
+ "autotouch agents diff [-h] --from-file FROM_FILE [--base-url BASE_URL]\n [--token TOKEN] [--use-x-api-key]\n [--timeout TIMEOUT]\n [--output {json,ndjson,human}] [--compact]\n [--select SELECT | --json-pointer JSON_POINTER]\n [--verbose]\n agent_id"
35560
35783
  ],
35561
35784
  "stability": "stable",
35562
35785
  "handler": "_fn"
@@ -782,6 +782,7 @@ def build_parser(
782
782
  "get": commands["agents_get"],
783
783
  "create": commands["agents_create"],
784
784
  "update": commands["agents_update"],
785
+ "diff": commands["agents_diff"],
785
786
  "delete": commands["agents_delete"],
786
787
  "run": commands["agents_run"],
787
788
  "runs": commands["agents_runs"],
@@ -379,10 +379,10 @@ SEQUENCE_RECIPES: Dict[str, Dict[str, Any]] = {
379
379
  {
380
380
  "id": "connect_1",
381
381
  "kind": "LINKEDIN_CONNECT",
382
- "waitDays": 1,
382
+ "waitDays": 0,
383
383
  "waitHours": 0,
384
- "waitMinutes": 0,
385
- "executionMode": "AUTOMATED",
384
+ "waitMinutes": 7,
385
+ "executionMode": "MANUAL",
386
386
  "aiDraft": True,
387
387
  "scriptTemplate": "",
388
388
  },
@@ -392,8 +392,8 @@ SEQUENCE_RECIPES: Dict[str, Dict[str, Any]] = {
392
392
  "waitDays": 0,
393
393
  "waitHours": 0,
394
394
  "waitMinutes": 0,
395
- "executionMode": "AUTOMATED",
396
- "emailSendMode": "AUTOMATED",
395
+ "executionMode": "MANUAL",
396
+ "emailSendMode": "MANUAL",
397
397
  "emailIsReply": False,
398
398
  "appendSignature": True,
399
399
  "aiDraft": True,
@@ -406,7 +406,7 @@ SEQUENCE_RECIPES: Dict[str, Dict[str, Any]] = {
406
406
  "waitDays": 0,
407
407
  "waitHours": 0,
408
408
  "waitMinutes": 0,
409
- "executionMode": "AUTOMATED",
409
+ "executionMode": "MANUAL",
410
410
  "aiDraft": True,
411
411
  "scriptTemplate": "",
412
412
  },
@@ -527,28 +527,29 @@ SEQUENCE_RECIPES: Dict[str, Dict[str, Any]] = {
527
527
 
528
528
  SEQUENCE_RECIPE_NOTES: Dict[str, List[str]] = {
529
529
  "create": [
530
- "Recommended default: V2 flowGraph with personal delivery plus AUTOMATED email with aiDraft=true.",
531
- "flowGraph.version=1 is the executable authoring layer; keep steps aligned with graph action sourceStepId values.",
530
+ "Recommended default: branch-aware sequence payload with personal delivery plus AUTOMATED email with aiDraft=true.",
531
+ "Keep steps aligned with graph action sourceStepId values.",
532
532
  "AI draft generates subject + body at execution time.",
533
533
  "AI draft for call generates a call script.",
534
534
  "External sequence create/update requires sourceTableId.",
535
535
  "Pass --actor-user-id on mutating commands when you need explicit actor resolution.",
536
536
  ],
537
537
  "bulk_automated": [
538
- "Emits a V2 flowGraph with two automated email actions.",
538
+ "Emits a branch-aware sequence payload with two automated email actions.",
539
539
  "Use this when the provider should send email automatically at scale.",
540
540
  "Bulk delivery sequences cannot contain MANUAL email steps, so aiDraft does not apply to those email steps.",
541
541
  "Activate only after provider readiness is configured (autotouch sequences delivery-status).",
542
542
  ],
543
543
  "linkedin_outreach": [
544
- "Emits a V2 flowGraph: visit profile, connect, wait for accepted connection, then branch to LinkedIn message or fallback email.",
544
+ "Emits the standard LinkedIn branch sequence: visit profile, manual AI-drafted connect, wait for accepted connection, then branch to LinkedIn message or email.",
545
545
  "Supported step kinds: LINKEDIN_VISIT_PROFILE, LINKEDIN_CONNECT, LINKEDIN_CHAT_MESSAGE, LINKEDIN_VOICE_MESSAGE.",
546
546
  "LINKEDIN_VISIT_PROFILE is always AUTOMATED and visits the lead's profile (notifies by default).",
547
- "LINKEDIN_CONNECT sends a connection request; scriptTemplate is the invite note (max 300 chars).",
548
- "LINKEDIN_CHAT_MESSAGE sends a direct message; uses InMail credits for 2nd/3rd degree connections.",
547
+ "For manual AI-drafted LinkedIn steps, set executionMode=MANUAL, aiDraft=true, and scriptTemplate=\"\".",
548
+ "LINKEDIN_CONNECT drafts a connection request; invite notes must stay under 300 chars.",
549
+ "LINKEDIN_CHAT_MESSAGE creates a direct-message task after connection is accepted.",
549
550
  "LINKEDIN_VOICE_MESSAGE sends a voice note; only works for 1st degree connections.",
550
551
  "Connection degree (1st/2nd/3rd/out_of_network) is auto-detected from the LinkedIn profile.",
551
- "The connected branch is explicit in flowGraph; the fallback email branch is explicit and does not happen silently.",
552
+ "Every branch must be explicit and must route to the action that should run on that path.",
552
553
  "Set stopOnLinkedInReply=true in exitRules to stop the sequence when the lead replies on LinkedIn.",
553
554
  "Leads must have a linkedin_url field to be reachable for LinkedIn steps.",
554
555
  ],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autotouch-cli
3
- Version: 0.2.92
3
+ Version: 0.2.94
4
4
  Summary: Autotouch Smart Table CLI
5
5
  Project-URL: Homepage, https://app.autotouch.ai
6
6
  Project-URL: Documentation, https://github.com/nicolonic/autotouch_main/tree/main/docs/research-table/reference
@@ -178,7 +178,7 @@ For automation or agent-driven setup, use:
178
178
  - `autotouch cli-manifest --output json` for the local machine-readable command contract
179
179
  - `autotouch cli-reference` for the shipped parser-generated reference
180
180
  - `autotouch capabilities --output json` for provider/workflow contracts
181
- - `autotouch --version` should be `0.2.92` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, paced HTTP Request column contracts, V2 sequence flowGraph recipes, real agent soft-delete with associated-table handling, and research-table sequence handoff assignee config
181
+ - `autotouch --version` should be `0.2.94` or newer for structured company list builds without user-supplied keywords, stored list-build input lookup, research-workspace list-build guidance, the cleaned single LinkedIn-sourced list-build path, Exa Company Search up to 100 results, scheduled agent `--target ACCOUNTS|LEADS`, paced HTTP Request column contracts, branch-aware LinkedIn sequence recipes, real agent soft-delete with associated-table handling, and research-table sequence handoff assignee config
182
182
  - `autotouch capabilities --output json --select list_builds` for documented list-build inputs such as geography IDs, company size buckets, profile language, and company IDs
183
183
  - `autotouch list-build inputs` and `autotouch list-build pricing` before creating durable list-build jobs
184
184
  - `autotouch list-build companies` and `autotouch list-build leads` for durable LinkedIn-sourced company and lead list builds with Smart Table-owned background workers, visible progress, and no user-owned LinkedIn connection requirement
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "autotouch-cli"
7
- version = "0.2.92"
7
+ version = "0.2.94"
8
8
  description = "Autotouch Smart Table CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes