autotouch-cli 0.2.25__tar.gz → 0.2.26__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.
- {autotouch_cli-0.2.25/autotouch_cli.egg-info → autotouch_cli-0.2.26}/PKG-INFO +64 -2
- autotouch_cli-0.2.25/docs/research-table/reference/autotouch-cli.md → autotouch_cli-0.2.26/autotouch_cli.egg-info/PKG-INFO +72 -1
- autotouch_cli-0.2.25/PKG-INFO → autotouch_cli-0.2.26/docs/research-table/reference/autotouch-cli.md +63 -10
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/pyproject.toml +1 -1
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/smart_table_cli.py +370 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/autotouch_cli.egg-info/SOURCES.txt +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/autotouch_cli.egg-info/dependency_links.txt +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/autotouch_cli.egg-info/entry_points.txt +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/autotouch_cli.egg-info/requires.txt +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/autotouch_cli.egg-info/top_level.txt +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/__init__.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/add_column_unique_index.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/attach_csv_import_leads_to_research_table.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/bundle_sequences_backend.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/check_agent_traces.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/check_column_mode.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/exit_terminal_leads_from_sequences.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/fetch_lead.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/fix_lead_titles_from_csv.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250106_add_column_position.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250108_fix_legacy_column_fields.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250109_add_user_fields_to_tables.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250117_add_call_logs_webhook_indexes.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250117_rename_call_logs_collection.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250119_create_leads_unique_email_index.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250123_add_filter_indexes.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250123_add_llm_responses_collection.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250128_migrate_user_ids_to_objectid.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250208_backfill_task_research_values.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250604_add_origin_indexes.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250608_cleanup_agent_metadata.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250608_rename_agent_metadata_to_metadata.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250922_add_activity_indexes.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250926_migrate_single_to_arrays.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250928_add_missing_timestamp_fields.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250929_add_task_join_indexes.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250929_add_task_join_indexes_safe.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250929_create_shared_phone_cache.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20251007_add_rows_position_id_index.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20251109_add_ttl_for_llm_and_preview_traces.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20260113_normalize_table_filter_operators.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20260113_set_user_permissions_user_admin.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20260204_sync_lead_owner_from_tasks.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20260303_add_webhook_subscription_collections.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20260305_force_formatter_autorun_on_source_update.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/migrate_org_user_credits.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/set_default_lead_status.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/update_lead_owner_from_tasks.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/reassign_sequence_owner.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/run_sidecar_orchestrator_demo.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/test_crm_company_policy.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/test_sequences_instantly_e2e.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/test_sequences_personal_e2e.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/test_task_error_logger.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/verify_azurite_voicemail.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/setup.cfg +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_contactout_custom.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_contactout_integration.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_contactout_multi_titles.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_contactout_pipeline.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_contactout_simple.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_contactout_v2_bulk.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_lead_required_fields.py +0 -0
- {autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/tests/test_phone_provider_pipeline.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: autotouch-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.26
|
|
4
4
|
Summary: Autotouch Smart Table CLI
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -37,12 +37,13 @@ Use this order when you are orienting in the CLI:
|
|
|
37
37
|
| verify whether a job is really done | `autotouch jobs get --job-id <JOB_ID>` |
|
|
38
38
|
| create projections from JSON output | `autotouch columns projections` |
|
|
39
39
|
| work with sequences/tasks | raw HTTP plus `docs/platform/external-workflows-api.md` |
|
|
40
|
+
| query/filter CRM leads and attached research | `autotouch leads query` then `autotouch leads research` |
|
|
40
41
|
|
|
41
42
|
### Operating model
|
|
42
43
|
|
|
43
44
|
- This file is the full CLI reference and the package readme published to PyPI.
|
|
44
45
|
- The installed package gives you CLI entrypoints and package metadata; do not assume there is a separate installed docs directory.
|
|
45
|
-
- Research-table APIs are the primary CLI surface today; workflow APIs (sequences/tasks) are still HTTP-first.
|
|
46
|
+
- Research-table APIs and read-only leads queries are the primary CLI surface today; workflow APIs (sequences/tasks) are still HTTP-first.
|
|
46
47
|
- For async operations, backend bulk-job state is authoritative; local terminal output is only a convenience layer.
|
|
47
48
|
- For staged or cost-sensitive runs, estimate first and prefer filtered scopes plus `firstN` or `run-next`.
|
|
48
49
|
|
|
@@ -128,6 +129,12 @@ Notes:
|
|
|
128
129
|
| `POST /api/tables/{table_id}/columns/{column_id}/stop` | `autotouch columns stop --table-id <TABLE_ID> --column-id <COLUMN_ID>` |
|
|
129
130
|
| `GET /api/bulk-jobs` | `autotouch jobs list --table-id <TABLE_ID> --column-id <COLUMN_ID> --limit 10` |
|
|
130
131
|
| `GET /api/bulk-jobs/{job_id}` | `autotouch jobs get --job-id <JOB_ID>` |
|
|
132
|
+
| `POST /api/leads/query` | `autotouch leads query --filter-file lead-filter.json --limit 50` |
|
|
133
|
+
| `POST /api/leads/query/count` | `autotouch leads count --filter-file lead-filter.json` |
|
|
134
|
+
| `POST /api/leads/query/stats` | `autotouch leads stats --filter-file lead-filter.json` |
|
|
135
|
+
| `POST /api/leads/query/research` | `autotouch leads research --lead-id <LEAD_ID> --source-table-id <TABLE_ID>` |
|
|
136
|
+
| `GET /api/leads/filters/metadata` | `autotouch leads filters-metadata` |
|
|
137
|
+
| `GET /api/leads/research-tables/available` | `autotouch leads research-tables` |
|
|
131
138
|
| `GET /api/tables/{table_id}/webhook` | `autotouch webhooks get --table-id <TABLE_ID>` |
|
|
132
139
|
| `POST /api/tables/{table_id}/webhook` | `autotouch webhooks rotate --table-id <TABLE_ID>` |
|
|
133
140
|
| `POST /api/webhooks/tables/{table_id}/ingest` | `autotouch webhooks ingest --table-id <TABLE_ID> --records-file records.json --webhook-token <WEBHOOK_TOKEN>` |
|
|
@@ -168,6 +175,61 @@ Signature controls for sequence payloads:
|
|
|
168
175
|
- `steps[].appendSignature` (optional, step-level) overrides signature behavior for a specific email step.
|
|
169
176
|
- Signature append is deterministic at send time when enabled for the step.
|
|
170
177
|
|
|
178
|
+
## Leads API coverage
|
|
179
|
+
|
|
180
|
+
The CLI now exposes the public read-only leads endpoints under `autotouch leads`.
|
|
181
|
+
|
|
182
|
+
Use this pattern:
|
|
183
|
+
|
|
184
|
+
1. `autotouch leads query` to page through leads, apply descriptor filters, and inspect `related_tables` / `research_summary`.
|
|
185
|
+
2. `autotouch leads research` when you need actual research field values for specific lead IDs from one source table.
|
|
186
|
+
3. `autotouch leads count` / `autotouch leads stats` when you need sizing before a downstream workflow.
|
|
187
|
+
|
|
188
|
+
Important contract notes:
|
|
189
|
+
- External callers should use `POST /api/leads/query` rather than the older `GET /api/leads` list route.
|
|
190
|
+
- `autotouch leads query` accepts the same descriptor payload shape as the backend:
|
|
191
|
+
- `filter`
|
|
192
|
+
- `search`
|
|
193
|
+
- `sort`
|
|
194
|
+
- `pagination`
|
|
195
|
+
- `scope`
|
|
196
|
+
- optional research context (`source_table_id`, `source_table_scope`, `related_tables_mode`)
|
|
197
|
+
- Research values are best treated as a follow-up call:
|
|
198
|
+
- `query` returns lead rows plus research linkage metadata
|
|
199
|
+
- `research` returns `research_data_by_id` keyed by lead id for one `source_table_id`
|
|
200
|
+
|
|
201
|
+
Examples:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
autotouch leads query \
|
|
205
|
+
--filter-json '{"root":{"kind":"rule","field":"status","operator":"eq","value":"new"}}' \
|
|
206
|
+
--limit 25
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
autotouch leads count \
|
|
211
|
+
--search "fintech" \
|
|
212
|
+
--scope org
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
autotouch leads stats \
|
|
217
|
+
--source-table-id <TABLE_ID> \
|
|
218
|
+
--source-table-scope company
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
autotouch leads research \
|
|
223
|
+
--lead-id <LEAD_ID_1> \
|
|
224
|
+
--lead-id <LEAD_ID_2> \
|
|
225
|
+
--source-table-id <TABLE_ID>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
autotouch leads filters-metadata
|
|
230
|
+
autotouch leads research-tables
|
|
231
|
+
```
|
|
232
|
+
|
|
171
233
|
## Bulk job status contract (authoritative run state)
|
|
172
234
|
|
|
173
235
|
Use bulk jobs as the source of truth for run lifecycle:
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: autotouch-cli
|
|
3
|
+
Version: 0.2.26
|
|
4
|
+
Summary: Autotouch Smart Table CLI
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: requests>=2.31.0
|
|
8
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
9
|
+
|
|
1
10
|
# Autotouch CLI Reference (`autotouch`)
|
|
2
11
|
|
|
3
12
|
This page documents the installable CLI for the Smart Table developer API.
|
|
@@ -28,12 +37,13 @@ Use this order when you are orienting in the CLI:
|
|
|
28
37
|
| verify whether a job is really done | `autotouch jobs get --job-id <JOB_ID>` |
|
|
29
38
|
| create projections from JSON output | `autotouch columns projections` |
|
|
30
39
|
| work with sequences/tasks | raw HTTP plus `docs/platform/external-workflows-api.md` |
|
|
40
|
+
| query/filter CRM leads and attached research | `autotouch leads query` then `autotouch leads research` |
|
|
31
41
|
|
|
32
42
|
### Operating model
|
|
33
43
|
|
|
34
44
|
- This file is the full CLI reference and the package readme published to PyPI.
|
|
35
45
|
- The installed package gives you CLI entrypoints and package metadata; do not assume there is a separate installed docs directory.
|
|
36
|
-
- Research-table APIs are the primary CLI surface today; workflow APIs (sequences/tasks) are still HTTP-first.
|
|
46
|
+
- Research-table APIs and read-only leads queries are the primary CLI surface today; workflow APIs (sequences/tasks) are still HTTP-first.
|
|
37
47
|
- For async operations, backend bulk-job state is authoritative; local terminal output is only a convenience layer.
|
|
38
48
|
- For staged or cost-sensitive runs, estimate first and prefer filtered scopes plus `firstN` or `run-next`.
|
|
39
49
|
|
|
@@ -119,6 +129,12 @@ Notes:
|
|
|
119
129
|
| `POST /api/tables/{table_id}/columns/{column_id}/stop` | `autotouch columns stop --table-id <TABLE_ID> --column-id <COLUMN_ID>` |
|
|
120
130
|
| `GET /api/bulk-jobs` | `autotouch jobs list --table-id <TABLE_ID> --column-id <COLUMN_ID> --limit 10` |
|
|
121
131
|
| `GET /api/bulk-jobs/{job_id}` | `autotouch jobs get --job-id <JOB_ID>` |
|
|
132
|
+
| `POST /api/leads/query` | `autotouch leads query --filter-file lead-filter.json --limit 50` |
|
|
133
|
+
| `POST /api/leads/query/count` | `autotouch leads count --filter-file lead-filter.json` |
|
|
134
|
+
| `POST /api/leads/query/stats` | `autotouch leads stats --filter-file lead-filter.json` |
|
|
135
|
+
| `POST /api/leads/query/research` | `autotouch leads research --lead-id <LEAD_ID> --source-table-id <TABLE_ID>` |
|
|
136
|
+
| `GET /api/leads/filters/metadata` | `autotouch leads filters-metadata` |
|
|
137
|
+
| `GET /api/leads/research-tables/available` | `autotouch leads research-tables` |
|
|
122
138
|
| `GET /api/tables/{table_id}/webhook` | `autotouch webhooks get --table-id <TABLE_ID>` |
|
|
123
139
|
| `POST /api/tables/{table_id}/webhook` | `autotouch webhooks rotate --table-id <TABLE_ID>` |
|
|
124
140
|
| `POST /api/webhooks/tables/{table_id}/ingest` | `autotouch webhooks ingest --table-id <TABLE_ID> --records-file records.json --webhook-token <WEBHOOK_TOKEN>` |
|
|
@@ -159,6 +175,61 @@ Signature controls for sequence payloads:
|
|
|
159
175
|
- `steps[].appendSignature` (optional, step-level) overrides signature behavior for a specific email step.
|
|
160
176
|
- Signature append is deterministic at send time when enabled for the step.
|
|
161
177
|
|
|
178
|
+
## Leads API coverage
|
|
179
|
+
|
|
180
|
+
The CLI now exposes the public read-only leads endpoints under `autotouch leads`.
|
|
181
|
+
|
|
182
|
+
Use this pattern:
|
|
183
|
+
|
|
184
|
+
1. `autotouch leads query` to page through leads, apply descriptor filters, and inspect `related_tables` / `research_summary`.
|
|
185
|
+
2. `autotouch leads research` when you need actual research field values for specific lead IDs from one source table.
|
|
186
|
+
3. `autotouch leads count` / `autotouch leads stats` when you need sizing before a downstream workflow.
|
|
187
|
+
|
|
188
|
+
Important contract notes:
|
|
189
|
+
- External callers should use `POST /api/leads/query` rather than the older `GET /api/leads` list route.
|
|
190
|
+
- `autotouch leads query` accepts the same descriptor payload shape as the backend:
|
|
191
|
+
- `filter`
|
|
192
|
+
- `search`
|
|
193
|
+
- `sort`
|
|
194
|
+
- `pagination`
|
|
195
|
+
- `scope`
|
|
196
|
+
- optional research context (`source_table_id`, `source_table_scope`, `related_tables_mode`)
|
|
197
|
+
- Research values are best treated as a follow-up call:
|
|
198
|
+
- `query` returns lead rows plus research linkage metadata
|
|
199
|
+
- `research` returns `research_data_by_id` keyed by lead id for one `source_table_id`
|
|
200
|
+
|
|
201
|
+
Examples:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
autotouch leads query \
|
|
205
|
+
--filter-json '{"root":{"kind":"rule","field":"status","operator":"eq","value":"new"}}' \
|
|
206
|
+
--limit 25
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
autotouch leads count \
|
|
211
|
+
--search "fintech" \
|
|
212
|
+
--scope org
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
autotouch leads stats \
|
|
217
|
+
--source-table-id <TABLE_ID> \
|
|
218
|
+
--source-table-scope company
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
autotouch leads research \
|
|
223
|
+
--lead-id <LEAD_ID_1> \
|
|
224
|
+
--lead-id <LEAD_ID_2> \
|
|
225
|
+
--source-table-id <TABLE_ID>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
autotouch leads filters-metadata
|
|
230
|
+
autotouch leads research-tables
|
|
231
|
+
```
|
|
232
|
+
|
|
162
233
|
## Bulk job status contract (authoritative run state)
|
|
163
234
|
|
|
164
235
|
Use bulk jobs as the source of truth for run lifecycle:
|
autotouch_cli-0.2.25/PKG-INFO → autotouch_cli-0.2.26/docs/research-table/reference/autotouch-cli.md
RENAMED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: autotouch-cli
|
|
3
|
-
Version: 0.2.25
|
|
4
|
-
Summary: Autotouch Smart Table CLI
|
|
5
|
-
Requires-Python: >=3.9
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: requests>=2.31.0
|
|
8
|
-
Requires-Dist: python-dotenv>=1.0.0
|
|
9
|
-
|
|
10
1
|
# Autotouch CLI Reference (`autotouch`)
|
|
11
2
|
|
|
12
3
|
This page documents the installable CLI for the Smart Table developer API.
|
|
@@ -37,12 +28,13 @@ Use this order when you are orienting in the CLI:
|
|
|
37
28
|
| verify whether a job is really done | `autotouch jobs get --job-id <JOB_ID>` |
|
|
38
29
|
| create projections from JSON output | `autotouch columns projections` |
|
|
39
30
|
| work with sequences/tasks | raw HTTP plus `docs/platform/external-workflows-api.md` |
|
|
31
|
+
| query/filter CRM leads and attached research | `autotouch leads query` then `autotouch leads research` |
|
|
40
32
|
|
|
41
33
|
### Operating model
|
|
42
34
|
|
|
43
35
|
- This file is the full CLI reference and the package readme published to PyPI.
|
|
44
36
|
- The installed package gives you CLI entrypoints and package metadata; do not assume there is a separate installed docs directory.
|
|
45
|
-
- Research-table APIs are the primary CLI surface today; workflow APIs (sequences/tasks) are still HTTP-first.
|
|
37
|
+
- Research-table APIs and read-only leads queries are the primary CLI surface today; workflow APIs (sequences/tasks) are still HTTP-first.
|
|
46
38
|
- For async operations, backend bulk-job state is authoritative; local terminal output is only a convenience layer.
|
|
47
39
|
- For staged or cost-sensitive runs, estimate first and prefer filtered scopes plus `firstN` or `run-next`.
|
|
48
40
|
|
|
@@ -128,6 +120,12 @@ Notes:
|
|
|
128
120
|
| `POST /api/tables/{table_id}/columns/{column_id}/stop` | `autotouch columns stop --table-id <TABLE_ID> --column-id <COLUMN_ID>` |
|
|
129
121
|
| `GET /api/bulk-jobs` | `autotouch jobs list --table-id <TABLE_ID> --column-id <COLUMN_ID> --limit 10` |
|
|
130
122
|
| `GET /api/bulk-jobs/{job_id}` | `autotouch jobs get --job-id <JOB_ID>` |
|
|
123
|
+
| `POST /api/leads/query` | `autotouch leads query --filter-file lead-filter.json --limit 50` |
|
|
124
|
+
| `POST /api/leads/query/count` | `autotouch leads count --filter-file lead-filter.json` |
|
|
125
|
+
| `POST /api/leads/query/stats` | `autotouch leads stats --filter-file lead-filter.json` |
|
|
126
|
+
| `POST /api/leads/query/research` | `autotouch leads research --lead-id <LEAD_ID> --source-table-id <TABLE_ID>` |
|
|
127
|
+
| `GET /api/leads/filters/metadata` | `autotouch leads filters-metadata` |
|
|
128
|
+
| `GET /api/leads/research-tables/available` | `autotouch leads research-tables` |
|
|
131
129
|
| `GET /api/tables/{table_id}/webhook` | `autotouch webhooks get --table-id <TABLE_ID>` |
|
|
132
130
|
| `POST /api/tables/{table_id}/webhook` | `autotouch webhooks rotate --table-id <TABLE_ID>` |
|
|
133
131
|
| `POST /api/webhooks/tables/{table_id}/ingest` | `autotouch webhooks ingest --table-id <TABLE_ID> --records-file records.json --webhook-token <WEBHOOK_TOKEN>` |
|
|
@@ -168,6 +166,61 @@ Signature controls for sequence payloads:
|
|
|
168
166
|
- `steps[].appendSignature` (optional, step-level) overrides signature behavior for a specific email step.
|
|
169
167
|
- Signature append is deterministic at send time when enabled for the step.
|
|
170
168
|
|
|
169
|
+
## Leads API coverage
|
|
170
|
+
|
|
171
|
+
The CLI now exposes the public read-only leads endpoints under `autotouch leads`.
|
|
172
|
+
|
|
173
|
+
Use this pattern:
|
|
174
|
+
|
|
175
|
+
1. `autotouch leads query` to page through leads, apply descriptor filters, and inspect `related_tables` / `research_summary`.
|
|
176
|
+
2. `autotouch leads research` when you need actual research field values for specific lead IDs from one source table.
|
|
177
|
+
3. `autotouch leads count` / `autotouch leads stats` when you need sizing before a downstream workflow.
|
|
178
|
+
|
|
179
|
+
Important contract notes:
|
|
180
|
+
- External callers should use `POST /api/leads/query` rather than the older `GET /api/leads` list route.
|
|
181
|
+
- `autotouch leads query` accepts the same descriptor payload shape as the backend:
|
|
182
|
+
- `filter`
|
|
183
|
+
- `search`
|
|
184
|
+
- `sort`
|
|
185
|
+
- `pagination`
|
|
186
|
+
- `scope`
|
|
187
|
+
- optional research context (`source_table_id`, `source_table_scope`, `related_tables_mode`)
|
|
188
|
+
- Research values are best treated as a follow-up call:
|
|
189
|
+
- `query` returns lead rows plus research linkage metadata
|
|
190
|
+
- `research` returns `research_data_by_id` keyed by lead id for one `source_table_id`
|
|
191
|
+
|
|
192
|
+
Examples:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
autotouch leads query \
|
|
196
|
+
--filter-json '{"root":{"kind":"rule","field":"status","operator":"eq","value":"new"}}' \
|
|
197
|
+
--limit 25
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
autotouch leads count \
|
|
202
|
+
--search "fintech" \
|
|
203
|
+
--scope org
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
autotouch leads stats \
|
|
208
|
+
--source-table-id <TABLE_ID> \
|
|
209
|
+
--source-table-scope company
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
autotouch leads research \
|
|
214
|
+
--lead-id <LEAD_ID_1> \
|
|
215
|
+
--lead-id <LEAD_ID_2> \
|
|
216
|
+
--source-table-id <TABLE_ID>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
autotouch leads filters-metadata
|
|
221
|
+
autotouch leads research-tables
|
|
222
|
+
```
|
|
223
|
+
|
|
171
224
|
## Bulk job status contract (authoritative run state)
|
|
172
225
|
|
|
173
226
|
Use bulk jobs as the source of truth for run lifecycle:
|
|
@@ -998,6 +998,198 @@ def _normalize_run_payload(args: argparse.Namespace) -> Dict[str, Any]:
|
|
|
998
998
|
return payload
|
|
999
999
|
|
|
1000
1000
|
|
|
1001
|
+
def _normalize_filter_payload(filter_payload: Any) -> Any:
|
|
1002
|
+
if filter_payload is None:
|
|
1003
|
+
return None
|
|
1004
|
+
if isinstance(filter_payload, dict):
|
|
1005
|
+
return filter_payload
|
|
1006
|
+
print("ERROR: leads filter payload must be a JSON object", file=sys.stderr)
|
|
1007
|
+
sys.exit(2)
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
def _normalize_sort_payload(sort_payload: Any) -> Any:
|
|
1011
|
+
if sort_payload is None:
|
|
1012
|
+
return None
|
|
1013
|
+
if isinstance(sort_payload, list):
|
|
1014
|
+
return sort_payload
|
|
1015
|
+
if isinstance(sort_payload, dict):
|
|
1016
|
+
return [sort_payload]
|
|
1017
|
+
print("ERROR: leads sort payload must be a JSON object or array", file=sys.stderr)
|
|
1018
|
+
sys.exit(2)
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
def _normalize_leads_query_payload(args: argparse.Namespace) -> Dict[str, Any]:
|
|
1022
|
+
explicit_payload = _load_json_input(
|
|
1023
|
+
inline_json=getattr(args, "data_json", None),
|
|
1024
|
+
file_path=getattr(args, "data_file", None),
|
|
1025
|
+
context="data",
|
|
1026
|
+
default=None,
|
|
1027
|
+
)
|
|
1028
|
+
if explicit_payload is not None:
|
|
1029
|
+
if not isinstance(explicit_payload, dict):
|
|
1030
|
+
print("ERROR: leads payload must be a JSON object", file=sys.stderr)
|
|
1031
|
+
sys.exit(2)
|
|
1032
|
+
return explicit_payload
|
|
1033
|
+
|
|
1034
|
+
payload: Dict[str, Any] = {}
|
|
1035
|
+
|
|
1036
|
+
filter_payload = _normalize_filter_payload(
|
|
1037
|
+
_load_json_input(
|
|
1038
|
+
inline_json=getattr(args, "filter_json", None),
|
|
1039
|
+
file_path=getattr(args, "filter_file", None),
|
|
1040
|
+
context="filter",
|
|
1041
|
+
default=None,
|
|
1042
|
+
)
|
|
1043
|
+
)
|
|
1044
|
+
if filter_payload is not None:
|
|
1045
|
+
payload["filter"] = filter_payload
|
|
1046
|
+
|
|
1047
|
+
sort_payload = _normalize_sort_payload(
|
|
1048
|
+
_load_json_input(
|
|
1049
|
+
inline_json=getattr(args, "sort_json", None),
|
|
1050
|
+
file_path=getattr(args, "sort_file", None),
|
|
1051
|
+
context="sort",
|
|
1052
|
+
default=None,
|
|
1053
|
+
)
|
|
1054
|
+
)
|
|
1055
|
+
if sort_payload is not None:
|
|
1056
|
+
payload["sort"] = sort_payload
|
|
1057
|
+
|
|
1058
|
+
search = str(getattr(args, "search", "") or "").strip()
|
|
1059
|
+
if search:
|
|
1060
|
+
payload["search"] = search
|
|
1061
|
+
|
|
1062
|
+
pagination: Dict[str, Any] = {}
|
|
1063
|
+
limit = getattr(args, "limit", None)
|
|
1064
|
+
if limit is not None:
|
|
1065
|
+
pagination["limit"] = int(limit)
|
|
1066
|
+
cursor = str(getattr(args, "cursor", "") or "").strip()
|
|
1067
|
+
if cursor:
|
|
1068
|
+
pagination["cursor"] = cursor
|
|
1069
|
+
if pagination:
|
|
1070
|
+
payload["pagination"] = pagination
|
|
1071
|
+
|
|
1072
|
+
scope = str(getattr(args, "scope", "") or "").strip()
|
|
1073
|
+
if scope:
|
|
1074
|
+
payload["scope"] = scope
|
|
1075
|
+
|
|
1076
|
+
source_table_id = str(getattr(args, "source_table_id", "") or "").strip()
|
|
1077
|
+
if source_table_id:
|
|
1078
|
+
payload["source_table_id"] = source_table_id
|
|
1079
|
+
|
|
1080
|
+
source_table_scope = str(getattr(args, "source_table_scope", "") or "").strip()
|
|
1081
|
+
if source_table_scope:
|
|
1082
|
+
payload["source_table_scope"] = source_table_scope
|
|
1083
|
+
|
|
1084
|
+
related_tables_mode = str(getattr(args, "related_tables_mode", "") or "").strip()
|
|
1085
|
+
if related_tables_mode:
|
|
1086
|
+
payload["related_tables_mode"] = related_tables_mode
|
|
1087
|
+
|
|
1088
|
+
if bool(getattr(args, "include_research_data", False)):
|
|
1089
|
+
payload["include_research_data"] = True
|
|
1090
|
+
|
|
1091
|
+
if bool(getattr(args, "include_placeholder_leads", False)):
|
|
1092
|
+
payload["include_placeholder_leads"] = True
|
|
1093
|
+
|
|
1094
|
+
return payload
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
def _collect_cli_string_values(raw_values: Optional[List[str]]) -> List[str]:
|
|
1098
|
+
values: List[str] = []
|
|
1099
|
+
for raw in raw_values or []:
|
|
1100
|
+
for piece in str(raw).replace("\n", ",").split(","):
|
|
1101
|
+
normalized = str(piece or "").strip()
|
|
1102
|
+
if normalized:
|
|
1103
|
+
values.append(normalized)
|
|
1104
|
+
return values
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
def _parse_string_list_payload(payload: Any, *, context: str, key: Optional[str] = None) -> List[str]:
|
|
1108
|
+
raw_values: List[Any]
|
|
1109
|
+
if isinstance(payload, list):
|
|
1110
|
+
raw_values = payload
|
|
1111
|
+
elif isinstance(payload, dict) and key and isinstance(payload.get(key), list):
|
|
1112
|
+
raw_values = payload.get(key) or []
|
|
1113
|
+
else:
|
|
1114
|
+
suffix = f" or object with '{key}' array" if key else ""
|
|
1115
|
+
print(f"ERROR: {context} must be a JSON array{suffix}", file=sys.stderr)
|
|
1116
|
+
sys.exit(2)
|
|
1117
|
+
|
|
1118
|
+
values: List[str] = []
|
|
1119
|
+
for item in raw_values:
|
|
1120
|
+
normalized = str(item or "").strip()
|
|
1121
|
+
if normalized:
|
|
1122
|
+
values.append(normalized)
|
|
1123
|
+
return values
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
def _load_string_list_input(
|
|
1127
|
+
*,
|
|
1128
|
+
cli_values: Optional[List[str]],
|
|
1129
|
+
inline_json: Optional[str],
|
|
1130
|
+
file_path: Optional[str],
|
|
1131
|
+
context: str,
|
|
1132
|
+
key: Optional[str] = None,
|
|
1133
|
+
) -> List[str]:
|
|
1134
|
+
values = _collect_cli_string_values(cli_values)
|
|
1135
|
+
payload = _load_json_input(
|
|
1136
|
+
inline_json=inline_json,
|
|
1137
|
+
file_path=file_path,
|
|
1138
|
+
context=context,
|
|
1139
|
+
default=None,
|
|
1140
|
+
)
|
|
1141
|
+
if payload is not None:
|
|
1142
|
+
values.extend(_parse_string_list_payload(payload, context=context, key=key))
|
|
1143
|
+
return _dedupe_keep_order(values)
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
def _normalize_leads_research_payload(args: argparse.Namespace) -> Dict[str, Any]:
|
|
1147
|
+
explicit_payload = _load_json_input(
|
|
1148
|
+
inline_json=getattr(args, "data_json", None),
|
|
1149
|
+
file_path=getattr(args, "data_file", None),
|
|
1150
|
+
context="data",
|
|
1151
|
+
default=None,
|
|
1152
|
+
)
|
|
1153
|
+
if explicit_payload is not None:
|
|
1154
|
+
if not isinstance(explicit_payload, dict):
|
|
1155
|
+
print("ERROR: leads research payload must be a JSON object", file=sys.stderr)
|
|
1156
|
+
sys.exit(2)
|
|
1157
|
+
return explicit_payload
|
|
1158
|
+
|
|
1159
|
+
lead_ids = _load_string_list_input(
|
|
1160
|
+
cli_values=getattr(args, "lead_id", None),
|
|
1161
|
+
inline_json=getattr(args, "lead_ids_json", None),
|
|
1162
|
+
file_path=getattr(args, "lead_ids_file", None),
|
|
1163
|
+
context="lead_ids",
|
|
1164
|
+
key="lead_ids",
|
|
1165
|
+
)
|
|
1166
|
+
if not lead_ids:
|
|
1167
|
+
print("ERROR: provide at least one lead id", file=sys.stderr)
|
|
1168
|
+
sys.exit(2)
|
|
1169
|
+
|
|
1170
|
+
source_table_id = str(getattr(args, "source_table_id", "") or "").strip()
|
|
1171
|
+
if not source_table_id:
|
|
1172
|
+
print("ERROR: --source-table-id is required", file=sys.stderr)
|
|
1173
|
+
sys.exit(2)
|
|
1174
|
+
|
|
1175
|
+
payload: Dict[str, Any] = {
|
|
1176
|
+
"lead_ids": lead_ids,
|
|
1177
|
+
"source_table_id": source_table_id,
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
field_ids = _load_string_list_input(
|
|
1181
|
+
cli_values=getattr(args, "field_id", None),
|
|
1182
|
+
inline_json=getattr(args, "field_ids_json", None),
|
|
1183
|
+
file_path=getattr(args, "field_ids_file", None),
|
|
1184
|
+
context="field_ids",
|
|
1185
|
+
key="field_ids",
|
|
1186
|
+
)
|
|
1187
|
+
if field_ids:
|
|
1188
|
+
payload["field_ids"] = field_ids
|
|
1189
|
+
|
|
1190
|
+
return payload
|
|
1191
|
+
|
|
1192
|
+
|
|
1001
1193
|
def _resolve_column_key(
|
|
1002
1194
|
*,
|
|
1003
1195
|
table_id: str,
|
|
@@ -3786,6 +3978,98 @@ def cmd_jobs_watch(args: argparse.Namespace) -> None:
|
|
|
3786
3978
|
sys.exit(1)
|
|
3787
3979
|
|
|
3788
3980
|
|
|
3981
|
+
def cmd_leads_query(args: argparse.Namespace) -> None:
|
|
3982
|
+
token = _resolve_token(args.token, required=True)
|
|
3983
|
+
payload = _normalize_leads_query_payload(args)
|
|
3984
|
+
data = _request_api(
|
|
3985
|
+
"POST",
|
|
3986
|
+
"/api/leads/query",
|
|
3987
|
+
base_url=args.base_url,
|
|
3988
|
+
token=token,
|
|
3989
|
+
use_x_api_key=args.use_x_api_key,
|
|
3990
|
+
payload=payload,
|
|
3991
|
+
timeout=args.timeout,
|
|
3992
|
+
verbose=args.verbose,
|
|
3993
|
+
)
|
|
3994
|
+
_print_json(data, compact=args.compact)
|
|
3995
|
+
|
|
3996
|
+
|
|
3997
|
+
def cmd_leads_count(args: argparse.Namespace) -> None:
|
|
3998
|
+
token = _resolve_token(args.token, required=True)
|
|
3999
|
+
payload = _normalize_leads_query_payload(args)
|
|
4000
|
+
data = _request_api(
|
|
4001
|
+
"POST",
|
|
4002
|
+
"/api/leads/query/count",
|
|
4003
|
+
base_url=args.base_url,
|
|
4004
|
+
token=token,
|
|
4005
|
+
use_x_api_key=args.use_x_api_key,
|
|
4006
|
+
payload=payload,
|
|
4007
|
+
timeout=args.timeout,
|
|
4008
|
+
verbose=args.verbose,
|
|
4009
|
+
)
|
|
4010
|
+
_print_json(data, compact=args.compact)
|
|
4011
|
+
|
|
4012
|
+
|
|
4013
|
+
def cmd_leads_stats(args: argparse.Namespace) -> None:
|
|
4014
|
+
token = _resolve_token(args.token, required=True)
|
|
4015
|
+
payload = _normalize_leads_query_payload(args)
|
|
4016
|
+
data = _request_api(
|
|
4017
|
+
"POST",
|
|
4018
|
+
"/api/leads/query/stats",
|
|
4019
|
+
base_url=args.base_url,
|
|
4020
|
+
token=token,
|
|
4021
|
+
use_x_api_key=args.use_x_api_key,
|
|
4022
|
+
payload=payload,
|
|
4023
|
+
timeout=args.timeout,
|
|
4024
|
+
verbose=args.verbose,
|
|
4025
|
+
)
|
|
4026
|
+
_print_json(data, compact=args.compact)
|
|
4027
|
+
|
|
4028
|
+
|
|
4029
|
+
def cmd_leads_research(args: argparse.Namespace) -> None:
|
|
4030
|
+
token = _resolve_token(args.token, required=True)
|
|
4031
|
+
payload = _normalize_leads_research_payload(args)
|
|
4032
|
+
data = _request_api(
|
|
4033
|
+
"POST",
|
|
4034
|
+
"/api/leads/query/research",
|
|
4035
|
+
base_url=args.base_url,
|
|
4036
|
+
token=token,
|
|
4037
|
+
use_x_api_key=args.use_x_api_key,
|
|
4038
|
+
payload=payload,
|
|
4039
|
+
timeout=args.timeout,
|
|
4040
|
+
verbose=args.verbose,
|
|
4041
|
+
)
|
|
4042
|
+
_print_json(data, compact=args.compact)
|
|
4043
|
+
|
|
4044
|
+
|
|
4045
|
+
def cmd_leads_filters_metadata(args: argparse.Namespace) -> None:
|
|
4046
|
+
token = _resolve_token(args.token, required=True)
|
|
4047
|
+
data = _request_api(
|
|
4048
|
+
"GET",
|
|
4049
|
+
"/api/leads/filters/metadata",
|
|
4050
|
+
base_url=args.base_url,
|
|
4051
|
+
token=token,
|
|
4052
|
+
use_x_api_key=args.use_x_api_key,
|
|
4053
|
+
timeout=args.timeout,
|
|
4054
|
+
verbose=args.verbose,
|
|
4055
|
+
)
|
|
4056
|
+
_print_json(data, compact=args.compact)
|
|
4057
|
+
|
|
4058
|
+
|
|
4059
|
+
def cmd_leads_research_tables(args: argparse.Namespace) -> None:
|
|
4060
|
+
token = _resolve_token(args.token, required=True)
|
|
4061
|
+
data = _request_api(
|
|
4062
|
+
"GET",
|
|
4063
|
+
"/api/leads/research-tables/available",
|
|
4064
|
+
base_url=args.base_url,
|
|
4065
|
+
token=token,
|
|
4066
|
+
use_x_api_key=args.use_x_api_key,
|
|
4067
|
+
timeout=args.timeout,
|
|
4068
|
+
verbose=args.verbose,
|
|
4069
|
+
)
|
|
4070
|
+
_print_json(data, compact=args.compact)
|
|
4071
|
+
|
|
4072
|
+
|
|
3789
4073
|
def cmd_webhooks_get(args: argparse.Namespace) -> None:
|
|
3790
4074
|
token = _resolve_token(args.token, required=True)
|
|
3791
4075
|
data = _request_api(
|
|
@@ -4177,6 +4461,60 @@ def _add_run_execution_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
4177
4461
|
parser.add_argument("--fail-on-partial", action="store_true", help="Exit non-zero when final status is partial")
|
|
4178
4462
|
|
|
4179
4463
|
|
|
4464
|
+
def _add_leads_query_arguments(parser: argparse.ArgumentParser) -> None:
|
|
4465
|
+
parser.add_argument("--data-json", help="Explicit leads query payload JSON")
|
|
4466
|
+
parser.add_argument("--data-file", help="Path to leads query payload JSON file")
|
|
4467
|
+
parser.add_argument("--filter-json", help="Filter descriptor JSON object")
|
|
4468
|
+
parser.add_argument("--filter-file", help="Path to filter descriptor JSON file")
|
|
4469
|
+
parser.add_argument("--sort-json", help="Sort spec JSON object/array")
|
|
4470
|
+
parser.add_argument("--sort-file", help="Path to sort spec JSON file")
|
|
4471
|
+
parser.add_argument("--search", help="Free-text lead search")
|
|
4472
|
+
parser.add_argument("--limit", type=int, help="Pagination limit")
|
|
4473
|
+
parser.add_argument("--cursor", help="Pagination cursor")
|
|
4474
|
+
parser.add_argument("--scope", choices=["org", "user"], help="Lead scope")
|
|
4475
|
+
parser.add_argument("--source-table-id", help="Research table id used for scope/research context")
|
|
4476
|
+
parser.add_argument(
|
|
4477
|
+
"--source-table-scope",
|
|
4478
|
+
choices=["company", "lead"],
|
|
4479
|
+
help="Research scope resolution mode",
|
|
4480
|
+
)
|
|
4481
|
+
parser.add_argument(
|
|
4482
|
+
"--related-tables-mode",
|
|
4483
|
+
choices=["linked", "direct", "none"],
|
|
4484
|
+
help="How related_tables should be populated",
|
|
4485
|
+
)
|
|
4486
|
+
parser.add_argument(
|
|
4487
|
+
"--include-research-data",
|
|
4488
|
+
action="store_true",
|
|
4489
|
+
help="Inline research_data when --source-table-id is provided",
|
|
4490
|
+
)
|
|
4491
|
+
parser.add_argument(
|
|
4492
|
+
"--include-placeholder-leads",
|
|
4493
|
+
action="store_true",
|
|
4494
|
+
help="Include placeholder/incomplete lead records",
|
|
4495
|
+
)
|
|
4496
|
+
|
|
4497
|
+
|
|
4498
|
+
def _add_leads_research_arguments(parser: argparse.ArgumentParser) -> None:
|
|
4499
|
+
parser.add_argument("--data-json", help="Explicit leads research payload JSON")
|
|
4500
|
+
parser.add_argument("--data-file", help="Path to leads research payload JSON file")
|
|
4501
|
+
parser.add_argument(
|
|
4502
|
+
"--lead-id",
|
|
4503
|
+
action="append",
|
|
4504
|
+
help="Lead id (repeatable; comma-separated also supported)",
|
|
4505
|
+
)
|
|
4506
|
+
parser.add_argument("--lead-ids-json", help="JSON array or object with lead_ids[]")
|
|
4507
|
+
parser.add_argument("--lead-ids-file", help="Path to JSON file with lead_ids[]")
|
|
4508
|
+
parser.add_argument("--source-table-id", help="Research table id")
|
|
4509
|
+
parser.add_argument(
|
|
4510
|
+
"--field-id",
|
|
4511
|
+
action="append",
|
|
4512
|
+
help="Research field/column id to include (repeatable; comma-separated also supported)",
|
|
4513
|
+
)
|
|
4514
|
+
parser.add_argument("--field-ids-json", help="JSON array or object with field_ids[]")
|
|
4515
|
+
parser.add_argument("--field-ids-file", help="Path to JSON file with field_ids[]")
|
|
4516
|
+
|
|
4517
|
+
|
|
4180
4518
|
def build_parser() -> argparse.ArgumentParser:
|
|
4181
4519
|
p = argparse.ArgumentParser(prog="autotouch", description="Smart Table CLI")
|
|
4182
4520
|
sub = p.add_subparsers(dest="cmd", required=True)
|
|
@@ -4543,6 +4881,38 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
4543
4881
|
pcre.add_argument("--compact", action="store_true", help="Print compact JSON")
|
|
4544
4882
|
pcre.set_defaults(func=cmd_columns_recipe)
|
|
4545
4883
|
|
|
4884
|
+
# leads
|
|
4885
|
+
pl = sub.add_parser("leads", help="Read-only leads query operations")
|
|
4886
|
+
leads_sub = pl.add_subparsers(dest="leads_cmd", required=True)
|
|
4887
|
+
|
|
4888
|
+
plq = leads_sub.add_parser("query", help="Query/filter leads with descriptor payloads")
|
|
4889
|
+
_add_leads_query_arguments(plq)
|
|
4890
|
+
_add_api_common_arguments(plq)
|
|
4891
|
+
plq.set_defaults(func=cmd_leads_query)
|
|
4892
|
+
|
|
4893
|
+
plc = leads_sub.add_parser("count", help="Count leads matching a query payload")
|
|
4894
|
+
_add_leads_query_arguments(plc)
|
|
4895
|
+
_add_api_common_arguments(plc)
|
|
4896
|
+
plc.set_defaults(func=cmd_leads_count)
|
|
4897
|
+
|
|
4898
|
+
pls = leads_sub.add_parser("stats", help="Aggregate stats for leads matching a query payload")
|
|
4899
|
+
_add_leads_query_arguments(pls)
|
|
4900
|
+
_add_api_common_arguments(pls)
|
|
4901
|
+
pls.set_defaults(func=cmd_leads_stats)
|
|
4902
|
+
|
|
4903
|
+
plr = leads_sub.add_parser("research", help="Fetch research row data for specific lead ids")
|
|
4904
|
+
_add_leads_research_arguments(plr)
|
|
4905
|
+
_add_api_common_arguments(plr)
|
|
4906
|
+
plr.set_defaults(func=cmd_leads_research)
|
|
4907
|
+
|
|
4908
|
+
plf = leads_sub.add_parser("filters-metadata", help="List filterable lead fields and research columns")
|
|
4909
|
+
_add_api_common_arguments(plf)
|
|
4910
|
+
plf.set_defaults(func=cmd_leads_filters_metadata)
|
|
4911
|
+
|
|
4912
|
+
plrt = leads_sub.add_parser("research-tables", help="List research tables available for lead lookups")
|
|
4913
|
+
_add_api_common_arguments(plrt)
|
|
4914
|
+
plrt.set_defaults(func=cmd_leads_research_tables)
|
|
4915
|
+
|
|
4546
4916
|
# jobs
|
|
4547
4917
|
pj = sub.add_parser("jobs", help="Bulk job operations")
|
|
4548
4918
|
jobs_sub = pj.add_subparsers(dest="jobs_cmd", required=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/attach_csv_import_leads_to_research_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250106_add_column_position.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250123_add_filter_indexes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250604_add_origin_indexes.py
RENAMED
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250608_cleanup_agent_metadata.py
RENAMED
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250922_add_activity_indexes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/20250929_add_task_join_indexes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/migrate_org_user_credits.py
RENAMED
|
File without changes
|
|
File without changes
|
{autotouch_cli-0.2.25 → autotouch_cli-0.2.26}/scripts/migrations/update_lead_owner_from_tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|