unique-sdk 2026.42.0.dev1__tar.gz → 2026.42.0.dev2__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.
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/PKG-INFO +1 -1
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/pyproject.toml +1 -1
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/cli.py +127 -3
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/agentic_table_write.py +252 -2
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-agentic-table/SKILL.md +81 -34
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/README.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/__init__.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_api_requestor.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_api_resource.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_api_version.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_error.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_http_client.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_list_object.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_object_classes.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_request_options.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_unique_object.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_unique_ql.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_unique_response.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_util.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_version.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/_webhook.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/__init__.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_acronyms.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_agentic_table.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_analytics_order.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_benchmarking.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_briefing.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_chat_completion.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_content.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_context_memory.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_elicitation.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_embedding.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_event.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_folder.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_group.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_integrated.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_llm_models.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_mcp.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message_assessment.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message_execution.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message_log.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message_tool.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_module.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_scheduled_task.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_search.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_search_string.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_short_term_memory.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_space.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_user.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_web_search.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/__init__.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/__main__.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/__init__.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/_citation_manifest.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/agentic_table.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/browser.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/cite_file.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/elicitation.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/files.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/folders.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/mcp.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/navigation.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/read.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/scheduled_tasks.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/search.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/subagent.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/web_search.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/web_search_config.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/config.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/formatting.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/identity.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/metadata_filter.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/shell.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-elicitation/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-file-management/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-mcp/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-scheduled-tasks/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-search/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-subagent/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-uploaded-search/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/skills/unique-cli-web-search/SKILL.md +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/state.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/workspace.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/analytics_order_run.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/benchmarking_run.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/chat_history.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/chat_in_space.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/file_io.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/sources.py +0 -0
- {unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/token.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-sdk
|
|
3
|
-
Version: 2026.42.0.
|
|
3
|
+
Version: 2026.42.0.dev2
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Martin Fadler, Konstantin Krauss, Andreas Hauri
|
|
6
6
|
Author-email: Martin Fadler <martin.fadler@unique.ch>, Konstantin Krauss <konstantin@unique.ch>, Andreas Hauri <andreas@unique.ch>
|
|
@@ -23,6 +23,7 @@ from unique_sdk.cli.commands.agentic_table_write import (
|
|
|
23
23
|
cmd_export,
|
|
24
24
|
cmd_import,
|
|
25
25
|
cmd_rerun_row,
|
|
26
|
+
cmd_set_cell,
|
|
26
27
|
)
|
|
27
28
|
from unique_sdk.cli.commands.browser import (
|
|
28
29
|
cmd_browser_action,
|
|
@@ -2304,9 +2305,9 @@ Work with Agentic Table (magic table) sheets over the public magic-table API.
|
|
|
2304
2305
|
\b
|
|
2305
2306
|
Reads (get-sheet / get-cell / cell-history / list-exports) are Tier 0: no
|
|
2306
2307
|
confirmation, no side effects. Writes (create-sheet / import / rerun-row /
|
|
2307
|
-
export) build and run a sheet — the full loop of create, populate,
|
|
2308
|
-
|
|
2309
|
-
call is scoped to the current user/company; sheet-role access (Owner / Can
|
|
2308
|
+
set-cell / export) build and run a sheet — the full loop of create, populate,
|
|
2309
|
+
run, and export — plus re-answering a single row or writing one cell's text.
|
|
2310
|
+
Every call is scoped to the current user/company; sheet-role access (Owner / Can
|
|
2310
2311
|
manage / Can edit) is enforced server-side and a denial is reported as
|
|
2311
2312
|
`agentic-table: permission denied`.
|
|
2312
2313
|
|
|
@@ -2322,6 +2323,7 @@ Write subcommands:
|
|
|
2322
2323
|
create-sheet Create a new sheet in a space
|
|
2323
2324
|
import Import questions/sources (adding questions triggers the run)
|
|
2324
2325
|
rerun-row Re-run the agent for a single row (import cannot redo a row)
|
|
2326
|
+
set-cell Write text into one cell by row/column order (no run)
|
|
2325
2327
|
export Generate export artifacts (report / question export)
|
|
2326
2328
|
|
|
2327
2329
|
\b
|
|
@@ -2329,6 +2331,7 @@ Examples:
|
|
|
2329
2331
|
unique-cli agentic-table get-sheet mt_abc123 --cells --metadata
|
|
2330
2332
|
unique-cli agentic-table create-sheet asst_123 --name "Vendor DDQ"
|
|
2331
2333
|
unique-cli agentic-table import mt_abc123 --question-file-id c_q --source-file-id c_src --wait
|
|
2334
|
+
unique-cli agentic-table set-cell mt_abc123 --row 1 --col 2 --text "Fee is 2%."
|
|
2332
2335
|
unique-cli agentic-table export mt_abc123 --type FULL_REPORT --wait
|
|
2333
2336
|
"""
|
|
2334
2337
|
|
|
@@ -2710,6 +2713,127 @@ def agentic_table_rerun_row(
|
|
|
2710
2713
|
)
|
|
2711
2714
|
|
|
2712
2715
|
|
|
2716
|
+
@agentic_table.command(name="set-cell")
|
|
2717
|
+
@click.argument("table_id")
|
|
2718
|
+
@click.option(
|
|
2719
|
+
"--row",
|
|
2720
|
+
"row_order",
|
|
2721
|
+
type=click.IntRange(min=0),
|
|
2722
|
+
required=True,
|
|
2723
|
+
help="Row order (0-based; 0 is the header).",
|
|
2724
|
+
)
|
|
2725
|
+
@click.option(
|
|
2726
|
+
"--col",
|
|
2727
|
+
"column_order",
|
|
2728
|
+
type=click.IntRange(min=0),
|
|
2729
|
+
required=True,
|
|
2730
|
+
help="Column order (0-based).",
|
|
2731
|
+
)
|
|
2732
|
+
@click.option(
|
|
2733
|
+
"--text",
|
|
2734
|
+
"text",
|
|
2735
|
+
default=None,
|
|
2736
|
+
help="Cell text (exactly one of --text, --file, --stdin).",
|
|
2737
|
+
)
|
|
2738
|
+
@click.option(
|
|
2739
|
+
"--file",
|
|
2740
|
+
"file",
|
|
2741
|
+
type=click.Path(exists=True, dir_okay=False),
|
|
2742
|
+
default=None,
|
|
2743
|
+
help="Read cell text from a UTF-8 file.",
|
|
2744
|
+
)
|
|
2745
|
+
@click.option(
|
|
2746
|
+
"--stdin",
|
|
2747
|
+
"stdin",
|
|
2748
|
+
is_flag=True,
|
|
2749
|
+
default=False,
|
|
2750
|
+
help="Read cell text from stdin.",
|
|
2751
|
+
)
|
|
2752
|
+
@click.option(
|
|
2753
|
+
"--log-file",
|
|
2754
|
+
"log_file",
|
|
2755
|
+
type=click.Path(exists=True, dir_okay=False),
|
|
2756
|
+
default=None,
|
|
2757
|
+
help="JSON array of log entries (text, actorType, createdAt).",
|
|
2758
|
+
)
|
|
2759
|
+
@click.option(
|
|
2760
|
+
"--log-json",
|
|
2761
|
+
"log_json",
|
|
2762
|
+
default=None,
|
|
2763
|
+
help="Inline JSON array of log entries (text, actorType, createdAt).",
|
|
2764
|
+
)
|
|
2765
|
+
@click.option(
|
|
2766
|
+
"--allow-create",
|
|
2767
|
+
"allow_create",
|
|
2768
|
+
is_flag=True,
|
|
2769
|
+
default=False,
|
|
2770
|
+
help="Allow creating the next row or column (not a gap).",
|
|
2771
|
+
)
|
|
2772
|
+
@click.option(
|
|
2773
|
+
"--force",
|
|
2774
|
+
"force",
|
|
2775
|
+
is_flag=True,
|
|
2776
|
+
default=False,
|
|
2777
|
+
help="Write even while the sheet is PROCESSING.",
|
|
2778
|
+
)
|
|
2779
|
+
@click.option(
|
|
2780
|
+
"--json", "output_json", is_flag=True, default=False, help="Print raw JSON."
|
|
2781
|
+
)
|
|
2782
|
+
@click.pass_context
|
|
2783
|
+
def agentic_table_set_cell(
|
|
2784
|
+
ctx: click.Context,
|
|
2785
|
+
table_id: str,
|
|
2786
|
+
row_order: int,
|
|
2787
|
+
column_order: int,
|
|
2788
|
+
text: str | None,
|
|
2789
|
+
file: str | None,
|
|
2790
|
+
stdin: bool,
|
|
2791
|
+
log_file: str | None,
|
|
2792
|
+
log_json: str | None,
|
|
2793
|
+
allow_create: bool,
|
|
2794
|
+
force: bool,
|
|
2795
|
+
output_json: bool,
|
|
2796
|
+
) -> None:
|
|
2797
|
+
"""Write text into one cell by row and column order.
|
|
2798
|
+
|
|
2799
|
+
\b
|
|
2800
|
+
This is not a run. Pass the cell value you already have; the API returns
|
|
2801
|
+
the updated cell immediately. --row/--col are 0-based like get-cell; row 0
|
|
2802
|
+
is the header and is allowed. A missing row or column is refused unless
|
|
2803
|
+
--allow-create, which adds only the next index. A PROCESSING sheet is
|
|
2804
|
+
refused unless --force. Use
|
|
2805
|
+
rerun-row to have the table agent regenerate an answer from sources.
|
|
2806
|
+
|
|
2807
|
+
\b
|
|
2808
|
+
Provide exactly one of --text, --file, or --stdin. Long or multi-line
|
|
2809
|
+
answers belong in a file or stdin. Optional --log-file / --log-json is a
|
|
2810
|
+
JSON array of {text, actorType, createdAt} with actorType TOOL or ASSISTANT.
|
|
2811
|
+
|
|
2812
|
+
\b
|
|
2813
|
+
Examples:
|
|
2814
|
+
unique-cli agentic-table set-cell mt_abc123 --row 1 --col 2 --text "Fee is 2%."
|
|
2815
|
+
unique-cli agentic-table set-cell mt_abc123 --row 1 --col 2 --file ./answer.md
|
|
2816
|
+
unique-cli agentic-table set-cell mt_abc123 --row 1 --col 2 --stdin < answer.md
|
|
2817
|
+
"""
|
|
2818
|
+
emit(
|
|
2819
|
+
cmd_set_cell(
|
|
2820
|
+
LazyState.get(ctx),
|
|
2821
|
+
table_id,
|
|
2822
|
+
row_order=row_order,
|
|
2823
|
+
column_order=column_order,
|
|
2824
|
+
text=text,
|
|
2825
|
+
file=file,
|
|
2826
|
+
stdin=stdin,
|
|
2827
|
+
log_file=log_file,
|
|
2828
|
+
log_json=log_json,
|
|
2829
|
+
allow_create=allow_create,
|
|
2830
|
+
force=force,
|
|
2831
|
+
output_json=output_json,
|
|
2832
|
+
),
|
|
2833
|
+
is_error=_is_agentic_table_error_output,
|
|
2834
|
+
)
|
|
2835
|
+
|
|
2836
|
+
|
|
2713
2837
|
@agentic_table.command(name="export")
|
|
2714
2838
|
@click.argument("table_id")
|
|
2715
2839
|
@click.option(
|
|
@@ -5,6 +5,7 @@ The full-loop write slice over the public magic-table API (``2023-12-06``):
|
|
|
5
5
|
- ``create-sheet`` — create an empty sheet in a space.
|
|
6
6
|
- ``import`` — add questions/sources; adding new questions triggers the agent run.
|
|
7
7
|
- ``rerun-row`` — re-run the agent for a single row.
|
|
8
|
+
- ``set-cell`` — write text into one cell (no run).
|
|
8
9
|
- ``export`` — generate export artifacts (report / question export) and list them.
|
|
9
10
|
|
|
10
11
|
Together these let an agent build a sheet, run it, and collect the answers it
|
|
@@ -35,14 +36,19 @@ from __future__ import annotations
|
|
|
35
36
|
|
|
36
37
|
import asyncio
|
|
37
38
|
import json
|
|
39
|
+
import sys
|
|
38
40
|
import time
|
|
39
|
-
from collections.abc import Awaitable, Callable
|
|
40
|
-
from
|
|
41
|
+
from collections.abc import Awaitable, Callable, Mapping
|
|
42
|
+
from datetime import datetime
|
|
43
|
+
from pathlib import Path
|
|
44
|
+
from typing import Literal, NamedTuple, TypeVar, cast
|
|
41
45
|
|
|
42
46
|
from unique_sdk._error import UniqueError
|
|
43
47
|
from unique_sdk.api_resources._agentic_table import (
|
|
44
48
|
AgenticTable,
|
|
45
49
|
AgenticTableSheetState,
|
|
50
|
+
LogDetail,
|
|
51
|
+
LogEntry,
|
|
46
52
|
MagicTableActionResult,
|
|
47
53
|
MagicTableArtifact,
|
|
48
54
|
MagicTableArtifactState,
|
|
@@ -57,6 +63,7 @@ from unique_sdk.cli.commands.agentic_table import AGENTIC_TABLE_ERROR_PREFIX
|
|
|
57
63
|
from unique_sdk.cli.formatting import (
|
|
58
64
|
format_agentic_table_action_result,
|
|
59
65
|
format_agentic_table_artifacts,
|
|
66
|
+
format_agentic_table_cell,
|
|
60
67
|
format_agentic_table_created_sheet,
|
|
61
68
|
)
|
|
62
69
|
from unique_sdk.cli.state import ShellState
|
|
@@ -152,6 +159,249 @@ def _rejected(result: MagicTableActionResult, *, action: str) -> str:
|
|
|
152
159
|
return f"{AGENTIC_TABLE_ERROR_PREFIX} {action} rejected: {message}"
|
|
153
160
|
|
|
154
161
|
|
|
162
|
+
# unique-cli is primarily agent-driven: USER/SYSTEM would be spoofable
|
|
163
|
+
# provenance on cell-history, so only ASSISTANT and TOOL are accepted here.
|
|
164
|
+
_LOG_ACTOR_TYPES = frozenset({"ASSISTANT", "TOOL"})
|
|
165
|
+
_LOG_FILE_ERRORS = (OSError, UnicodeDecodeError)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _parse_log_created_at(raw: object, *, index: int) -> str:
|
|
169
|
+
"""Return *raw* if it is an ISO-8601 timestamp string.
|
|
170
|
+
|
|
171
|
+
``Z`` is accepted as UTC. Non-strings and unparseable values fail locally
|
|
172
|
+
so they never become cell-history labels.
|
|
173
|
+
"""
|
|
174
|
+
if not isinstance(raw, str):
|
|
175
|
+
raise ValueError(f"logEntries[{index}] createdAt must be an ISO-8601 string")
|
|
176
|
+
candidate = raw[:-1] + "+00:00" if raw.endswith("Z") else raw
|
|
177
|
+
try:
|
|
178
|
+
datetime.fromisoformat(candidate)
|
|
179
|
+
except ValueError as exc:
|
|
180
|
+
raise ValueError(f"logEntries[{index}] createdAt must be ISO-8601") from exc
|
|
181
|
+
return raw
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _sheet_column_count(sheet: Mapping[str, object]) -> int:
|
|
185
|
+
"""Return 1 + max ``columnOrder`` in the sheet cells, or 0 if none."""
|
|
186
|
+
cells = sheet.get("magicTableCells")
|
|
187
|
+
if not isinstance(cells, list):
|
|
188
|
+
return 0
|
|
189
|
+
orders = [
|
|
190
|
+
order
|
|
191
|
+
for cell in cells
|
|
192
|
+
if isinstance(cell, dict)
|
|
193
|
+
for order in [cell.get("columnOrder")]
|
|
194
|
+
if isinstance(order, int)
|
|
195
|
+
]
|
|
196
|
+
return max(orders) + 1 if orders else 0
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _read_cell_text(
|
|
200
|
+
*,
|
|
201
|
+
text: str | None,
|
|
202
|
+
file: str | None,
|
|
203
|
+
stdin: bool,
|
|
204
|
+
) -> str:
|
|
205
|
+
"""Return cell text from exactly one of ``text``, ``file``, or stdin.
|
|
206
|
+
|
|
207
|
+
Raises ``ValueError`` with an unprefixed message when the sources are
|
|
208
|
+
missing, ambiguous, unreadable, empty, or a TTY. Whitespace-only text is
|
|
209
|
+
kept: the API treats it as non-empty.
|
|
210
|
+
"""
|
|
211
|
+
sources = sum([text is not None, file is not None, stdin])
|
|
212
|
+
if sources == 0:
|
|
213
|
+
raise ValueError("cell text is required: pass --text, --file, or --stdin")
|
|
214
|
+
if sources > 1:
|
|
215
|
+
raise ValueError(
|
|
216
|
+
"ambiguous input: provide exactly one of --text, --file, or --stdin"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
if stdin:
|
|
220
|
+
if sys.stdin.isatty():
|
|
221
|
+
raise ValueError("stdin is a tty: pipe input or use --text / --file")
|
|
222
|
+
body = sys.stdin.read()
|
|
223
|
+
elif file is not None:
|
|
224
|
+
try:
|
|
225
|
+
body = Path(file).read_text(encoding="utf-8")
|
|
226
|
+
except _LOG_FILE_ERRORS as exc:
|
|
227
|
+
raise ValueError(f"could not read --file: {exc}") from exc
|
|
228
|
+
else:
|
|
229
|
+
assert text is not None
|
|
230
|
+
body = text
|
|
231
|
+
|
|
232
|
+
if body == "":
|
|
233
|
+
raise ValueError("cell text is empty")
|
|
234
|
+
return body
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _parse_log_entries(
|
|
238
|
+
*,
|
|
239
|
+
log_file: str | None,
|
|
240
|
+
log_json: str | None,
|
|
241
|
+
) -> list[LogEntry] | None:
|
|
242
|
+
"""Parse optional log entries from a file or an inline JSON array.
|
|
243
|
+
|
|
244
|
+
Raises ``ValueError`` with an unprefixed message when both sources are
|
|
245
|
+
set, JSON is invalid, or a required field is missing. ``None`` means
|
|
246
|
+
omit ``logEntries`` from the request.
|
|
247
|
+
"""
|
|
248
|
+
if log_file is not None and log_json is not None:
|
|
249
|
+
raise ValueError(
|
|
250
|
+
"ambiguous logs: provide at most one of --log-file or --log-json"
|
|
251
|
+
)
|
|
252
|
+
raw: str | None
|
|
253
|
+
if log_file is not None:
|
|
254
|
+
try:
|
|
255
|
+
raw = Path(log_file).read_text(encoding="utf-8")
|
|
256
|
+
except _LOG_FILE_ERRORS as exc:
|
|
257
|
+
raise ValueError(f"could not read --log-file: {exc}") from exc
|
|
258
|
+
elif log_json is not None:
|
|
259
|
+
raw = log_json
|
|
260
|
+
else:
|
|
261
|
+
return None
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
parsed = json.loads(raw)
|
|
265
|
+
except json.JSONDecodeError as exc:
|
|
266
|
+
raise ValueError(f"log entries must be JSON: {exc}") from exc
|
|
267
|
+
|
|
268
|
+
if not isinstance(parsed, list):
|
|
269
|
+
raise ValueError("log entries must be a JSON array")
|
|
270
|
+
|
|
271
|
+
entries: list[LogEntry] = []
|
|
272
|
+
for index, item in enumerate(parsed):
|
|
273
|
+
if not isinstance(item, dict):
|
|
274
|
+
raise ValueError(f"logEntries[{index}] must be an object")
|
|
275
|
+
missing = [key for key in ("text", "actorType", "createdAt") if key not in item]
|
|
276
|
+
if missing:
|
|
277
|
+
raise ValueError(
|
|
278
|
+
f"logEntries[{index}] missing required field(s): {', '.join(missing)}"
|
|
279
|
+
)
|
|
280
|
+
actor_raw = item["actorType"]
|
|
281
|
+
if not isinstance(actor_raw, str) or actor_raw not in _LOG_ACTOR_TYPES:
|
|
282
|
+
raise ValueError(
|
|
283
|
+
f"logEntries[{index}] actorType must be one of "
|
|
284
|
+
f"{', '.join(sorted(_LOG_ACTOR_TYPES))}"
|
|
285
|
+
)
|
|
286
|
+
text_raw = item["text"]
|
|
287
|
+
if not isinstance(text_raw, str):
|
|
288
|
+
raise ValueError(f"logEntries[{index}] text must be a string")
|
|
289
|
+
actor = cast(Literal["USER", "SYSTEM", "ASSISTANT", "TOOL"], actor_raw)
|
|
290
|
+
entry: LogEntry = {
|
|
291
|
+
"text": text_raw,
|
|
292
|
+
"actorType": actor,
|
|
293
|
+
"createdAt": _parse_log_created_at(item["createdAt"], index=index),
|
|
294
|
+
}
|
|
295
|
+
message_id = item.get("messageId")
|
|
296
|
+
if message_id is not None:
|
|
297
|
+
if not isinstance(message_id, str):
|
|
298
|
+
raise ValueError(f"logEntries[{index}] messageId must be a string")
|
|
299
|
+
entry["messageId"] = message_id
|
|
300
|
+
if "details" in item and item["details"] is not None:
|
|
301
|
+
if not isinstance(item["details"], dict):
|
|
302
|
+
raise ValueError(f"logEntries[{index}] details must be an object")
|
|
303
|
+
entry["details"] = cast(LogDetail, cast(object, item["details"]))
|
|
304
|
+
entries.append(entry)
|
|
305
|
+
return entries
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def cmd_set_cell(
|
|
309
|
+
state: ShellState,
|
|
310
|
+
table_id: str,
|
|
311
|
+
*,
|
|
312
|
+
row_order: int,
|
|
313
|
+
column_order: int,
|
|
314
|
+
text: str | None = None,
|
|
315
|
+
file: str | None = None,
|
|
316
|
+
stdin: bool = False,
|
|
317
|
+
log_file: str | None = None,
|
|
318
|
+
log_json: str | None = None,
|
|
319
|
+
allow_create: bool = False,
|
|
320
|
+
force: bool = False,
|
|
321
|
+
output_json: bool = False,
|
|
322
|
+
) -> str:
|
|
323
|
+
"""Upsert one cell (``POST /magic-table/{id}/cell``).
|
|
324
|
+
|
|
325
|
+
Writes the given text at ``(row_order, column_order)``. This is not a
|
|
326
|
+
run: unlike ``import`` / ``rerun-row`` it does not start the table agent.
|
|
327
|
+
Row 0 (the header) is allowed. ``allow_create`` may add only the next
|
|
328
|
+
row or column; a gap is refused. A ``PROCESSING`` sheet is refused
|
|
329
|
+
unless ``force``.
|
|
330
|
+
"""
|
|
331
|
+
try:
|
|
332
|
+
cell_text = _read_cell_text(text=text, file=file, stdin=stdin)
|
|
333
|
+
log_entries = _parse_log_entries(log_file=log_file, log_json=log_json)
|
|
334
|
+
except ValueError as exc:
|
|
335
|
+
return f"{AGENTIC_TABLE_ERROR_PREFIX} {exc}"
|
|
336
|
+
|
|
337
|
+
params: AgenticTable.SetCell = {
|
|
338
|
+
"tableId": table_id,
|
|
339
|
+
"rowOrder": row_order,
|
|
340
|
+
"columnOrder": column_order,
|
|
341
|
+
"text": cell_text,
|
|
342
|
+
}
|
|
343
|
+
if log_entries is not None:
|
|
344
|
+
params["logEntries"] = log_entries
|
|
345
|
+
|
|
346
|
+
async def _run() -> str:
|
|
347
|
+
# GET + POST in one loop; a second asyncio.run closes the HTTP client.
|
|
348
|
+
sheet = await AgenticTable.get_sheet_data(
|
|
349
|
+
user_id=state.config.user_id,
|
|
350
|
+
company_id=state.config.company_id,
|
|
351
|
+
tableId=table_id,
|
|
352
|
+
includeCells=True,
|
|
353
|
+
includeRowCount=True,
|
|
354
|
+
rowOrders=[0],
|
|
355
|
+
)
|
|
356
|
+
if sheet["state"] == AgenticTableSheetState.PROCESSING and not force:
|
|
357
|
+
return (
|
|
358
|
+
f"{AGENTIC_TABLE_ERROR_PREFIX} sheet is PROCESSING; wait for IDLE "
|
|
359
|
+
"or pass --force"
|
|
360
|
+
)
|
|
361
|
+
row_count = sheet.get("magicTableRowCount")
|
|
362
|
+
if not isinstance(row_count, int):
|
|
363
|
+
row_count = 0
|
|
364
|
+
column_count = _sheet_column_count(sheet)
|
|
365
|
+
if allow_create:
|
|
366
|
+
if row_order > row_count:
|
|
367
|
+
return (
|
|
368
|
+
f"{AGENTIC_TABLE_ERROR_PREFIX} row {row_order} is too far "
|
|
369
|
+
f"(sheet has {row_count} rows); --allow-create only adds the next "
|
|
370
|
+
"row"
|
|
371
|
+
)
|
|
372
|
+
if column_order > column_count:
|
|
373
|
+
return (
|
|
374
|
+
f"{AGENTIC_TABLE_ERROR_PREFIX} col {column_order} is too far "
|
|
375
|
+
f"(sheet has {column_count} columns); --allow-create only adds "
|
|
376
|
+
"the next column"
|
|
377
|
+
)
|
|
378
|
+
else:
|
|
379
|
+
if row_order >= row_count:
|
|
380
|
+
return (
|
|
381
|
+
f"{AGENTIC_TABLE_ERROR_PREFIX} row {row_order} is out of range "
|
|
382
|
+
f"(sheet has {row_count} rows); pass --allow-create to add a row"
|
|
383
|
+
)
|
|
384
|
+
if column_order >= column_count:
|
|
385
|
+
return (
|
|
386
|
+
f"{AGENTIC_TABLE_ERROR_PREFIX} col {column_order} is out of range "
|
|
387
|
+
f"(sheet has {column_count} columns); pass --allow-create to add a "
|
|
388
|
+
"column"
|
|
389
|
+
)
|
|
390
|
+
cell = await AgenticTable.set_cell(
|
|
391
|
+
user_id=state.config.user_id,
|
|
392
|
+
company_id=state.config.company_id,
|
|
393
|
+
**params,
|
|
394
|
+
)
|
|
395
|
+
if output_json:
|
|
396
|
+
return json.dumps(cell, indent=2, default=str)
|
|
397
|
+
return format_agentic_table_cell(cell)
|
|
398
|
+
|
|
399
|
+
try:
|
|
400
|
+
return asyncio.run(_run())
|
|
401
|
+
except UniqueError as exc:
|
|
402
|
+
return _error(exc)
|
|
403
|
+
|
|
404
|
+
|
|
155
405
|
def cmd_create_sheet(
|
|
156
406
|
state: ShellState,
|
|
157
407
|
assistant_id: str,
|
|
@@ -4,11 +4,11 @@ description: >-
|
|
|
4
4
|
Read and drive Agentic Table (magic table / due-diligence) sheets through the
|
|
5
5
|
unique-cli agentic-table command. Use when the user or task involves an
|
|
6
6
|
Agentic Table: inspecting a sheet's state, a cell's value or lock state, a
|
|
7
|
-
cell's edit history or its export artifacts;
|
|
8
|
-
creating a sheet, importing a questionnaire
|
|
9
|
-
agent to answer, and exporting the result.
|
|
10
|
-
the platform and varies from sheet to sheet;
|
|
11
|
-
`agentic-table: permission denied`.
|
|
7
|
+
cell's edit history or its export artifacts; writing text into a specific
|
|
8
|
+
cell; or running the full loop — creating a sheet, importing a questionnaire
|
|
9
|
+
and sources, waiting for the agent to answer, and exporting the result.
|
|
10
|
+
Access is enforced per sheet by the platform and varies from sheet to sheet;
|
|
11
|
+
a denial is reported as `agentic-table: permission denied`.
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# Unique CLI -- Agentic Table
|
|
@@ -21,17 +21,19 @@ Commands fall into two groups:
|
|
|
21
21
|
|
|
22
22
|
- **Read (Tier 0)** — `get-sheet`, `get-cell`, `cell-history`, `list-exports`.
|
|
23
23
|
Never modify anything, never need confirmation.
|
|
24
|
-
- **Write (Tier 1)** — `create-sheet`, `import`, `export`, `rerun-row
|
|
25
|
-
create a sheet, add questions and sources, start the agent
|
|
26
|
-
export artifacts,
|
|
27
|
-
|
|
28
|
-
afterwards.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
- **Write (Tier 1)** — `create-sheet`, `import`, `export`, `rerun-row`,
|
|
25
|
+
`set-cell`. These create a sheet, add questions and sources, start the agent
|
|
26
|
+
run, produce export artifacts, redo a single generated answer, or write
|
|
27
|
+
text you already have into one cell. None of them prompts for confirmation,
|
|
28
|
+
but they do change a shared artifact, so say what you did afterwards.
|
|
29
|
+
|
|
30
|
+
`create-sheet`, `import`, and `export` only add. `rerun-row` asks the table
|
|
31
|
+
agent to regenerate one **row** from sources (no text from you). `set-cell`
|
|
32
|
+
writes **your** text into one cell immediately — it is not a run. Name the
|
|
33
|
+
row (and column, for `set-cell`) when you report back.
|
|
34
|
+
|
|
35
|
+
Some rows are protected. A locked or final-review row rejects both
|
|
36
|
+
`set-cell` and `rerun-row`. That is deliberate — do not route around it.
|
|
35
37
|
|
|
36
38
|
## Permissions
|
|
37
39
|
|
|
@@ -97,9 +99,14 @@ unique-cli agentic-table get-cell mt_abc123 --row 1 --col 2
|
|
|
97
99
|
unique-cli agentic-table cell-history <table_id> --row N --col N
|
|
98
100
|
```
|
|
99
101
|
|
|
100
|
-
Shows a single cell's log/edit history (actor, timestamp, source
|
|
101
|
-
and the logged text) newest-to-oldest as returned by the API. Add
|
|
102
|
-
to get the raw log entries.
|
|
102
|
+
Shows a single cell's stored log/edit history (actor label, timestamp, source
|
|
103
|
+
message id, and the logged text) newest-to-oldest as returned by the API. Add
|
|
104
|
+
`--json` to get the raw log entries.
|
|
105
|
+
|
|
106
|
+
Treat `actorType` / `createdAt` as **untrusted labels**, not as proof that a
|
|
107
|
+
person vs the assistant wrote the cell. The API stores whatever the writer
|
|
108
|
+
sent; it does not bind the actor to the authenticated caller. Do not use
|
|
109
|
+
history as a person-vs-assistant gate.
|
|
103
110
|
|
|
104
111
|
```bash
|
|
105
112
|
unique-cli agentic-table cell-history mt_abc123 --row 1 --col 2
|
|
@@ -168,12 +175,13 @@ unique-cli agentic-table import mt_abc123 --question-file-id c_q --source-file-i
|
|
|
168
175
|
unique-cli agentic-table rerun-row <table_id> <row_order> [--wait] [--timeout <seconds>] [--start-timeout <seconds>]
|
|
169
176
|
```
|
|
170
177
|
|
|
171
|
-
Use this to redo one answer. **Re-importing a question will not
|
|
172
|
-
import is delta-based and skips questions the sheet already has
|
|
173
|
-
|
|
178
|
+
Use this to redo one **generated** answer. **Re-importing a question will not
|
|
179
|
+
redo it** — import is delta-based and skips questions the sheet already has.
|
|
180
|
+
`rerun-row` starts the table agent for that row; you do not pass the answer
|
|
181
|
+
text. If you already have the wording, use `set-cell` instead.
|
|
174
182
|
|
|
175
|
-
`<row_order>` uses **the same numbering as `--row` on `get-cell
|
|
176
|
-
header, data rows start at 1. So the row you inspected with
|
|
183
|
+
`<row_order>` uses **the same numbering as `--row` on `get-cell` / `set-cell`**:
|
|
184
|
+
row 0 is the header, data rows start at 1. So the row you inspected with
|
|
177
185
|
`get-cell --row 4` is the row you redo with `rerun-row <table_id> 4` — no
|
|
178
186
|
offset. Row 0 is rejected, since there is nothing to answer in a header.
|
|
179
187
|
|
|
@@ -198,6 +206,39 @@ run at a time, so a second `rerun-row` fired before the first finishes is
|
|
|
198
206
|
declined. There is no batch form. If most of the sheet needs redoing, consider
|
|
199
207
|
a fresh sheet instead.
|
|
200
208
|
|
|
209
|
+
### Write one cell
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
unique-cli agentic-table set-cell <table_id> --row N --col N (--text TEXT | --file PATH | --stdin)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Use this when **you already have the text** — the user gave the wording, you
|
|
216
|
+
copied a cell, or you researched the answer yourself. It writes that one cell
|
|
217
|
+
immediately. It does not start the table agent.
|
|
218
|
+
|
|
219
|
+
`--row` / `--col` are the same 0-based numbers as `get-cell`. Row 0 (the
|
|
220
|
+
header) **can** be set. Find coordinates with `get-sheet --cells` or
|
|
221
|
+
`get-cell` first. A coordinate that does not exist is **refused** unless you
|
|
222
|
+
pass `--allow-create` for the **next** row or column only (`--row 5` on a
|
|
223
|
+
5-row sheet). A far-off number (`--row 50`) is still refused: the API would
|
|
224
|
+
create a gap.
|
|
225
|
+
|
|
226
|
+
There is no batch form. Several cells means several `set-cell` calls. The
|
|
227
|
+
sheet must be `IDLE`; `PROCESSING` is refused unless you pass `--force` (the
|
|
228
|
+
row-runner can overwrite the cell).
|
|
229
|
+
|
|
230
|
+
Long or multi-line answers: `--file` or `--stdin`, not `--text`. Prefer omitting
|
|
231
|
+
`--log-json` / `--log-file`. If you attach a note, send `{text, actorType,
|
|
232
|
+
createdAt}` with `actorType` `TOOL` or `ASSISTANT` and a current ISO-8601 time.
|
|
233
|
+
`USER` and `SYSTEM` are rejected by the CLI.
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
unique-cli agentic-table set-cell mt_abc123 --row 1 --col 2 --text "The management fee is 2%."
|
|
237
|
+
unique-cli agentic-table set-cell mt_abc123 --row 1 --col 2 --file ./answer.md
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
After a write, say which row and column you changed.
|
|
241
|
+
|
|
201
242
|
### Export answers
|
|
202
243
|
|
|
203
244
|
```bash
|
|
@@ -234,32 +275,38 @@ empty and the rest of the chain running against a sheet that does not exist.
|
|
|
234
275
|
|
|
235
276
|
To fill in an existing questionnaire from a sheet someone else has already
|
|
236
277
|
answered, skip the create and import steps: read the answers with
|
|
237
|
-
`get-sheet --cells` or `get-cell
|
|
238
|
-
|
|
278
|
+
`get-sheet --cells` or `get-cell`. `cell-history` is a stored log, not a bound
|
|
279
|
+
identity signal — do not treat actor labels as proof a person vs the assistant
|
|
280
|
+
wrote the cell.
|
|
239
281
|
|
|
240
|
-
If a
|
|
241
|
-
and export again
|
|
242
|
-
|
|
282
|
+
If a generated answer looks wrong and you want the table agent to try again,
|
|
283
|
+
fix that row with `rerun-row` and export again — not `set-cell`, and not
|
|
284
|
+
re-import.
|
|
243
285
|
|
|
244
286
|
## Rules
|
|
245
287
|
|
|
246
288
|
1. Rows and columns are numbered from 0, and row 0 is the header — so the first
|
|
247
|
-
question is row 1. This holds for `--row`/`--col` on `get-cell
|
|
248
|
-
`cell-history` and for `<row_order>` on `rerun-row
|
|
249
|
-
means the same row in every command.
|
|
289
|
+
question is row 1. This holds for `--row`/`--col` on `get-cell`,
|
|
290
|
+
`cell-history`, and `set-cell`, and for `<row_order>` on `rerun-row`; the
|
|
291
|
+
same number means the same row in every command. `set-cell` may write row 0;
|
|
292
|
+
`rerun-row` may not.
|
|
250
293
|
2. Fetch what you need, not everything. `get-cell` for one value,
|
|
251
294
|
`get-sheet --cells` for an overview — don't dump a whole sheet unless asked.
|
|
295
|
+
Look up coordinates before `set-cell`; do not guess a column index.
|
|
252
296
|
3. Use `--wait` when a later step depends on the result, and only then. Without
|
|
253
297
|
it, `import` and `export` return as soon as the request is accepted, and the
|
|
254
|
-
answers or artifacts will not be ready yet.
|
|
298
|
+
answers or artifacts will not be ready yet. `set-cell` has no `--wait`: the
|
|
299
|
+
cell is updated when the command returns.
|
|
255
300
|
4. Never re-run `import` with the same questions to "retry" — ids and texts
|
|
256
301
|
already on the sheet are skipped, and a run that is already in flight will
|
|
257
302
|
reject the call.
|
|
258
303
|
5. Tell the user what you changed. A sheet is shared, and someone else may be
|
|
259
|
-
working in it.
|
|
304
|
+
working in it. For `set-cell`, name the row and column.
|
|
260
305
|
6. Use `--json` when you need to parse fields programmatically (e.g. reading a
|
|
261
306
|
`contentId` before downloading an export); use the default formatted output
|
|
262
307
|
when summarising for a person.
|
|
308
|
+
7. `set-cell` when you have the text. `rerun-row` when the table agent should
|
|
309
|
+
regenerate from sources. Never both for the same correction.
|
|
263
310
|
|
|
264
311
|
## Prerequisites
|
|
265
312
|
|
|
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
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/__init__.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_acronyms.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_agentic_table.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_analytics_order.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_benchmarking.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_briefing.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_chat_completion.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_content.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_context_memory.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_elicitation.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_embedding.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_integrated.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_llm_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message_log.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_message_tool.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_scheduled_task.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_search_string.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/api_resources/_web_search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/agentic_table.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/cite_file.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/elicitation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/navigation.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/scheduled_tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/web_search.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/cli/commands/web_search_config.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
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/analytics_order_run.py
RENAMED
|
File without changes
|
{unique_sdk-2026.42.0.dev1 → unique_sdk-2026.42.0.dev2}/unique_sdk/utils/benchmarking_run.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|