autotouch-cli 0.2.20__tar.gz → 0.2.22__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.20 → autotouch_cli-0.2.22}/PKG-INFO +129 -5
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/autotouch_cli.egg-info/PKG-INFO +129 -5
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/autotouch_cli.egg-info/SOURCES.txt +1 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/docs/research-table/reference/autotouch-cli-pypi.md +128 -4
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/pyproject.toml +1 -1
- autotouch_cli-0.2.22/scripts/migrations/20260305_force_formatter_autorun_on_source_update.py +98 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/smart_table_cli.py +937 -1
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/autotouch_cli.egg-info/dependency_links.txt +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/autotouch_cli.egg-info/entry_points.txt +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/autotouch_cli.egg-info/requires.txt +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/autotouch_cli.egg-info/top_level.txt +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/__init__.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/add_column_unique_index.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/attach_csv_import_leads_to_research_table.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/bundle_sequences_backend.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/check_agent_traces.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/check_column_mode.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/exit_terminal_leads_from_sequences.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/fetch_lead.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/fix_lead_titles_from_csv.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250106_add_column_position.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250108_fix_legacy_column_fields.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250109_add_user_fields_to_tables.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250117_add_call_logs_webhook_indexes.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250117_rename_call_logs_collection.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250119_create_leads_unique_email_index.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250123_add_filter_indexes.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250123_add_llm_responses_collection.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250128_migrate_user_ids_to_objectid.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250208_backfill_task_research_values.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250604_add_origin_indexes.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250608_cleanup_agent_metadata.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250608_rename_agent_metadata_to_metadata.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250922_add_activity_indexes.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250926_migrate_single_to_arrays.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250928_add_missing_timestamp_fields.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250929_add_task_join_indexes.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250929_add_task_join_indexes_safe.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20250929_create_shared_phone_cache.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20251007_add_rows_position_id_index.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20251109_add_ttl_for_llm_and_preview_traces.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20260113_normalize_table_filter_operators.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20260113_set_user_permissions_user_admin.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20260204_sync_lead_owner_from_tasks.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/20260303_add_webhook_subscription_collections.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/migrate_org_user_credits.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/set_default_lead_status.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/migrations/update_lead_owner_from_tasks.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/reassign_sequence_owner.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/run_sidecar_orchestrator_demo.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/test_crm_company_policy.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/test_sequences_instantly_e2e.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/test_sequences_personal_e2e.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/test_task_error_logger.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/scripts/verify_azurite_voicemail.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/setup.cfg +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_contactout_custom.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_contactout_integration.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_contactout_multi_titles.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_contactout_pipeline.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_contactout_simple.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_contactout_v2_bulk.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/tests/test_lead_required_fields.py +0 -0
- {autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/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.22
|
|
4
4
|
Summary: Autotouch Smart Table CLI
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -72,12 +72,12 @@ Reference:
|
|
|
72
72
|
# 1) Verify target table exists and copy the exact id
|
|
73
73
|
autotouch tables list --view-mode org --output human
|
|
74
74
|
|
|
75
|
-
# 2)
|
|
75
|
+
# 2) Validate server-side CSV parse/shape (no write)
|
|
76
76
|
autotouch rows import-csv \
|
|
77
77
|
--table-id <TABLE_ID> \
|
|
78
78
|
--confirm-table-id <TABLE_ID> \
|
|
79
79
|
--file contacts.csv \
|
|
80
|
-
--
|
|
80
|
+
--validate-only \
|
|
81
81
|
--output json
|
|
82
82
|
```
|
|
83
83
|
|
|
@@ -101,7 +101,56 @@ Notes:
|
|
|
101
101
|
- `--transport optimized` is default (`/import-optimized`).
|
|
102
102
|
- `--wait` polls import status to terminal state.
|
|
103
103
|
- `--checkpoint-file` stores state and blocks accidental duplicate re-imports.
|
|
104
|
+
- `--validate-only` validates CSV parse/shape on server without writing rows.
|
|
105
|
+
- Blacklist controls on optimized import:
|
|
106
|
+
- company-domain filtering is ON by default
|
|
107
|
+
- email filtering is OFF by default
|
|
108
|
+
- disable company filtering with `--no-check-company-blacklist`
|
|
109
|
+
- enable email filtering with `--check-email-blacklist`
|
|
110
|
+
- Safety assertions:
|
|
111
|
+
- `--expected-rows <N>`
|
|
112
|
+
- `--require-columns col_a,col_b`
|
|
113
|
+
- `--duplicate-key col_a,col_b`
|
|
114
|
+
- `--require-non-empty key:ratio`
|
|
115
|
+
- For async imports with `--wait`, assertions are rechecked postflight via task manifest verification.
|
|
104
116
|
- Use `--allow-reimport` if you intentionally want to run the same file again.
|
|
117
|
+
- Import responses include `blacklist_summary` with company/email `skipped_count` and `enforced` flags.
|
|
118
|
+
|
|
119
|
+
Example enabling both company and email enforcement:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
autotouch rows import-csv \
|
|
123
|
+
--table-id <TABLE_ID> \
|
|
124
|
+
--confirm-table-id <TABLE_ID> \
|
|
125
|
+
--file contacts.csv \
|
|
126
|
+
--checkpoint-file .autotouch-import.json \
|
|
127
|
+
--check-email-blacklist \
|
|
128
|
+
--wait \
|
|
129
|
+
--output json
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Manage blacklist entries (native CLI, admin identity required):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# List current entries
|
|
136
|
+
autotouch blacklist list --type-filter all --limit 100
|
|
137
|
+
|
|
138
|
+
# Add entries
|
|
139
|
+
autotouch blacklist add --type domain --value competitor.com --reason "Do not contact"
|
|
140
|
+
autotouch blacklist add --type email --value blocked@example.com --reason "Unsubscribed"
|
|
141
|
+
|
|
142
|
+
# Bulk-import entries from CSV/TXT
|
|
143
|
+
autotouch blacklist import --file blacklist.csv
|
|
144
|
+
|
|
145
|
+
# Check/filter email sets (auto-chunked for large lists)
|
|
146
|
+
autotouch blacklist check --emails-file recipients.csv --emails-column email --summary-only
|
|
147
|
+
autotouch blacklist filter --emails-file recipients.csv --emails-column email --summary-only
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Recommended timing:
|
|
151
|
+
- Add suppressions early (unsubscribed addresses, existing customers, competitors, and clear non-ICP domains).
|
|
152
|
+
- Before billable enrichments (`llm_enrichment`, `email_finder`, `phone_finder`), run blacklist filtering and enrich only clean candidates.
|
|
153
|
+
- Run one final blacklist check/filter before outreach execution.
|
|
105
154
|
|
|
106
155
|
## Import modes
|
|
107
156
|
|
|
@@ -133,6 +182,7 @@ Auto-run is configured per column (`autoRun`), not per table.
|
|
|
133
182
|
Important:
|
|
134
183
|
- Insert events do not run `onSourceUpdate` columns.
|
|
135
184
|
- Imports may queue auto-run dispatch evaluation, but only columns whose `autoRun` policy matches the event are queued.
|
|
185
|
+
- Formatter columns are normalized server-side to `onSourceUpdate` (attempted `never`/`onInsert` values are overridden).
|
|
136
186
|
|
|
137
187
|
## Create a column
|
|
138
188
|
|
|
@@ -157,6 +207,7 @@ Notes:
|
|
|
157
207
|
- `add_to_crm` is optional and non-billable.
|
|
158
208
|
- Email/phone enrichment does not require creating/running `add_to_crm`.
|
|
159
209
|
- For `add_to_crm`, required mapping keys are `linkedinUrl` and `companyDomain`.
|
|
210
|
+
- Formatter formulas must use row references (`row['first_name']`, `row.last_name`), not bare template placeholders like ``${first_name}``.
|
|
160
211
|
- `sync_to_table` supports both:
|
|
161
212
|
- single destination: `destinationTableId` + `columnMappings`
|
|
162
213
|
- router mode: `routes[]` (first matching route wins)
|
|
@@ -164,6 +215,7 @@ Notes:
|
|
|
164
215
|
- `sequenceId`
|
|
165
216
|
- `sourceLeadColumn` pointing to a lead-id producing column (`add_to_crm` or `lead_finder` output)
|
|
166
217
|
- auto-attaches research context defaults during enrollment (`source_table_id`, plus optional table name); favorite fields resolve from current starred columns when explicit `fieldIds` are not provided
|
|
218
|
+
- star/favorite high-signal fields so call-sidecar context stays quick to scan and AI draft context stays focused
|
|
167
219
|
|
|
168
220
|
If you create custom `llm_enrichment` schemas:
|
|
169
221
|
- Use strict field-map schema shape (no root `type/properties` wrapper).
|
|
@@ -209,6 +261,65 @@ This keeps quickstart short while documenting the full strategy:
|
|
|
209
261
|
- one-person-per-row output contract,
|
|
210
262
|
- JSON split + downstream enrichment chaining.
|
|
211
263
|
|
|
264
|
+
## First-principles shape: intent + context
|
|
265
|
+
|
|
266
|
+
For most workflows, useful output combines:
|
|
267
|
+
- context: source evidence (what happened / what was observed)
|
|
268
|
+
- intent: interpretation signal (what to prioritize / do next)
|
|
269
|
+
|
|
270
|
+
Design guidance:
|
|
271
|
+
- preserve full-fidelity context in at least one raw field (for example full post/body text)
|
|
272
|
+
- default behavior for agents: write full context/content, not summaries or truncation
|
|
273
|
+
- only truncate/summarize when there is a hard limit (storage/model/provider/payload), and explicitly mark truncation
|
|
274
|
+
- keep intent separate from raw context so downstream logic can change without losing source data
|
|
275
|
+
- for calling workflows, favorite/star key fields so users can access the most relevant context quickly in sidecar views
|
|
276
|
+
- for AI-generated emails/copy, include both intent and full context in imports so drafts are grounded, not generic
|
|
277
|
+
- keep one entity per row and dedupe on a stable identity key
|
|
278
|
+
- keep snippets/summaries optional and derived from raw context, never a replacement for it
|
|
279
|
+
- normalize intent labels if you need deterministic automation
|
|
280
|
+
|
|
281
|
+
Optional field pattern (adapt to your workflow):
|
|
282
|
+
- `post_content` or `context_raw`: full long-form context
|
|
283
|
+
- `context_url`: source URL
|
|
284
|
+
- `context_timestamp`: recency marker
|
|
285
|
+
- `intent_label`: normalized intent category
|
|
286
|
+
- `intent_reason`: concise rationale
|
|
287
|
+
|
|
288
|
+
CSV import note for context fields:
|
|
289
|
+
- long text fields like `post_content` can contain newlines and commas
|
|
290
|
+
- that is valid CSV when fields are properly quoted
|
|
291
|
+
- always run `rows import-csv --validate-only` (or `--dry-run`) before write
|
|
292
|
+
- for strict guardrails, add assertions: `--expected-rows`, `--require-columns`, `--duplicate-key`, `--require-non-empty`
|
|
293
|
+
- import does not intentionally truncate text values; very large single-cell payloads are still bounded by Mongo document limits
|
|
294
|
+
|
|
295
|
+
Verification + rollback commands:
|
|
296
|
+
- `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> --expected-rows <N>`
|
|
297
|
+
- `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
298
|
+
|
|
299
|
+
Multiline `post_content` examples:
|
|
300
|
+
|
|
301
|
+
```csv
|
|
302
|
+
# bad (unquoted multiline content breaks row shape)
|
|
303
|
+
first_name,linkedin_url,post_content
|
|
304
|
+
Ada,https://linkedin.com/in/ada,Line 1
|
|
305
|
+
Line 2
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
```csv
|
|
309
|
+
# good (quoted multiline content is valid CSV)
|
|
310
|
+
first_name,linkedin_url,post_content
|
|
311
|
+
Ada,https://linkedin.com/in/ada,"Line 1
|
|
312
|
+
Line 2"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Do not re-import blind (recovery flow):
|
|
316
|
+
- stop and keep the original `task_id`
|
|
317
|
+
- inspect status: `autotouch rows import-status --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
318
|
+
- prove postflight: `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> ...assertions...`
|
|
319
|
+
- if verification fails, preview rollback: `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID> --dry-run`
|
|
320
|
+
- then rollback: `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
321
|
+
- fix CSV quoting/mapping and run `--validate-only` before any new import
|
|
322
|
+
|
|
212
323
|
## Sequences/Tasks workflow APIs (current CLI coverage)
|
|
213
324
|
|
|
214
325
|
The installable `autotouch` CLI currently provides first-class commands for research-table APIs.
|
|
@@ -452,6 +563,15 @@ autotouch columns run-next \
|
|
|
452
563
|
--wait
|
|
453
564
|
```
|
|
454
565
|
|
|
566
|
+
Blacklist gate (recommended before billable runs):
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
autotouch blacklist filter \
|
|
570
|
+
--emails-file candidates.csv \
|
|
571
|
+
--emails-column work_email \
|
|
572
|
+
--output json
|
|
573
|
+
```
|
|
574
|
+
|
|
455
575
|
## Job truth contract (agent-safe)
|
|
456
576
|
|
|
457
577
|
- Treat a run as started only when you receive `job_id`.
|
|
@@ -507,12 +627,16 @@ If either failure status appears, treat the run as unconfirmed/inconsistent, ver
|
|
|
507
627
|
- Re-run with same `--checkpoint-file` and `--wait`.
|
|
508
628
|
- CLI can resume/poll an in-flight task from checkpoint state.
|
|
509
629
|
|
|
510
|
-
4.
|
|
630
|
+
4. Need proof before saying "fixed":
|
|
631
|
+
- Run `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> ...assertions...`
|
|
632
|
+
- Treat `passed=false` as a failed import outcome.
|
|
633
|
+
|
|
634
|
+
5. Run queued but job id missing from local output:
|
|
511
635
|
- Recover from backend history:
|
|
512
636
|
- `autotouch jobs list --table-id <TABLE_ID> --column-id <COLUMN_ID> --limit 5 --output json`
|
|
513
637
|
- Then poll the returned `job_id` with `autotouch jobs get` / `autotouch jobs watch`.
|
|
514
638
|
|
|
515
|
-
|
|
639
|
+
6. Need to stop a running column job:
|
|
516
640
|
|
|
517
641
|
```bash
|
|
518
642
|
autotouch columns stop --table-id <TABLE_ID> --column-id <COLUMN_ID>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: autotouch-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.22
|
|
4
4
|
Summary: Autotouch Smart Table CLI
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -72,12 +72,12 @@ Reference:
|
|
|
72
72
|
# 1) Verify target table exists and copy the exact id
|
|
73
73
|
autotouch tables list --view-mode org --output human
|
|
74
74
|
|
|
75
|
-
# 2)
|
|
75
|
+
# 2) Validate server-side CSV parse/shape (no write)
|
|
76
76
|
autotouch rows import-csv \
|
|
77
77
|
--table-id <TABLE_ID> \
|
|
78
78
|
--confirm-table-id <TABLE_ID> \
|
|
79
79
|
--file contacts.csv \
|
|
80
|
-
--
|
|
80
|
+
--validate-only \
|
|
81
81
|
--output json
|
|
82
82
|
```
|
|
83
83
|
|
|
@@ -101,7 +101,56 @@ Notes:
|
|
|
101
101
|
- `--transport optimized` is default (`/import-optimized`).
|
|
102
102
|
- `--wait` polls import status to terminal state.
|
|
103
103
|
- `--checkpoint-file` stores state and blocks accidental duplicate re-imports.
|
|
104
|
+
- `--validate-only` validates CSV parse/shape on server without writing rows.
|
|
105
|
+
- Blacklist controls on optimized import:
|
|
106
|
+
- company-domain filtering is ON by default
|
|
107
|
+
- email filtering is OFF by default
|
|
108
|
+
- disable company filtering with `--no-check-company-blacklist`
|
|
109
|
+
- enable email filtering with `--check-email-blacklist`
|
|
110
|
+
- Safety assertions:
|
|
111
|
+
- `--expected-rows <N>`
|
|
112
|
+
- `--require-columns col_a,col_b`
|
|
113
|
+
- `--duplicate-key col_a,col_b`
|
|
114
|
+
- `--require-non-empty key:ratio`
|
|
115
|
+
- For async imports with `--wait`, assertions are rechecked postflight via task manifest verification.
|
|
104
116
|
- Use `--allow-reimport` if you intentionally want to run the same file again.
|
|
117
|
+
- Import responses include `blacklist_summary` with company/email `skipped_count` and `enforced` flags.
|
|
118
|
+
|
|
119
|
+
Example enabling both company and email enforcement:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
autotouch rows import-csv \
|
|
123
|
+
--table-id <TABLE_ID> \
|
|
124
|
+
--confirm-table-id <TABLE_ID> \
|
|
125
|
+
--file contacts.csv \
|
|
126
|
+
--checkpoint-file .autotouch-import.json \
|
|
127
|
+
--check-email-blacklist \
|
|
128
|
+
--wait \
|
|
129
|
+
--output json
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Manage blacklist entries (native CLI, admin identity required):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# List current entries
|
|
136
|
+
autotouch blacklist list --type-filter all --limit 100
|
|
137
|
+
|
|
138
|
+
# Add entries
|
|
139
|
+
autotouch blacklist add --type domain --value competitor.com --reason "Do not contact"
|
|
140
|
+
autotouch blacklist add --type email --value blocked@example.com --reason "Unsubscribed"
|
|
141
|
+
|
|
142
|
+
# Bulk-import entries from CSV/TXT
|
|
143
|
+
autotouch blacklist import --file blacklist.csv
|
|
144
|
+
|
|
145
|
+
# Check/filter email sets (auto-chunked for large lists)
|
|
146
|
+
autotouch blacklist check --emails-file recipients.csv --emails-column email --summary-only
|
|
147
|
+
autotouch blacklist filter --emails-file recipients.csv --emails-column email --summary-only
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Recommended timing:
|
|
151
|
+
- Add suppressions early (unsubscribed addresses, existing customers, competitors, and clear non-ICP domains).
|
|
152
|
+
- Before billable enrichments (`llm_enrichment`, `email_finder`, `phone_finder`), run blacklist filtering and enrich only clean candidates.
|
|
153
|
+
- Run one final blacklist check/filter before outreach execution.
|
|
105
154
|
|
|
106
155
|
## Import modes
|
|
107
156
|
|
|
@@ -133,6 +182,7 @@ Auto-run is configured per column (`autoRun`), not per table.
|
|
|
133
182
|
Important:
|
|
134
183
|
- Insert events do not run `onSourceUpdate` columns.
|
|
135
184
|
- Imports may queue auto-run dispatch evaluation, but only columns whose `autoRun` policy matches the event are queued.
|
|
185
|
+
- Formatter columns are normalized server-side to `onSourceUpdate` (attempted `never`/`onInsert` values are overridden).
|
|
136
186
|
|
|
137
187
|
## Create a column
|
|
138
188
|
|
|
@@ -157,6 +207,7 @@ Notes:
|
|
|
157
207
|
- `add_to_crm` is optional and non-billable.
|
|
158
208
|
- Email/phone enrichment does not require creating/running `add_to_crm`.
|
|
159
209
|
- For `add_to_crm`, required mapping keys are `linkedinUrl` and `companyDomain`.
|
|
210
|
+
- Formatter formulas must use row references (`row['first_name']`, `row.last_name`), not bare template placeholders like ``${first_name}``.
|
|
160
211
|
- `sync_to_table` supports both:
|
|
161
212
|
- single destination: `destinationTableId` + `columnMappings`
|
|
162
213
|
- router mode: `routes[]` (first matching route wins)
|
|
@@ -164,6 +215,7 @@ Notes:
|
|
|
164
215
|
- `sequenceId`
|
|
165
216
|
- `sourceLeadColumn` pointing to a lead-id producing column (`add_to_crm` or `lead_finder` output)
|
|
166
217
|
- auto-attaches research context defaults during enrollment (`source_table_id`, plus optional table name); favorite fields resolve from current starred columns when explicit `fieldIds` are not provided
|
|
218
|
+
- star/favorite high-signal fields so call-sidecar context stays quick to scan and AI draft context stays focused
|
|
167
219
|
|
|
168
220
|
If you create custom `llm_enrichment` schemas:
|
|
169
221
|
- Use strict field-map schema shape (no root `type/properties` wrapper).
|
|
@@ -209,6 +261,65 @@ This keeps quickstart short while documenting the full strategy:
|
|
|
209
261
|
- one-person-per-row output contract,
|
|
210
262
|
- JSON split + downstream enrichment chaining.
|
|
211
263
|
|
|
264
|
+
## First-principles shape: intent + context
|
|
265
|
+
|
|
266
|
+
For most workflows, useful output combines:
|
|
267
|
+
- context: source evidence (what happened / what was observed)
|
|
268
|
+
- intent: interpretation signal (what to prioritize / do next)
|
|
269
|
+
|
|
270
|
+
Design guidance:
|
|
271
|
+
- preserve full-fidelity context in at least one raw field (for example full post/body text)
|
|
272
|
+
- default behavior for agents: write full context/content, not summaries or truncation
|
|
273
|
+
- only truncate/summarize when there is a hard limit (storage/model/provider/payload), and explicitly mark truncation
|
|
274
|
+
- keep intent separate from raw context so downstream logic can change without losing source data
|
|
275
|
+
- for calling workflows, favorite/star key fields so users can access the most relevant context quickly in sidecar views
|
|
276
|
+
- for AI-generated emails/copy, include both intent and full context in imports so drafts are grounded, not generic
|
|
277
|
+
- keep one entity per row and dedupe on a stable identity key
|
|
278
|
+
- keep snippets/summaries optional and derived from raw context, never a replacement for it
|
|
279
|
+
- normalize intent labels if you need deterministic automation
|
|
280
|
+
|
|
281
|
+
Optional field pattern (adapt to your workflow):
|
|
282
|
+
- `post_content` or `context_raw`: full long-form context
|
|
283
|
+
- `context_url`: source URL
|
|
284
|
+
- `context_timestamp`: recency marker
|
|
285
|
+
- `intent_label`: normalized intent category
|
|
286
|
+
- `intent_reason`: concise rationale
|
|
287
|
+
|
|
288
|
+
CSV import note for context fields:
|
|
289
|
+
- long text fields like `post_content` can contain newlines and commas
|
|
290
|
+
- that is valid CSV when fields are properly quoted
|
|
291
|
+
- always run `rows import-csv --validate-only` (or `--dry-run`) before write
|
|
292
|
+
- for strict guardrails, add assertions: `--expected-rows`, `--require-columns`, `--duplicate-key`, `--require-non-empty`
|
|
293
|
+
- import does not intentionally truncate text values; very large single-cell payloads are still bounded by Mongo document limits
|
|
294
|
+
|
|
295
|
+
Verification + rollback commands:
|
|
296
|
+
- `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> --expected-rows <N>`
|
|
297
|
+
- `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
298
|
+
|
|
299
|
+
Multiline `post_content` examples:
|
|
300
|
+
|
|
301
|
+
```csv
|
|
302
|
+
# bad (unquoted multiline content breaks row shape)
|
|
303
|
+
first_name,linkedin_url,post_content
|
|
304
|
+
Ada,https://linkedin.com/in/ada,Line 1
|
|
305
|
+
Line 2
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
```csv
|
|
309
|
+
# good (quoted multiline content is valid CSV)
|
|
310
|
+
first_name,linkedin_url,post_content
|
|
311
|
+
Ada,https://linkedin.com/in/ada,"Line 1
|
|
312
|
+
Line 2"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Do not re-import blind (recovery flow):
|
|
316
|
+
- stop and keep the original `task_id`
|
|
317
|
+
- inspect status: `autotouch rows import-status --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
318
|
+
- prove postflight: `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> ...assertions...`
|
|
319
|
+
- if verification fails, preview rollback: `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID> --dry-run`
|
|
320
|
+
- then rollback: `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
321
|
+
- fix CSV quoting/mapping and run `--validate-only` before any new import
|
|
322
|
+
|
|
212
323
|
## Sequences/Tasks workflow APIs (current CLI coverage)
|
|
213
324
|
|
|
214
325
|
The installable `autotouch` CLI currently provides first-class commands for research-table APIs.
|
|
@@ -452,6 +563,15 @@ autotouch columns run-next \
|
|
|
452
563
|
--wait
|
|
453
564
|
```
|
|
454
565
|
|
|
566
|
+
Blacklist gate (recommended before billable runs):
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
autotouch blacklist filter \
|
|
570
|
+
--emails-file candidates.csv \
|
|
571
|
+
--emails-column work_email \
|
|
572
|
+
--output json
|
|
573
|
+
```
|
|
574
|
+
|
|
455
575
|
## Job truth contract (agent-safe)
|
|
456
576
|
|
|
457
577
|
- Treat a run as started only when you receive `job_id`.
|
|
@@ -507,12 +627,16 @@ If either failure status appears, treat the run as unconfirmed/inconsistent, ver
|
|
|
507
627
|
- Re-run with same `--checkpoint-file` and `--wait`.
|
|
508
628
|
- CLI can resume/poll an in-flight task from checkpoint state.
|
|
509
629
|
|
|
510
|
-
4.
|
|
630
|
+
4. Need proof before saying "fixed":
|
|
631
|
+
- Run `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> ...assertions...`
|
|
632
|
+
- Treat `passed=false` as a failed import outcome.
|
|
633
|
+
|
|
634
|
+
5. Run queued but job id missing from local output:
|
|
511
635
|
- Recover from backend history:
|
|
512
636
|
- `autotouch jobs list --table-id <TABLE_ID> --column-id <COLUMN_ID> --limit 5 --output json`
|
|
513
637
|
- Then poll the returned `job_id` with `autotouch jobs get` / `autotouch jobs watch`.
|
|
514
638
|
|
|
515
|
-
|
|
639
|
+
6. Need to stop a running column job:
|
|
516
640
|
|
|
517
641
|
```bash
|
|
518
642
|
autotouch columns stop --table-id <TABLE_ID> --column-id <COLUMN_ID>
|
|
@@ -48,6 +48,7 @@ scripts/migrations/20260113_normalize_table_filter_operators.py
|
|
|
48
48
|
scripts/migrations/20260113_set_user_permissions_user_admin.py
|
|
49
49
|
scripts/migrations/20260204_sync_lead_owner_from_tasks.py
|
|
50
50
|
scripts/migrations/20260303_add_webhook_subscription_collections.py
|
|
51
|
+
scripts/migrations/20260305_force_formatter_autorun_on_source_update.py
|
|
51
52
|
scripts/migrations/migrate_org_user_credits.py
|
|
52
53
|
scripts/migrations/set_default_lead_status.py
|
|
53
54
|
scripts/migrations/update_lead_owner_from_tasks.py
|
{autotouch_cli-0.2.20 → autotouch_cli-0.2.22}/docs/research-table/reference/autotouch-cli-pypi.md
RENAMED
|
@@ -63,12 +63,12 @@ Reference:
|
|
|
63
63
|
# 1) Verify target table exists and copy the exact id
|
|
64
64
|
autotouch tables list --view-mode org --output human
|
|
65
65
|
|
|
66
|
-
# 2)
|
|
66
|
+
# 2) Validate server-side CSV parse/shape (no write)
|
|
67
67
|
autotouch rows import-csv \
|
|
68
68
|
--table-id <TABLE_ID> \
|
|
69
69
|
--confirm-table-id <TABLE_ID> \
|
|
70
70
|
--file contacts.csv \
|
|
71
|
-
--
|
|
71
|
+
--validate-only \
|
|
72
72
|
--output json
|
|
73
73
|
```
|
|
74
74
|
|
|
@@ -92,7 +92,56 @@ Notes:
|
|
|
92
92
|
- `--transport optimized` is default (`/import-optimized`).
|
|
93
93
|
- `--wait` polls import status to terminal state.
|
|
94
94
|
- `--checkpoint-file` stores state and blocks accidental duplicate re-imports.
|
|
95
|
+
- `--validate-only` validates CSV parse/shape on server without writing rows.
|
|
96
|
+
- Blacklist controls on optimized import:
|
|
97
|
+
- company-domain filtering is ON by default
|
|
98
|
+
- email filtering is OFF by default
|
|
99
|
+
- disable company filtering with `--no-check-company-blacklist`
|
|
100
|
+
- enable email filtering with `--check-email-blacklist`
|
|
101
|
+
- Safety assertions:
|
|
102
|
+
- `--expected-rows <N>`
|
|
103
|
+
- `--require-columns col_a,col_b`
|
|
104
|
+
- `--duplicate-key col_a,col_b`
|
|
105
|
+
- `--require-non-empty key:ratio`
|
|
106
|
+
- For async imports with `--wait`, assertions are rechecked postflight via task manifest verification.
|
|
95
107
|
- Use `--allow-reimport` if you intentionally want to run the same file again.
|
|
108
|
+
- Import responses include `blacklist_summary` with company/email `skipped_count` and `enforced` flags.
|
|
109
|
+
|
|
110
|
+
Example enabling both company and email enforcement:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
autotouch rows import-csv \
|
|
114
|
+
--table-id <TABLE_ID> \
|
|
115
|
+
--confirm-table-id <TABLE_ID> \
|
|
116
|
+
--file contacts.csv \
|
|
117
|
+
--checkpoint-file .autotouch-import.json \
|
|
118
|
+
--check-email-blacklist \
|
|
119
|
+
--wait \
|
|
120
|
+
--output json
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Manage blacklist entries (native CLI, admin identity required):
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# List current entries
|
|
127
|
+
autotouch blacklist list --type-filter all --limit 100
|
|
128
|
+
|
|
129
|
+
# Add entries
|
|
130
|
+
autotouch blacklist add --type domain --value competitor.com --reason "Do not contact"
|
|
131
|
+
autotouch blacklist add --type email --value blocked@example.com --reason "Unsubscribed"
|
|
132
|
+
|
|
133
|
+
# Bulk-import entries from CSV/TXT
|
|
134
|
+
autotouch blacklist import --file blacklist.csv
|
|
135
|
+
|
|
136
|
+
# Check/filter email sets (auto-chunked for large lists)
|
|
137
|
+
autotouch blacklist check --emails-file recipients.csv --emails-column email --summary-only
|
|
138
|
+
autotouch blacklist filter --emails-file recipients.csv --emails-column email --summary-only
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Recommended timing:
|
|
142
|
+
- Add suppressions early (unsubscribed addresses, existing customers, competitors, and clear non-ICP domains).
|
|
143
|
+
- Before billable enrichments (`llm_enrichment`, `email_finder`, `phone_finder`), run blacklist filtering and enrich only clean candidates.
|
|
144
|
+
- Run one final blacklist check/filter before outreach execution.
|
|
96
145
|
|
|
97
146
|
## Import modes
|
|
98
147
|
|
|
@@ -124,6 +173,7 @@ Auto-run is configured per column (`autoRun`), not per table.
|
|
|
124
173
|
Important:
|
|
125
174
|
- Insert events do not run `onSourceUpdate` columns.
|
|
126
175
|
- Imports may queue auto-run dispatch evaluation, but only columns whose `autoRun` policy matches the event are queued.
|
|
176
|
+
- Formatter columns are normalized server-side to `onSourceUpdate` (attempted `never`/`onInsert` values are overridden).
|
|
127
177
|
|
|
128
178
|
## Create a column
|
|
129
179
|
|
|
@@ -148,6 +198,7 @@ Notes:
|
|
|
148
198
|
- `add_to_crm` is optional and non-billable.
|
|
149
199
|
- Email/phone enrichment does not require creating/running `add_to_crm`.
|
|
150
200
|
- For `add_to_crm`, required mapping keys are `linkedinUrl` and `companyDomain`.
|
|
201
|
+
- Formatter formulas must use row references (`row['first_name']`, `row.last_name`), not bare template placeholders like ``${first_name}``.
|
|
151
202
|
- `sync_to_table` supports both:
|
|
152
203
|
- single destination: `destinationTableId` + `columnMappings`
|
|
153
204
|
- router mode: `routes[]` (first matching route wins)
|
|
@@ -155,6 +206,7 @@ Notes:
|
|
|
155
206
|
- `sequenceId`
|
|
156
207
|
- `sourceLeadColumn` pointing to a lead-id producing column (`add_to_crm` or `lead_finder` output)
|
|
157
208
|
- auto-attaches research context defaults during enrollment (`source_table_id`, plus optional table name); favorite fields resolve from current starred columns when explicit `fieldIds` are not provided
|
|
209
|
+
- star/favorite high-signal fields so call-sidecar context stays quick to scan and AI draft context stays focused
|
|
158
210
|
|
|
159
211
|
If you create custom `llm_enrichment` schemas:
|
|
160
212
|
- Use strict field-map schema shape (no root `type/properties` wrapper).
|
|
@@ -200,6 +252,65 @@ This keeps quickstart short while documenting the full strategy:
|
|
|
200
252
|
- one-person-per-row output contract,
|
|
201
253
|
- JSON split + downstream enrichment chaining.
|
|
202
254
|
|
|
255
|
+
## First-principles shape: intent + context
|
|
256
|
+
|
|
257
|
+
For most workflows, useful output combines:
|
|
258
|
+
- context: source evidence (what happened / what was observed)
|
|
259
|
+
- intent: interpretation signal (what to prioritize / do next)
|
|
260
|
+
|
|
261
|
+
Design guidance:
|
|
262
|
+
- preserve full-fidelity context in at least one raw field (for example full post/body text)
|
|
263
|
+
- default behavior for agents: write full context/content, not summaries or truncation
|
|
264
|
+
- only truncate/summarize when there is a hard limit (storage/model/provider/payload), and explicitly mark truncation
|
|
265
|
+
- keep intent separate from raw context so downstream logic can change without losing source data
|
|
266
|
+
- for calling workflows, favorite/star key fields so users can access the most relevant context quickly in sidecar views
|
|
267
|
+
- for AI-generated emails/copy, include both intent and full context in imports so drafts are grounded, not generic
|
|
268
|
+
- keep one entity per row and dedupe on a stable identity key
|
|
269
|
+
- keep snippets/summaries optional and derived from raw context, never a replacement for it
|
|
270
|
+
- normalize intent labels if you need deterministic automation
|
|
271
|
+
|
|
272
|
+
Optional field pattern (adapt to your workflow):
|
|
273
|
+
- `post_content` or `context_raw`: full long-form context
|
|
274
|
+
- `context_url`: source URL
|
|
275
|
+
- `context_timestamp`: recency marker
|
|
276
|
+
- `intent_label`: normalized intent category
|
|
277
|
+
- `intent_reason`: concise rationale
|
|
278
|
+
|
|
279
|
+
CSV import note for context fields:
|
|
280
|
+
- long text fields like `post_content` can contain newlines and commas
|
|
281
|
+
- that is valid CSV when fields are properly quoted
|
|
282
|
+
- always run `rows import-csv --validate-only` (or `--dry-run`) before write
|
|
283
|
+
- for strict guardrails, add assertions: `--expected-rows`, `--require-columns`, `--duplicate-key`, `--require-non-empty`
|
|
284
|
+
- import does not intentionally truncate text values; very large single-cell payloads are still bounded by Mongo document limits
|
|
285
|
+
|
|
286
|
+
Verification + rollback commands:
|
|
287
|
+
- `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> --expected-rows <N>`
|
|
288
|
+
- `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
289
|
+
|
|
290
|
+
Multiline `post_content` examples:
|
|
291
|
+
|
|
292
|
+
```csv
|
|
293
|
+
# bad (unquoted multiline content breaks row shape)
|
|
294
|
+
first_name,linkedin_url,post_content
|
|
295
|
+
Ada,https://linkedin.com/in/ada,Line 1
|
|
296
|
+
Line 2
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
```csv
|
|
300
|
+
# good (quoted multiline content is valid CSV)
|
|
301
|
+
first_name,linkedin_url,post_content
|
|
302
|
+
Ada,https://linkedin.com/in/ada,"Line 1
|
|
303
|
+
Line 2"
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Do not re-import blind (recovery flow):
|
|
307
|
+
- stop and keep the original `task_id`
|
|
308
|
+
- inspect status: `autotouch rows import-status --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
309
|
+
- prove postflight: `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> ...assertions...`
|
|
310
|
+
- if verification fails, preview rollback: `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID> --dry-run`
|
|
311
|
+
- then rollback: `autotouch rows import-rollback --table-id <TABLE_ID> --task-id <TASK_ID>`
|
|
312
|
+
- fix CSV quoting/mapping and run `--validate-only` before any new import
|
|
313
|
+
|
|
203
314
|
## Sequences/Tasks workflow APIs (current CLI coverage)
|
|
204
315
|
|
|
205
316
|
The installable `autotouch` CLI currently provides first-class commands for research-table APIs.
|
|
@@ -443,6 +554,15 @@ autotouch columns run-next \
|
|
|
443
554
|
--wait
|
|
444
555
|
```
|
|
445
556
|
|
|
557
|
+
Blacklist gate (recommended before billable runs):
|
|
558
|
+
|
|
559
|
+
```bash
|
|
560
|
+
autotouch blacklist filter \
|
|
561
|
+
--emails-file candidates.csv \
|
|
562
|
+
--emails-column work_email \
|
|
563
|
+
--output json
|
|
564
|
+
```
|
|
565
|
+
|
|
446
566
|
## Job truth contract (agent-safe)
|
|
447
567
|
|
|
448
568
|
- Treat a run as started only when you receive `job_id`.
|
|
@@ -498,12 +618,16 @@ If either failure status appears, treat the run as unconfirmed/inconsistent, ver
|
|
|
498
618
|
- Re-run with same `--checkpoint-file` and `--wait`.
|
|
499
619
|
- CLI can resume/poll an in-flight task from checkpoint state.
|
|
500
620
|
|
|
501
|
-
4.
|
|
621
|
+
4. Need proof before saying "fixed":
|
|
622
|
+
- Run `autotouch rows import-verify --table-id <TABLE_ID> --task-id <TASK_ID> ...assertions...`
|
|
623
|
+
- Treat `passed=false` as a failed import outcome.
|
|
624
|
+
|
|
625
|
+
5. Run queued but job id missing from local output:
|
|
502
626
|
- Recover from backend history:
|
|
503
627
|
- `autotouch jobs list --table-id <TABLE_ID> --column-id <COLUMN_ID> --limit 5 --output json`
|
|
504
628
|
- Then poll the returned `job_id` with `autotouch jobs get` / `autotouch jobs watch`.
|
|
505
629
|
|
|
506
|
-
|
|
630
|
+
6. Need to stop a running column job:
|
|
507
631
|
|
|
508
632
|
```bash
|
|
509
633
|
autotouch columns stop --table-id <TABLE_ID> --column-id <COLUMN_ID>
|