autotouch-cli 0.2.40__tar.gz → 0.2.42__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.40 → autotouch_cli-0.2.42}/PKG-INFO +5 -5
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/README.md +4 -4
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/cli.py +54 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/cli_contracts.py +17 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/columns.py +109 -1
- autotouch_cli-0.2.42/autotouch_cli/commands/workspace_secrets.py +176 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/data/CLI_REFERENCE.md +208 -5
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/data/cli-manifest.json +1145 -4
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/templates.py +28 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli.egg-info/PKG-INFO +5 -5
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli.egg-info/SOURCES.txt +1 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_shared/provider_registry.py +122 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/pyproject.toml +1 -1
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/MANIFEST.in +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/__init__.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/__init__.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/auth.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/cells.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/jobs.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/leads.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/linkedin.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/rows.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/search.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/sequences.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/tables.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/tasks.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/commands/webhooks.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/__init__.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/auth.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/config.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/http.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/io.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/output.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/core/polling.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/mongo_status.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/parser_groups.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli/sequence_support.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli.egg-info/dependency_links.txt +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli.egg-info/entry_points.txt +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli.egg-info/requires.txt +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_cli.egg-info/top_level.txt +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_shared/__init__.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_shared/linkedin_contract.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/autotouch_shared/search_contract.py +0 -0
- {autotouch_cli-0.2.40 → autotouch_cli-0.2.42}/setup.cfg +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.42
|
|
4
4
|
Summary: Autotouch Smart Table CLI
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -137,7 +137,7 @@ Use a dedicated `AUTOTOUCH_CONFIG_PATH` if you want a clean local account instea
|
|
|
137
137
|
|
|
138
138
|
## Docs
|
|
139
139
|
|
|
140
|
-
- Full CLI reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
141
|
-
- Agent playbook: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
142
|
-
- Tables/API reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
143
|
-
- Authentication/scopes: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
140
|
+
- Full CLI reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/research-table/reference/autotouch-cli.md
|
|
141
|
+
- Agent playbook: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/research-table/guides/autotouch-cli-agent-playbook.md
|
|
142
|
+
- Tables/API reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/research-table/reference/tables-api.md
|
|
143
|
+
- Authentication/scopes: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/platform/authentication.md
|
|
@@ -128,7 +128,7 @@ Use a dedicated `AUTOTOUCH_CONFIG_PATH` if you want a clean local account instea
|
|
|
128
128
|
|
|
129
129
|
## Docs
|
|
130
130
|
|
|
131
|
-
- Full CLI reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
132
|
-
- Agent playbook: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
133
|
-
- Tables/API reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
134
|
-
- Authentication/scopes: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.
|
|
131
|
+
- Full CLI reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/research-table/reference/autotouch-cli.md
|
|
132
|
+
- Agent playbook: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/research-table/guides/autotouch-cli-agent-playbook.md
|
|
133
|
+
- Tables/API reference: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/research-table/reference/tables-api.md
|
|
134
|
+
- Authentication/scopes: https://github.com/nicolonic/autotouch_main/blob/autotouch-cli-v0.2.42/docs/platform/authentication.md
|
|
@@ -49,6 +49,7 @@ from autotouch_cli.commands.columns import (
|
|
|
49
49
|
cmd_columns_run as cmd_columns_run_impl,
|
|
50
50
|
cmd_columns_run_next as cmd_columns_run_next_impl,
|
|
51
51
|
cmd_columns_stop as cmd_columns_stop_impl,
|
|
52
|
+
cmd_columns_test_http_request as cmd_columns_test_http_request_impl,
|
|
52
53
|
cmd_columns_update as cmd_columns_update_impl,
|
|
53
54
|
register_columns_subcommands,
|
|
54
55
|
)
|
|
@@ -185,6 +186,13 @@ from autotouch_cli.commands.webhooks import (
|
|
|
185
186
|
cmd_webhooks_subscriptions_test as cmd_webhooks_subscriptions_test_impl,
|
|
186
187
|
cmd_webhooks_subscriptions_update as cmd_webhooks_subscriptions_update_impl,
|
|
187
188
|
)
|
|
189
|
+
from autotouch_cli.commands.workspace_secrets import (
|
|
190
|
+
WorkspaceSecretCommandRuntime as WorkspaceSecretCommandHandlerRuntime,
|
|
191
|
+
cmd_workspace_secrets_delete as cmd_workspace_secrets_delete_impl,
|
|
192
|
+
cmd_workspace_secrets_list as cmd_workspace_secrets_list_impl,
|
|
193
|
+
cmd_workspace_secrets_set as cmd_workspace_secrets_set_impl,
|
|
194
|
+
register_workspace_secrets_subcommands,
|
|
195
|
+
)
|
|
188
196
|
from autotouch_cli.core.auth import (
|
|
189
197
|
auth_headers as auth_headers_impl,
|
|
190
198
|
env_api_key as env_api_key_impl,
|
|
@@ -263,6 +271,7 @@ from autotouch_cli.templates import (
|
|
|
263
271
|
ONBOARDING_SCHEMA_TYPES,
|
|
264
272
|
ORG_CONTEXT_SCHEMA_TYPES,
|
|
265
273
|
PERSONAL_CONTEXT_SCHEMA_TYPES,
|
|
274
|
+
WORKSPACE_SECRET_SCHEMA_TYPES,
|
|
266
275
|
ROW_SCHEMA_TYPES,
|
|
267
276
|
SEQUENCE_RECIPE_TYPES,
|
|
268
277
|
SHARED_SCHEMA_TYPES,
|
|
@@ -279,6 +288,7 @@ from autotouch_cli.templates import (
|
|
|
279
288
|
emit_onboarding_schema,
|
|
280
289
|
emit_org_context_schema,
|
|
281
290
|
emit_personal_context_schema,
|
|
291
|
+
emit_workspace_secrets_schema,
|
|
282
292
|
emit_rows_schema,
|
|
283
293
|
emit_schema,
|
|
284
294
|
emit_sequences_recipe,
|
|
@@ -2252,6 +2262,18 @@ def cmd_auth_clear(args: argparse.Namespace) -> None:
|
|
|
2252
2262
|
cmd_auth_clear_impl(args, runtime=_auth_command_runtime())
|
|
2253
2263
|
|
|
2254
2264
|
|
|
2265
|
+
def cmd_workspace_secrets_list(args: argparse.Namespace) -> None:
|
|
2266
|
+
cmd_workspace_secrets_list_impl(args, runtime=_workspace_secret_command_runtime())
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
def cmd_workspace_secrets_set(args: argparse.Namespace) -> None:
|
|
2270
|
+
cmd_workspace_secrets_set_impl(args, runtime=_workspace_secret_command_runtime())
|
|
2271
|
+
|
|
2272
|
+
|
|
2273
|
+
def cmd_workspace_secrets_delete(args: argparse.Namespace) -> None:
|
|
2274
|
+
cmd_workspace_secrets_delete_impl(args, runtime=_workspace_secret_command_runtime())
|
|
2275
|
+
|
|
2276
|
+
|
|
2255
2277
|
def _coerce_string_list(values: Any) -> List[str]:
|
|
2256
2278
|
if values is None:
|
|
2257
2279
|
return []
|
|
@@ -2626,6 +2648,10 @@ def cmd_personal_context_schema(args: argparse.Namespace) -> None:
|
|
|
2626
2648
|
emit_personal_context_schema(args, _template_runtime())
|
|
2627
2649
|
|
|
2628
2650
|
|
|
2651
|
+
def cmd_workspace_secrets_schema(args: argparse.Namespace) -> None:
|
|
2652
|
+
emit_workspace_secrets_schema(args, _template_runtime())
|
|
2653
|
+
|
|
2654
|
+
|
|
2629
2655
|
def cmd_tables_schema(args: argparse.Namespace) -> None:
|
|
2630
2656
|
emit_tables_schema(args, _template_runtime())
|
|
2631
2657
|
|
|
@@ -2774,6 +2800,16 @@ def _auth_command_runtime() -> AuthCommandHandlerRuntime:
|
|
|
2774
2800
|
)
|
|
2775
2801
|
|
|
2776
2802
|
|
|
2803
|
+
def _workspace_secret_command_runtime() -> WorkspaceSecretCommandHandlerRuntime:
|
|
2804
|
+
return WorkspaceSecretCommandHandlerRuntime(
|
|
2805
|
+
resolve_token=_resolve_token,
|
|
2806
|
+
request_api=_request_api,
|
|
2807
|
+
print_json=lambda data, compact=False: _print_json(data, compact=compact),
|
|
2808
|
+
load_json_input=_load_json_input,
|
|
2809
|
+
normalize_string_value=_normalize_string_value,
|
|
2810
|
+
)
|
|
2811
|
+
|
|
2812
|
+
|
|
2777
2813
|
def _job_command_runtime() -> JobCommandHandlerRuntime:
|
|
2778
2814
|
return JobCommandHandlerRuntime(
|
|
2779
2815
|
resolve_token=_resolve_token,
|
|
@@ -3211,6 +3247,10 @@ def cmd_columns_projections(args: argparse.Namespace) -> None:
|
|
|
3211
3247
|
cmd_columns_projections_impl(args, runtime=_column_command_runtime())
|
|
3212
3248
|
|
|
3213
3249
|
|
|
3250
|
+
def cmd_columns_test_http_request(args: argparse.Namespace) -> None:
|
|
3251
|
+
cmd_columns_test_http_request_impl(args, runtime=_column_command_runtime())
|
|
3252
|
+
|
|
3253
|
+
|
|
3214
3254
|
def cmd_columns_run(args: argparse.Namespace) -> None:
|
|
3215
3255
|
cmd_columns_run_impl(args, runtime=_column_command_runtime())
|
|
3216
3256
|
|
|
@@ -3794,6 +3834,19 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
3794
3834
|
_add_output_formatting_arguments(ppersonalschema)
|
|
3795
3835
|
ppersonalschema.set_defaults(func=cmd_personal_context_schema)
|
|
3796
3836
|
|
|
3837
|
+
register_workspace_secrets_subcommands(
|
|
3838
|
+
sub,
|
|
3839
|
+
add_api_common_arguments=_add_api_common_arguments,
|
|
3840
|
+
add_output_formatting_arguments=_add_output_formatting_arguments,
|
|
3841
|
+
handlers={
|
|
3842
|
+
"list": cmd_workspace_secrets_list,
|
|
3843
|
+
"set": cmd_workspace_secrets_set,
|
|
3844
|
+
"delete": cmd_workspace_secrets_delete,
|
|
3845
|
+
"schema": cmd_workspace_secrets_schema,
|
|
3846
|
+
},
|
|
3847
|
+
workspace_secret_schema_types=WORKSPACE_SECRET_SCHEMA_TYPES,
|
|
3848
|
+
)
|
|
3849
|
+
|
|
3797
3850
|
# resolved context
|
|
3798
3851
|
pctx = sub.add_parser("context", help="Resolved requester context used by enrichment/runtime")
|
|
3799
3852
|
ctx_sub = pctx.add_subparsers(dest="context_cmd", required=True)
|
|
@@ -3959,6 +4012,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
3959
4012
|
"update": cmd_columns_update,
|
|
3960
4013
|
"delete": cmd_columns_delete,
|
|
3961
4014
|
"projections": cmd_columns_projections,
|
|
4015
|
+
"test_http_request": cmd_columns_test_http_request,
|
|
3962
4016
|
"run": cmd_columns_run,
|
|
3963
4017
|
"stop": cmd_columns_stop,
|
|
3964
4018
|
"run_next": cmd_columns_run_next,
|
|
@@ -33,6 +33,7 @@ _AUTH_MODE_PREFIXES: Tuple[Tuple[str, str], ...] = (
|
|
|
33
33
|
("org-context.", "user_session"),
|
|
34
34
|
("personal-context.", "user_session"),
|
|
35
35
|
("context.", "user_session"),
|
|
36
|
+
("workspace-secrets.", "developer_key_or_user_session"),
|
|
36
37
|
("tables.", "developer_key_or_user_session"),
|
|
37
38
|
("blacklist.", "developer_key_or_user_session"),
|
|
38
39
|
("rows.", "developer_key_or_user_session"),
|
|
@@ -200,6 +201,9 @@ def output_contract(command_key: str, parser: argparse.ArgumentParser) -> Option
|
|
|
200
201
|
|
|
201
202
|
|
|
202
203
|
def command_examples(parser: argparse.ArgumentParser) -> List[str]:
|
|
204
|
+
extra_examples = getattr(parser, "_codex_examples", None)
|
|
205
|
+
if isinstance(extra_examples, list) and extra_examples:
|
|
206
|
+
return [str(example) for example in extra_examples if str(example).strip()]
|
|
203
207
|
usage = parser.format_usage().strip()
|
|
204
208
|
if usage.startswith("usage: "):
|
|
205
209
|
usage = usage[len("usage: ") :]
|
|
@@ -261,6 +265,8 @@ def collect_cli_command_manifest(
|
|
|
261
265
|
"aliases": [],
|
|
262
266
|
"group": path_parts[1] if len(path_parts) > 1 else None,
|
|
263
267
|
"help": parser.description or parser.format_usage().strip(),
|
|
268
|
+
"description": parser.description,
|
|
269
|
+
"notes": parser.epilog,
|
|
264
270
|
"required_flags": required_flags,
|
|
265
271
|
"positionals": positionals,
|
|
266
272
|
"options": options,
|
|
@@ -338,6 +344,10 @@ def build_cli_reference_markdown(manifest: Dict[str, Any]) -> str:
|
|
|
338
344
|
if help_text:
|
|
339
345
|
lines.append(help_text)
|
|
340
346
|
lines.append("")
|
|
347
|
+
description = str(entry.get("description") or "").strip()
|
|
348
|
+
if description and description != help_text:
|
|
349
|
+
lines.append(description)
|
|
350
|
+
lines.append("")
|
|
341
351
|
lines.append(f"- Auth: `{entry.get('auth_mode') or 'unknown'}`")
|
|
342
352
|
lines.append(f"- Stability: `{entry.get('stability') or 'stable'}`")
|
|
343
353
|
lines.append(f"- Destructive: `{'yes' if entry.get('destructive') else 'no'}`")
|
|
@@ -368,6 +378,13 @@ def build_cli_reference_markdown(manifest: Dict[str, Any]) -> str:
|
|
|
368
378
|
lines.append("- Example:")
|
|
369
379
|
for example in examples:
|
|
370
380
|
lines.append(f" - `{example}`")
|
|
381
|
+
notes = str(entry.get("notes") or "").strip()
|
|
382
|
+
if notes:
|
|
383
|
+
lines.append("- Notes:")
|
|
384
|
+
lines.append("")
|
|
385
|
+
lines.append("```text")
|
|
386
|
+
lines.extend(notes.rstrip().splitlines())
|
|
387
|
+
lines.append("```")
|
|
371
388
|
options = entry.get("options") or []
|
|
372
389
|
if options:
|
|
373
390
|
lines.append("- Options:")
|
|
@@ -22,6 +22,38 @@ class ColumnCommandRuntime:
|
|
|
22
22
|
select_next_row_ids: Callable[..., Dict[str, Any]]
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def _normalize_http_request_test_payload(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
26
|
+
candidate = payload
|
|
27
|
+
config = payload.get("config")
|
|
28
|
+
if isinstance(config, dict):
|
|
29
|
+
candidate = config
|
|
30
|
+
if candidate.get("provider") and str(candidate.get("provider")) != "http_request":
|
|
31
|
+
print("ERROR: columns test-http-request only accepts http_request payloads", file=sys.stderr)
|
|
32
|
+
sys.exit(2)
|
|
33
|
+
|
|
34
|
+
url = candidate.get("url")
|
|
35
|
+
if not isinstance(url, str) or not url.strip():
|
|
36
|
+
print("ERROR: HTTP request preview requires url", file=sys.stderr)
|
|
37
|
+
sys.exit(2)
|
|
38
|
+
|
|
39
|
+
headers = candidate.get("headers")
|
|
40
|
+
if headers is None:
|
|
41
|
+
headers = {}
|
|
42
|
+
if not isinstance(headers, dict):
|
|
43
|
+
print("ERROR: HTTP request preview requires headers to be a JSON object", file=sys.stderr)
|
|
44
|
+
sys.exit(2)
|
|
45
|
+
|
|
46
|
+
timeout = candidate.get("timeout_seconds", candidate.get("timeoutSeconds", 30))
|
|
47
|
+
normalized: Dict[str, Any] = {
|
|
48
|
+
"method": str(candidate.get("method") or "GET").upper(),
|
|
49
|
+
"url": url,
|
|
50
|
+
"headers": headers,
|
|
51
|
+
"body": candidate.get("body"),
|
|
52
|
+
"timeoutSeconds": timeout,
|
|
53
|
+
}
|
|
54
|
+
return normalized
|
|
55
|
+
|
|
56
|
+
|
|
25
57
|
def cmd_columns_list(args: argparse.Namespace, *, runtime: ColumnCommandRuntime) -> None:
|
|
26
58
|
token = runtime.resolve_token(args.token, required=True)
|
|
27
59
|
data = runtime.request_api(
|
|
@@ -168,6 +200,30 @@ def cmd_columns_projections(args: argparse.Namespace, *, runtime: ColumnCommandR
|
|
|
168
200
|
runtime.print_json(data, args.compact)
|
|
169
201
|
|
|
170
202
|
|
|
203
|
+
def cmd_columns_test_http_request(args: argparse.Namespace, *, runtime: ColumnCommandRuntime) -> None:
|
|
204
|
+
token = runtime.resolve_token(args.token, required=True)
|
|
205
|
+
payload = runtime.load_json_input(
|
|
206
|
+
inline_json=args.data_json,
|
|
207
|
+
file_path=args.data_file,
|
|
208
|
+
context="data",
|
|
209
|
+
default=None,
|
|
210
|
+
)
|
|
211
|
+
if not isinstance(payload, dict):
|
|
212
|
+
print("ERROR: HTTP request preview requires --data-json/--data-file with a JSON object", file=sys.stderr)
|
|
213
|
+
sys.exit(2)
|
|
214
|
+
data = runtime.request_api(
|
|
215
|
+
"POST",
|
|
216
|
+
f"/api/tables/{args.table_id}/test-http-request",
|
|
217
|
+
base_url=args.base_url,
|
|
218
|
+
token=token,
|
|
219
|
+
use_x_api_key=args.use_x_api_key,
|
|
220
|
+
payload=_normalize_http_request_test_payload(payload),
|
|
221
|
+
timeout=args.timeout,
|
|
222
|
+
verbose=args.verbose,
|
|
223
|
+
)
|
|
224
|
+
runtime.print_json(data, args.compact)
|
|
225
|
+
|
|
226
|
+
|
|
171
227
|
def cmd_columns_run(args: argparse.Namespace, *, runtime: ColumnCommandRuntime) -> None:
|
|
172
228
|
token = runtime.resolve_token(args.token, required=True)
|
|
173
229
|
payload = runtime.normalize_run_payload(args)
|
|
@@ -286,13 +342,65 @@ def register_columns_subcommands(
|
|
|
286
342
|
add_api_common_arguments(pcd)
|
|
287
343
|
pcd.set_defaults(func=handlers["delete"])
|
|
288
344
|
|
|
289
|
-
pcpj = col_sub.add_parser(
|
|
345
|
+
pcpj = col_sub.add_parser(
|
|
346
|
+
"projections",
|
|
347
|
+
help="Create JSON projection columns",
|
|
348
|
+
description=(
|
|
349
|
+
"Create JSON-split projection columns from a JSON source column.\n"
|
|
350
|
+
"Use this command for flattening enrichment JSON output into readable columns.\n"
|
|
351
|
+
"Do not use `autotouch columns create` with `kind: \"projection\"` and empty `config`."
|
|
352
|
+
),
|
|
353
|
+
epilog=(
|
|
354
|
+
"CreateProjectionsRequest payload example:\n\n"
|
|
355
|
+
"{\n"
|
|
356
|
+
" \"items\": [\n"
|
|
357
|
+
" {\n"
|
|
358
|
+
" \"key\": \"company_name\",\n"
|
|
359
|
+
" \"label\": \"Company Name\",\n"
|
|
360
|
+
" \"sourceColumnId\": \"<JSON_COLUMN_ID>\",\n"
|
|
361
|
+
" \"path\": \"company_name\",\n"
|
|
362
|
+
" \"dataType\": \"text\"\n"
|
|
363
|
+
" }\n"
|
|
364
|
+
" ]\n"
|
|
365
|
+
"}\n\n"
|
|
366
|
+
"Each item must include `key`, `label`, `sourceColumnId`, and `path`."
|
|
367
|
+
),
|
|
368
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
369
|
+
)
|
|
290
370
|
pcpj.add_argument("--table-id", required=True)
|
|
291
371
|
pcpj.add_argument("--data-json", help="CreateProjectionsRequest payload JSON")
|
|
292
372
|
pcpj.add_argument("--data-file", help="CreateProjectionsRequest payload file path")
|
|
293
373
|
add_api_common_arguments(pcpj)
|
|
294
374
|
pcpj.set_defaults(func=handlers["projections"])
|
|
295
375
|
|
|
376
|
+
pcht = col_sub.add_parser(
|
|
377
|
+
"test-http-request",
|
|
378
|
+
help="Preview an HTTP Request column against the first table row",
|
|
379
|
+
description=(
|
|
380
|
+
"Resolve and execute one HTTP request using the first row in the table.\n"
|
|
381
|
+
"This preview does not write cells.\n"
|
|
382
|
+
"Pass either a full http_request column payload or a direct request config object."
|
|
383
|
+
),
|
|
384
|
+
epilog=(
|
|
385
|
+
"Recommended flow:\n\n"
|
|
386
|
+
"autotouch columns recipe --type http_request --out-file column.json\n"
|
|
387
|
+
"autotouch columns test-http-request --table-id <TABLE_ID> --data-file column.json\n"
|
|
388
|
+
"autotouch columns create --table-id <TABLE_ID> --data-file column.json\n\n"
|
|
389
|
+
"Template syntax:\n"
|
|
390
|
+
"- {{column_key}} -> row value from the first table row\n"
|
|
391
|
+
"- {{secrets.name}} -> workspace secret or active org integration credential by provider slug"
|
|
392
|
+
),
|
|
393
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
394
|
+
)
|
|
395
|
+
pcht.add_argument("--table-id", required=True)
|
|
396
|
+
pcht.add_argument("--data-json", help="HTTP request column payload JSON or direct preview payload JSON")
|
|
397
|
+
pcht.add_argument("--data-file", help="HTTP request column payload file path or direct preview payload file path")
|
|
398
|
+
add_api_common_arguments(pcht)
|
|
399
|
+
pcht.set_defaults(func=handlers["test_http_request"])
|
|
400
|
+
pcht._codex_examples = [
|
|
401
|
+
"autotouch columns test-http-request --table-id <TABLE_ID> --data-file column.json",
|
|
402
|
+
]
|
|
403
|
+
|
|
296
404
|
pcr = col_sub.add_parser("run", help="Run a column")
|
|
297
405
|
pcr.add_argument("--table-id", required=True)
|
|
298
406
|
pcr.add_argument("--column-id", required=True)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Callable, Dict, Optional, Sequence
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class WorkspaceSecretCommandRuntime:
|
|
11
|
+
resolve_token: Callable[[Optional[str], bool], Optional[str]]
|
|
12
|
+
request_api: Callable[..., Any]
|
|
13
|
+
print_json: Callable[[Any, bool], None]
|
|
14
|
+
load_json_input: Callable[..., Any]
|
|
15
|
+
normalize_string_value: Callable[[Any], str]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _normalize_secret_name(name: Any) -> str:
|
|
19
|
+
normalized = str(name or "").strip().lower()
|
|
20
|
+
if not normalized:
|
|
21
|
+
print("ERROR: workspace secret name is required", file=sys.stderr)
|
|
22
|
+
sys.exit(2)
|
|
23
|
+
return normalized
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _build_workspace_secret_payload(
|
|
27
|
+
args: argparse.Namespace,
|
|
28
|
+
*,
|
|
29
|
+
runtime: WorkspaceSecretCommandRuntime,
|
|
30
|
+
) -> Dict[str, Any]:
|
|
31
|
+
payload = runtime.load_json_input(
|
|
32
|
+
inline_json=getattr(args, "data_json", None),
|
|
33
|
+
file_path=getattr(args, "data_file", None),
|
|
34
|
+
context="data",
|
|
35
|
+
default=None,
|
|
36
|
+
)
|
|
37
|
+
if payload is not None:
|
|
38
|
+
if not isinstance(payload, dict):
|
|
39
|
+
print("ERROR: workspace-secrets set payload must be a JSON object", file=sys.stderr)
|
|
40
|
+
sys.exit(2)
|
|
41
|
+
else:
|
|
42
|
+
payload = {
|
|
43
|
+
"name": _normalize_secret_name(getattr(args, "name", None)),
|
|
44
|
+
"value": runtime.normalize_string_value(getattr(args, "value", None)),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
name = _normalize_secret_name(payload.get("name"))
|
|
48
|
+
value = runtime.normalize_string_value(payload.get("value"))
|
|
49
|
+
if not value:
|
|
50
|
+
print("ERROR: workspace secret value is required", file=sys.stderr)
|
|
51
|
+
sys.exit(2)
|
|
52
|
+
return {
|
|
53
|
+
"name": name,
|
|
54
|
+
"value": value,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def cmd_workspace_secrets_list(
|
|
59
|
+
args: argparse.Namespace,
|
|
60
|
+
*,
|
|
61
|
+
runtime: WorkspaceSecretCommandRuntime,
|
|
62
|
+
) -> None:
|
|
63
|
+
token = runtime.resolve_token(args.token, required=True)
|
|
64
|
+
data = runtime.request_api(
|
|
65
|
+
"GET",
|
|
66
|
+
"/api/workspace-secrets",
|
|
67
|
+
base_url=args.base_url,
|
|
68
|
+
token=token,
|
|
69
|
+
use_x_api_key=args.use_x_api_key,
|
|
70
|
+
timeout=args.timeout,
|
|
71
|
+
verbose=args.verbose,
|
|
72
|
+
)
|
|
73
|
+
runtime.print_json(data, args.compact)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def cmd_workspace_secrets_set(
|
|
77
|
+
args: argparse.Namespace,
|
|
78
|
+
*,
|
|
79
|
+
runtime: WorkspaceSecretCommandRuntime,
|
|
80
|
+
) -> None:
|
|
81
|
+
token = runtime.resolve_token(args.token, required=True)
|
|
82
|
+
payload = _build_workspace_secret_payload(args, runtime=runtime)
|
|
83
|
+
data = runtime.request_api(
|
|
84
|
+
"POST",
|
|
85
|
+
"/api/workspace-secrets",
|
|
86
|
+
base_url=args.base_url,
|
|
87
|
+
token=token,
|
|
88
|
+
use_x_api_key=args.use_x_api_key,
|
|
89
|
+
payload=payload,
|
|
90
|
+
timeout=args.timeout,
|
|
91
|
+
verbose=args.verbose,
|
|
92
|
+
)
|
|
93
|
+
runtime.print_json(data, args.compact)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def cmd_workspace_secrets_delete(
|
|
97
|
+
args: argparse.Namespace,
|
|
98
|
+
*,
|
|
99
|
+
runtime: WorkspaceSecretCommandRuntime,
|
|
100
|
+
) -> None:
|
|
101
|
+
if not getattr(args, "yes", False):
|
|
102
|
+
print(
|
|
103
|
+
"ERROR: workspace secret delete is destructive. Re-run with --yes to confirm.",
|
|
104
|
+
file=sys.stderr,
|
|
105
|
+
)
|
|
106
|
+
sys.exit(2)
|
|
107
|
+
|
|
108
|
+
token = runtime.resolve_token(args.token, required=True)
|
|
109
|
+
secret_name = _normalize_secret_name(getattr(args, "name", None))
|
|
110
|
+
data = runtime.request_api(
|
|
111
|
+
"DELETE",
|
|
112
|
+
f"/api/workspace-secrets/{secret_name}",
|
|
113
|
+
base_url=args.base_url,
|
|
114
|
+
token=token,
|
|
115
|
+
use_x_api_key=args.use_x_api_key,
|
|
116
|
+
timeout=args.timeout,
|
|
117
|
+
verbose=args.verbose,
|
|
118
|
+
)
|
|
119
|
+
runtime.print_json(data, args.compact)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def register_workspace_secrets_subcommands(
|
|
123
|
+
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
124
|
+
*,
|
|
125
|
+
add_api_common_arguments: Callable[[argparse.ArgumentParser], None],
|
|
126
|
+
add_output_formatting_arguments: Callable[[argparse.ArgumentParser], None],
|
|
127
|
+
handlers: Dict[str, Callable[[argparse.Namespace], None]],
|
|
128
|
+
workspace_secret_schema_types: Sequence[str],
|
|
129
|
+
) -> None:
|
|
130
|
+
pws = subparsers.add_parser(
|
|
131
|
+
"workspace-secrets",
|
|
132
|
+
help="Manage reusable org-scoped secrets for HTTP request columns",
|
|
133
|
+
description=(
|
|
134
|
+
"Manage reusable org-scoped secrets used by {{secrets.name}} templates in HTTP request columns "
|
|
135
|
+
"and other templated features."
|
|
136
|
+
),
|
|
137
|
+
epilog=(
|
|
138
|
+
"Developer API keys need secrets:read / secrets:write scopes (or *) for these endpoints.\n"
|
|
139
|
+
"Workspace secrets are optional; HTTP request columns can still use literal headers/body values."
|
|
140
|
+
),
|
|
141
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
142
|
+
)
|
|
143
|
+
pws._codex_examples = [
|
|
144
|
+
"autotouch workspace-secrets set --name clearbit --value \"$CLEARBIT_API_KEY\"",
|
|
145
|
+
"autotouch workspace-secrets list",
|
|
146
|
+
"autotouch workspace-secrets delete --name clearbit --yes",
|
|
147
|
+
]
|
|
148
|
+
ws_sub = pws.add_subparsers(dest="workspace_secret_cmd", required=True)
|
|
149
|
+
|
|
150
|
+
pwsl = ws_sub.add_parser("list", help="List workspace secrets (masked values)")
|
|
151
|
+
add_api_common_arguments(pwsl)
|
|
152
|
+
pwsl.set_defaults(func=handlers["list"])
|
|
153
|
+
|
|
154
|
+
pwss = ws_sub.add_parser(
|
|
155
|
+
"set",
|
|
156
|
+
help="Create or update a workspace secret",
|
|
157
|
+
description="Create or update a workspace secret used by {{secrets.name}} template references.",
|
|
158
|
+
)
|
|
159
|
+
pwss.add_argument("--name", help="Secret/provider slug, for example clearbit")
|
|
160
|
+
pwss.add_argument("--value", help="Secret value (for example an API key or bearer token)")
|
|
161
|
+
pwss.add_argument("--data-json", help="Explicit workspace secret payload JSON")
|
|
162
|
+
pwss.add_argument("--data-file", help="Path to workspace secret payload JSON file")
|
|
163
|
+
add_api_common_arguments(pwss)
|
|
164
|
+
pwss.set_defaults(func=handlers["set"])
|
|
165
|
+
|
|
166
|
+
pwsd = ws_sub.add_parser("delete", help="Delete a workspace secret")
|
|
167
|
+
pwsd.add_argument("--name", required=True, help="Secret/provider slug to delete")
|
|
168
|
+
pwsd.add_argument("--yes", action="store_true", help="Confirm deletion")
|
|
169
|
+
add_api_common_arguments(pwsd)
|
|
170
|
+
pwsd.set_defaults(func=handlers["delete"])
|
|
171
|
+
|
|
172
|
+
pwsschema = ws_sub.add_parser("schema", help="Print workspace-secrets payload schemas")
|
|
173
|
+
pwsschema.add_argument("--type", choices=["all", *workspace_secret_schema_types], default="all")
|
|
174
|
+
pwsschema.add_argument("--out-file", help="Write schema JSON to file")
|
|
175
|
+
add_output_formatting_arguments(pwsschema)
|
|
176
|
+
pwsschema.set_defaults(func=handlers["schema"])
|