unique-sdk 2026.32.0.dev7__tar.gz → 2026.32.0.dev9__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.32.0.dev7 → unique_sdk-2026.32.0.dev9}/PKG-INFO +1 -1
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/pyproject.toml +1 -1
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/__init__.py +0 -3
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/cli.py +0 -103
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/web_search.py +39 -2
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-file-management/SKILL.md +25 -18
- unique_sdk-2026.32.0.dev7/unique_sdk/api_resources/_dynamic_frontend.py +0 -101
- unique_sdk-2026.32.0.dev7/unique_sdk/cli/commands/dynamic_frontend.py +0 -155
- unique_sdk-2026.32.0.dev7/unique_sdk/cli/skills/unique-cli-dynamic-frontend/SKILL.md +0 -151
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/README.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_api_requestor.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_api_resource.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_api_version.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_error.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_http_client.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_list_object.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_object_classes.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_request_options.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_unique_object.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_unique_ql.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_unique_response.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_util.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_version.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/_webhook.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/__init__.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_acronyms.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_agentic_table.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_analytics_order.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_benchmarking.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_briefing.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_chat_completion.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_content.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_elicitation.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_embedding.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_event.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_folder.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_group.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_integrated.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_llm_models.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_mcp.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message_assessment.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message_execution.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message_log.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message_tool.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_module.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_scheduled_task.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_search.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_search_string.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_short_term_memory.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_space.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_user.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_web_search.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/__init__.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/__main__.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/__init__.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/_citation_manifest.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/agentic_table.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/browser.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/cite_file.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/elicitation.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/files.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/folders.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/mcp.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/navigation.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/read.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/scheduled_tasks.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/search.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/subagent.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/web_search_config.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/config.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/formatting.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/identity.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/metadata_filter.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/shell.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-agentic-table/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-elicitation/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-mcp/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-scheduled-tasks/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-search/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-subagent/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-uploaded-search/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/skills/unique-cli-web-search/SKILL.md +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/state.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/analytics_order_run.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/benchmarking_run.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/chat_history.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/chat_in_space.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/file_io.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/sources.py +0 -0
- {unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/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.32.0.
|
|
3
|
+
Version: 2026.32.0.dev9
|
|
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>
|
|
@@ -77,9 +77,6 @@ from unique_sdk.api_resources._message import Message as Message
|
|
|
77
77
|
from unique_sdk.api_resources._integrated import Integrated as Integrated
|
|
78
78
|
from unique_sdk.api_resources._search import Search as Search
|
|
79
79
|
from unique_sdk.api_resources._content import Content as Content
|
|
80
|
-
from unique_sdk.api_resources._dynamic_frontend import (
|
|
81
|
-
DynamicFrontend as DynamicFrontend,
|
|
82
|
-
)
|
|
83
80
|
from unique_sdk.api_resources._search_string import SearchString as SearchString
|
|
84
81
|
from unique_sdk.api_resources._short_term_memory import (
|
|
85
82
|
ShortTermMemory as ShortTermMemory,
|
|
@@ -31,11 +31,6 @@ from unique_sdk.cli.commands.cite_file import cmd_cite_file
|
|
|
31
31
|
from unique_sdk.cli.commands.cite_file import (
|
|
32
32
|
is_error_output as _is_cite_error_output,
|
|
33
33
|
)
|
|
34
|
-
from unique_sdk.cli.commands.dynamic_frontend import (
|
|
35
|
-
cmd_dynamic_frontend_delete,
|
|
36
|
-
cmd_dynamic_frontend_deploy,
|
|
37
|
-
cmd_dynamic_frontend_list,
|
|
38
|
-
)
|
|
39
34
|
from unique_sdk.cli.commands.elicitation import (
|
|
40
35
|
DEFAULT_WAIT_TIMEOUT_SECONDS,
|
|
41
36
|
cmd_elicit_ask,
|
|
@@ -97,8 +92,6 @@ from unique_sdk.cli.identity import TurnIdentityError, resolve_message_id
|
|
|
97
92
|
from unique_sdk.cli.shell import UniqueShell
|
|
98
93
|
from unique_sdk.cli.state import ShellState
|
|
99
94
|
|
|
100
|
-
_DYNAMIC_FRONTEND_ERROR_PREFIX = "dynamic-frontend "
|
|
101
|
-
|
|
102
95
|
|
|
103
96
|
def _resolve_cli_message_id(
|
|
104
97
|
ctx: click.Context,
|
|
@@ -174,7 +167,6 @@ Examples:
|
|
|
174
167
|
unique-cli subagent Legal "Review" Invoke a connected space/subagent
|
|
175
168
|
unique-cli web-search search "x" Search the web via the public API
|
|
176
169
|
unique-cli web-search crawl URL Crawl a URL via the public API
|
|
177
|
-
unique-cli dynamic-frontend list List manageable Dynamic Frontend spaces
|
|
178
170
|
unique-cli browser get-dom Read the user's live Chrome tab (a11y tree)
|
|
179
171
|
unique-cli agentic-table get-sheet mt_abc123 Show a magic-table sheet summary
|
|
180
172
|
"""
|
|
@@ -582,101 +574,6 @@ def read_cmd(
|
|
|
582
574
|
emit(output, is_error=_is_read_error_output)
|
|
583
575
|
|
|
584
576
|
|
|
585
|
-
@main.group(name="dynamic-frontend")
|
|
586
|
-
def dynamic_frontend() -> None:
|
|
587
|
-
"""Deploy, list, and delete Dynamic Frontend spaces."""
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
@dynamic_frontend.command(name="deploy")
|
|
591
|
-
@click.option(
|
|
592
|
-
"--file",
|
|
593
|
-
"file_path",
|
|
594
|
-
default=None,
|
|
595
|
-
type=click.Path(exists=True),
|
|
596
|
-
help="Path to an upload-ready Dynamic Frontend ZIP bundle.",
|
|
597
|
-
)
|
|
598
|
-
@click.option(
|
|
599
|
-
"--content-id",
|
|
600
|
-
default=None,
|
|
601
|
-
help="Existing Knowledge Base content id for the ZIP bundle.",
|
|
602
|
-
)
|
|
603
|
-
@click.option(
|
|
604
|
-
"--name",
|
|
605
|
-
default=None,
|
|
606
|
-
help="Space display name. Required when creating; optional rename when updating.",
|
|
607
|
-
)
|
|
608
|
-
@click.option(
|
|
609
|
-
"--space-id", default=None, help="Existing Dynamic Frontend space id to update."
|
|
610
|
-
)
|
|
611
|
-
@click.option(
|
|
612
|
-
"--json", "output_json", is_flag=True, default=False, help="Print raw JSON."
|
|
613
|
-
)
|
|
614
|
-
@click.pass_context
|
|
615
|
-
def dynamic_frontend_deploy(
|
|
616
|
-
ctx: click.Context,
|
|
617
|
-
file_path: str | None,
|
|
618
|
-
content_id: str | None,
|
|
619
|
-
name: str | None,
|
|
620
|
-
space_id: str | None,
|
|
621
|
-
output_json: bool,
|
|
622
|
-
) -> None:
|
|
623
|
-
"""Create or update a Dynamic Frontend space.
|
|
624
|
-
|
|
625
|
-
\b
|
|
626
|
-
Examples:
|
|
627
|
-
unique-cli dynamic-frontend deploy --file ./app.zip --name "Revenue Dashboard"
|
|
628
|
-
unique-cli dynamic-frontend deploy --content-id content_123 --name "Revenue Dashboard"
|
|
629
|
-
unique-cli dynamic-frontend deploy --space-id assistant_123 --file ./app.zip
|
|
630
|
-
"""
|
|
631
|
-
output = cmd_dynamic_frontend_deploy(
|
|
632
|
-
LazyState.get(ctx),
|
|
633
|
-
file=file_path,
|
|
634
|
-
content_id=content_id,
|
|
635
|
-
name=name,
|
|
636
|
-
space_id=space_id,
|
|
637
|
-
output_json=output_json,
|
|
638
|
-
)
|
|
639
|
-
click.echo(output)
|
|
640
|
-
if output.startswith(_DYNAMIC_FRONTEND_ERROR_PREFIX):
|
|
641
|
-
ctx.exit(1)
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
@dynamic_frontend.command(name="list")
|
|
645
|
-
@click.option(
|
|
646
|
-
"--json", "output_json", is_flag=True, default=False, help="Print raw JSON."
|
|
647
|
-
)
|
|
648
|
-
@click.pass_context
|
|
649
|
-
def dynamic_frontend_list(ctx: click.Context, output_json: bool) -> None:
|
|
650
|
-
"""List Dynamic Frontend spaces the current user can manage."""
|
|
651
|
-
output = cmd_dynamic_frontend_list(LazyState.get(ctx), output_json=output_json)
|
|
652
|
-
click.echo(output)
|
|
653
|
-
if output.startswith(_DYNAMIC_FRONTEND_ERROR_PREFIX):
|
|
654
|
-
ctx.exit(1)
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
@dynamic_frontend.command(name="delete")
|
|
658
|
-
@click.argument("space_id")
|
|
659
|
-
@click.option(
|
|
660
|
-
"--json", "output_json", is_flag=True, default=False, help="Print raw JSON."
|
|
661
|
-
)
|
|
662
|
-
@click.pass_context
|
|
663
|
-
def dynamic_frontend_delete(
|
|
664
|
-
ctx: click.Context, space_id: str, output_json: bool
|
|
665
|
-
) -> None:
|
|
666
|
-
"""Delete a deployed Dynamic Frontend space by its space id.
|
|
667
|
-
|
|
668
|
-
\b
|
|
669
|
-
Example:
|
|
670
|
-
unique-cli dynamic-frontend delete assistant_123
|
|
671
|
-
"""
|
|
672
|
-
output = cmd_dynamic_frontend_delete(
|
|
673
|
-
LazyState.get(ctx), space_id, output_json=output_json
|
|
674
|
-
)
|
|
675
|
-
click.echo(output)
|
|
676
|
-
if output.startswith(_DYNAMIC_FRONTEND_ERROR_PREFIX):
|
|
677
|
-
ctx.exit(1)
|
|
678
|
-
|
|
679
|
-
|
|
680
577
|
@main.command()
|
|
681
578
|
@click.argument("name_or_id")
|
|
682
579
|
@click.pass_context
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/web_search.py
RENAMED
|
@@ -67,6 +67,29 @@ def _next_source_number(entries: list[dict[str, Any]]) -> int:
|
|
|
67
67
|
return max(source_numbers, default=0) + 1
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
def _fetch_error_message(content: Any) -> str | None:
|
|
71
|
+
"""Extract the failure message when ``content`` is a crawl-error payload.
|
|
72
|
+
|
|
73
|
+
The web-search backend reports per-URL fetch failures in-band: proxy
|
|
74
|
+
crawlers return ``"URL: <url>\\n\\nError: <message>"``, Tavily/Jina a
|
|
75
|
+
bare ``"Error: <message>"``. Returns the message for error payloads and
|
|
76
|
+
``None`` for real page content.
|
|
77
|
+
|
|
78
|
+
Any leading ``URL: …`` line is skipped without matching it against the
|
|
79
|
+
result's own URL — redirects or normalization can make the reported URL
|
|
80
|
+
differ from the requested one.
|
|
81
|
+
"""
|
|
82
|
+
if not isinstance(content, str):
|
|
83
|
+
return None
|
|
84
|
+
stripped = content.strip()
|
|
85
|
+
first_line, _, rest = stripped.partition("\n")
|
|
86
|
+
if first_line.startswith("URL:"):
|
|
87
|
+
stripped = rest.lstrip()
|
|
88
|
+
if stripped.startswith("Error:"):
|
|
89
|
+
return stripped[len("Error:") :].strip() or "unknown crawl error"
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
|
|
70
93
|
def _annotate_web_results_for_citations(
|
|
71
94
|
payload: dict[str, Any],
|
|
72
95
|
*,
|
|
@@ -78,6 +101,14 @@ def _annotate_web_results_for_citations(
|
|
|
78
101
|
``sourceNumber`` across consecutive ``search`` / ``crawl`` calls in
|
|
79
102
|
the same turn, so the crawled-content row carries the same citation
|
|
80
103
|
marker the search-snippet row already advertised.
|
|
104
|
+
|
|
105
|
+
Crawl-error payloads (``_fetch_error_message``) are kept out of the
|
|
106
|
+
manifest's ``content`` field and recorded under ``error`` instead: the
|
|
107
|
+
platform grounds the hallucination judge on manifest ``content``, so an
|
|
108
|
+
in-band fetch error stored as content turns a correctly cited,
|
|
109
|
+
snippet-verifiable source into a false "high hallucination" verdict
|
|
110
|
+
(UN-23356). The on-screen result still shows the error text so the
|
|
111
|
+
agent can react to the failed fetch.
|
|
81
112
|
"""
|
|
82
113
|
refs_log_path = refs_log_path or (Path.cwd() / _WEB_REFS_LOG_RELATIVE_PATH)
|
|
83
114
|
with _locked_turn_refs_manifest(
|
|
@@ -109,13 +140,19 @@ def _annotate_web_results_for_citations(
|
|
|
109
140
|
|
|
110
141
|
result["sourceNumber"] = source_number
|
|
111
142
|
result["citation"] = f"websource{source_number}"
|
|
143
|
+
content = result.get("content")
|
|
144
|
+
error = result.get("error")
|
|
145
|
+
fetch_error = _fetch_error_message(content)
|
|
146
|
+
if fetch_error is not None:
|
|
147
|
+
content = None
|
|
148
|
+
error = error or fetch_error
|
|
112
149
|
manifest_entry = {
|
|
113
150
|
"sourceNumber": source_number,
|
|
114
151
|
"url": url,
|
|
115
152
|
"title": result.get("title"),
|
|
116
153
|
"snippet": result.get("snippet"),
|
|
117
|
-
"content":
|
|
118
|
-
"error":
|
|
154
|
+
"content": content,
|
|
155
|
+
"error": error,
|
|
119
156
|
}
|
|
120
157
|
_append_turn_refs_manifest_entry(refs_log_path, manifest_entry)
|
|
121
158
|
annotated_results.append(result)
|
|
@@ -235,24 +235,29 @@ If you obtained the content some other way (you `download`ed the raw bytes and p
|
|
|
235
235
|
CSV, `.txt`, HTML, images) have no pages — always omit `--pages`** and cite the
|
|
236
236
|
whole file.
|
|
237
237
|
|
|
238
|
-
**Choosing `--read-method`** (declare the *representation*
|
|
238
|
+
**Choosing `--read-method`** (declare the *representation* you actually read the
|
|
239
|
+
cited value from). Pick it by the **modality you read** — NOT by how you *located*
|
|
240
|
+
the page. Locating a page with `unique-cli read` does **not** force `indexed`: if you
|
|
241
|
+
then rendered that page and read a chart/figure with vision, the method is `vision`.
|
|
239
242
|
|
|
240
243
|
- `text` → you used **extracted text** (`pdftotext`, PyMuPDF / `fitz` `page.get_text()`, MarkItDown, or any text extraction).
|
|
241
|
-
- `vision` → you read a **rendered image** of the page/slide (e.g. `get_pixmap()`) with your vision capability.
|
|
242
|
-
- `indexed` → you
|
|
244
|
+
- `vision` → you read a **rendered image** of the page/slide (e.g. `get_pixmap()`) with your vision capability — including when you located the page via `unique-cli read` but then rendered it to read a chart, figure, table, or scanned page.
|
|
245
|
+
- `indexed` → you used the **text returned by `unique-cli read`** (the platform's indexed chunks) as your answer source.
|
|
243
246
|
|
|
244
247
|
| Value | When to use |
|
|
245
248
|
|-------|-------------|
|
|
246
|
-
| `text` | You
|
|
247
|
-
| `vision` | You
|
|
248
|
-
| `indexed` | You
|
|
249
|
-
|
|
250
|
-
**Verify page numbers before citing — unless you
|
|
251
|
-
|
|
252
|
-
`[p.N]` / `[p.N-M]` markers are already
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
| `text` | You extracted the page/document text yourself and used that text. |
|
|
250
|
+
| `vision` | You read a rendered image of the page with your vision capability — even if you located the page via `unique-cli read`. |
|
|
251
|
+
| `indexed` | You used the text returned by `unique-cli read` (indexed chunks) as your source. |
|
|
252
|
+
|
|
253
|
+
**Verify page numbers before citing — unless you located them via `unique-cli read`.**
|
|
254
|
+
This is about the *page number* only, and is **independent of `--read-method`**. If you
|
|
255
|
+
located the page with `unique-cli read`, its `[p.N]` / `[p.N-M]` markers are already
|
|
256
|
+
physical positions — trust them and skip the checks below, even if you then rendered the
|
|
257
|
+
page and read it with vision (in that case still cite `--read-method vision`). Only when
|
|
258
|
+
you obtained the page some other way — you `download`ed the raw bytes and parsed them
|
|
259
|
+
yourself, or `read` returned no `[p.N]` markers — pick the row matching the file you read
|
|
260
|
+
and verify the cited content really is where you claim before calling `cite`:
|
|
256
261
|
|
|
257
262
|
- **PDF** — `pdfinfo file.pdf | grep Pages` for the total physical page count, then
|
|
258
263
|
for **each** page run `pdftotext -f N -l N file.pdf -` and confirm the content is
|
|
@@ -265,11 +270,13 @@ verify the cited content really is where you claim before calling `cite`:
|
|
|
265
270
|
- **Non-paginated (XLSX/CSV/TXT/HTML/images)** — there are no pages. Do **NOT**
|
|
266
271
|
pass `--pages`; cite the whole file and verify the content exists in it.
|
|
267
272
|
|
|
268
|
-
Then determine `--read-method
|
|
269
|
-
fallback chain (e.g. text extraction returned nothing →
|
|
270
|
-
report `text` if you used extracted text or `vision` if you read
|
|
271
|
-
|
|
272
|
-
|
|
273
|
+
Then determine `--read-method` by the **modality you actually read** — independent of
|
|
274
|
+
how you located the page. In a fallback chain (e.g. text extraction returned nothing →
|
|
275
|
+
render + read visually), report `text` if you used extracted text or `vision` if you read
|
|
276
|
+
a rendered image. If you located the page via `unique-cli read` but read the cited value
|
|
277
|
+
off a rendered image (a chart, figure, table, or scanned page), report `vision`, not
|
|
278
|
+
`indexed`. Only after confirming the page numbers, call `unique-cli cite` with the
|
|
279
|
+
verified page numbers (if any) and `--read-method`.
|
|
273
280
|
|
|
274
281
|
- **One method per `cite` call.** If different pages were read with different methods, issue separate `cite` calls — one per method.
|
|
275
282
|
- Numbers are **per-turn only**; do not reuse from prior turns.
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
from typing import Literal, cast
|
|
2
|
-
|
|
3
|
-
from typing_extensions import NotRequired, Unpack
|
|
4
|
-
|
|
5
|
-
from unique_sdk._api_resource import APIResource
|
|
6
|
-
from unique_sdk._request_options import RequestOptions
|
|
7
|
-
from unique_sdk._util import classproperty
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class DynamicFrontend(APIResource["DynamicFrontend"]):
|
|
11
|
-
@classproperty
|
|
12
|
-
def OBJECT_NAME(cls) -> Literal["dynamic-frontend"]:
|
|
13
|
-
return "dynamic-frontend"
|
|
14
|
-
|
|
15
|
-
id: str
|
|
16
|
-
spaceId: str
|
|
17
|
-
name: str
|
|
18
|
-
contentId: str
|
|
19
|
-
url: str | None
|
|
20
|
-
configUrl: str | None
|
|
21
|
-
status: dict[str, object] | None
|
|
22
|
-
|
|
23
|
-
class CreateParams(RequestOptions):
|
|
24
|
-
name: str
|
|
25
|
-
contentId: str
|
|
26
|
-
|
|
27
|
-
class UpdateParams(RequestOptions):
|
|
28
|
-
contentId: str
|
|
29
|
-
name: NotRequired[str | None]
|
|
30
|
-
|
|
31
|
-
@classmethod
|
|
32
|
-
def create(
|
|
33
|
-
cls,
|
|
34
|
-
user_id: str,
|
|
35
|
-
company_id: str,
|
|
36
|
-
**params: Unpack["DynamicFrontend.CreateParams"],
|
|
37
|
-
) -> "DynamicFrontend":
|
|
38
|
-
return cast(
|
|
39
|
-
DynamicFrontend,
|
|
40
|
-
cls._static_request(
|
|
41
|
-
"post",
|
|
42
|
-
"/dynamic-frontend",
|
|
43
|
-
user_id,
|
|
44
|
-
company_id,
|
|
45
|
-
params=params,
|
|
46
|
-
),
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
@classmethod
|
|
50
|
-
def modify(
|
|
51
|
-
cls,
|
|
52
|
-
space_id: str,
|
|
53
|
-
user_id: str,
|
|
54
|
-
company_id: str,
|
|
55
|
-
**params: Unpack["DynamicFrontend.UpdateParams"],
|
|
56
|
-
) -> "DynamicFrontend":
|
|
57
|
-
return cast(
|
|
58
|
-
DynamicFrontend,
|
|
59
|
-
cls._static_request(
|
|
60
|
-
"patch",
|
|
61
|
-
f"/dynamic-frontend/{space_id}",
|
|
62
|
-
user_id,
|
|
63
|
-
company_id,
|
|
64
|
-
params=params,
|
|
65
|
-
),
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
@classmethod
|
|
69
|
-
def delete(
|
|
70
|
-
cls,
|
|
71
|
-
space_id: str,
|
|
72
|
-
user_id: str,
|
|
73
|
-
company_id: str,
|
|
74
|
-
) -> "DynamicFrontend":
|
|
75
|
-
"""Delete a deployed Dynamic Frontend space."""
|
|
76
|
-
return cast(
|
|
77
|
-
DynamicFrontend,
|
|
78
|
-
cls._static_request(
|
|
79
|
-
"delete",
|
|
80
|
-
f"/dynamic-frontend/{space_id}",
|
|
81
|
-
user_id,
|
|
82
|
-
company_id,
|
|
83
|
-
),
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
@classmethod
|
|
87
|
-
def list(
|
|
88
|
-
cls,
|
|
89
|
-
user_id: str,
|
|
90
|
-
company_id: str,
|
|
91
|
-
) -> list["DynamicFrontend"]:
|
|
92
|
-
response = cls._static_request(
|
|
93
|
-
"get",
|
|
94
|
-
"/dynamic-frontend",
|
|
95
|
-
user_id,
|
|
96
|
-
company_id,
|
|
97
|
-
)
|
|
98
|
-
if isinstance(response, list):
|
|
99
|
-
return cast(list[DynamicFrontend], response)
|
|
100
|
-
data = response.get("data", []) if isinstance(response, dict) else []
|
|
101
|
-
return cast(list[DynamicFrontend], data)
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
import unique_sdk
|
|
7
|
-
from unique_sdk.cli.state import ShellState
|
|
8
|
-
from unique_sdk.utils.file_io import upload_file
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def _upload_bundle(state: ShellState, file_path: str) -> str:
|
|
12
|
-
path = Path(file_path).expanduser().resolve()
|
|
13
|
-
if not path.is_file():
|
|
14
|
-
raise ValueError(f"local file not found: {file_path}")
|
|
15
|
-
|
|
16
|
-
if not state.scope_id:
|
|
17
|
-
raise ValueError("cannot upload bundle to root. cd into a folder first.")
|
|
18
|
-
|
|
19
|
-
result = upload_file(
|
|
20
|
-
userId=state.config.user_id,
|
|
21
|
-
companyId=state.config.company_id,
|
|
22
|
-
path_to_file=str(path),
|
|
23
|
-
displayed_filename=path.name,
|
|
24
|
-
mime_type="application/zip",
|
|
25
|
-
scope_or_unique_path=state.scope_id,
|
|
26
|
-
)
|
|
27
|
-
content_id = getattr(result, "id", None)
|
|
28
|
-
if not isinstance(content_id, str) or not content_id:
|
|
29
|
-
raise ValueError("upload did not return a content id")
|
|
30
|
-
return content_id
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _format_space(space: object) -> str:
|
|
34
|
-
space_id = getattr(space, "spaceId", None) or getattr(space, "id", "")
|
|
35
|
-
name = getattr(space, "name", "")
|
|
36
|
-
content_id = getattr(space, "contentId", "")
|
|
37
|
-
status = getattr(space, "status", None)
|
|
38
|
-
phase = ""
|
|
39
|
-
url = str(getattr(space, "url", "") or "")
|
|
40
|
-
config_url = str(getattr(space, "configUrl", "") or "")
|
|
41
|
-
if isinstance(status, dict):
|
|
42
|
-
phase = str(status.get("phase") or "")
|
|
43
|
-
url = url or str(status.get("url") or "")
|
|
44
|
-
return "\t".join(
|
|
45
|
-
part
|
|
46
|
-
for part in [str(space_id), str(name), str(content_id), phase, url, config_url]
|
|
47
|
-
if part
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def cmd_dynamic_frontend_deploy(
|
|
52
|
-
state: ShellState,
|
|
53
|
-
*,
|
|
54
|
-
file: str | None = None,
|
|
55
|
-
content_id: str | None = None,
|
|
56
|
-
name: str | None = None,
|
|
57
|
-
space_id: str | None = None,
|
|
58
|
-
output_json: bool = False,
|
|
59
|
-
) -> str:
|
|
60
|
-
try:
|
|
61
|
-
if not file and not content_id:
|
|
62
|
-
return "dynamic-frontend deploy: provide either --file or --content-id."
|
|
63
|
-
if file and content_id:
|
|
64
|
-
return "dynamic-frontend deploy: --file and --content-id are mutually exclusive."
|
|
65
|
-
if not space_id and not name:
|
|
66
|
-
return "dynamic-frontend deploy: provide --name when creating a Dynamic Frontend space."
|
|
67
|
-
|
|
68
|
-
resolved_content_id = _upload_bundle(state, file) if file else content_id
|
|
69
|
-
if not resolved_content_id:
|
|
70
|
-
return "dynamic-frontend deploy: expected a content id after resolving deploy input."
|
|
71
|
-
|
|
72
|
-
if space_id:
|
|
73
|
-
update_params: unique_sdk.DynamicFrontend.UpdateParams = {
|
|
74
|
-
"contentId": resolved_content_id,
|
|
75
|
-
}
|
|
76
|
-
if name is not None:
|
|
77
|
-
update_params["name"] = name
|
|
78
|
-
space = unique_sdk.DynamicFrontend.modify(
|
|
79
|
-
space_id,
|
|
80
|
-
user_id=state.config.user_id,
|
|
81
|
-
company_id=state.config.company_id,
|
|
82
|
-
**update_params,
|
|
83
|
-
)
|
|
84
|
-
action = "Updated"
|
|
85
|
-
else:
|
|
86
|
-
space = unique_sdk.DynamicFrontend.create(
|
|
87
|
-
user_id=state.config.user_id,
|
|
88
|
-
company_id=state.config.company_id,
|
|
89
|
-
name=name or "",
|
|
90
|
-
contentId=resolved_content_id,
|
|
91
|
-
)
|
|
92
|
-
action = "Created"
|
|
93
|
-
|
|
94
|
-
if output_json:
|
|
95
|
-
return json.dumps(dict(space), indent=2, default=str)
|
|
96
|
-
|
|
97
|
-
space_id_value = getattr(space, "spaceId", None) or getattr(space, "id", "")
|
|
98
|
-
name_value = getattr(space, "name", name or "")
|
|
99
|
-
url_value = getattr(space, "url", None)
|
|
100
|
-
config_url_value = getattr(space, "configUrl", None)
|
|
101
|
-
url_line = (
|
|
102
|
-
f"\nURL: {url_value}" if isinstance(url_value, str) and url_value else ""
|
|
103
|
-
)
|
|
104
|
-
config_url_line = (
|
|
105
|
-
f"\nConfig URL: {config_url_value}"
|
|
106
|
-
if isinstance(config_url_value, str) and config_url_value
|
|
107
|
-
else ""
|
|
108
|
-
)
|
|
109
|
-
return (
|
|
110
|
-
f'{action} Dynamic Frontend space "{name_value}" ({space_id_value})\n'
|
|
111
|
-
f"Content: {resolved_content_id}"
|
|
112
|
-
f"{url_line}"
|
|
113
|
-
f"{config_url_line}"
|
|
114
|
-
)
|
|
115
|
-
except (ValueError, unique_sdk.APIError, OSError) as e:
|
|
116
|
-
return f"dynamic-frontend deploy: {e}"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def cmd_dynamic_frontend_delete(
|
|
120
|
-
state: ShellState,
|
|
121
|
-
space_id: str,
|
|
122
|
-
*,
|
|
123
|
-
output_json: bool = False,
|
|
124
|
-
) -> str:
|
|
125
|
-
try:
|
|
126
|
-
if not space_id:
|
|
127
|
-
return "dynamic-frontend delete: provide a space id."
|
|
128
|
-
result = unique_sdk.DynamicFrontend.delete(
|
|
129
|
-
space_id,
|
|
130
|
-
user_id=state.config.user_id,
|
|
131
|
-
company_id=state.config.company_id,
|
|
132
|
-
)
|
|
133
|
-
if output_json:
|
|
134
|
-
return json.dumps(dict(result), indent=2, default=str)
|
|
135
|
-
deleted_id = (
|
|
136
|
-
getattr(result, "spaceId", None) or getattr(result, "id", None) or space_id
|
|
137
|
-
)
|
|
138
|
-
return f"Deleted Dynamic Frontend space {deleted_id}"
|
|
139
|
-
except (ValueError, unique_sdk.APIError) as e:
|
|
140
|
-
return f"dynamic-frontend delete: {e}"
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def cmd_dynamic_frontend_list(state: ShellState, *, output_json: bool = False) -> str:
|
|
144
|
-
try:
|
|
145
|
-
spaces = unique_sdk.DynamicFrontend.list(
|
|
146
|
-
user_id=state.config.user_id,
|
|
147
|
-
company_id=state.config.company_id,
|
|
148
|
-
)
|
|
149
|
-
if output_json:
|
|
150
|
-
return json.dumps(spaces, indent=2, default=str)
|
|
151
|
-
if not spaces:
|
|
152
|
-
return "No manageable Dynamic Frontend spaces found."
|
|
153
|
-
return "\n".join(_format_space(space) for space in spaces)
|
|
154
|
-
except unique_sdk.APIError as e:
|
|
155
|
-
return f"dynamic-frontend list: {e}"
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: unique-cli-dynamic-frontend
|
|
3
|
-
description: >-
|
|
4
|
-
Create, update, list, and delete Unique Dynamic Frontend Spaces using the
|
|
5
|
-
`unique-cli dynamic-frontend` command. Use when deploying a generated
|
|
6
|
-
Dynamic Frontend ZIP, updating an existing Dynamic Frontend Space bundle,
|
|
7
|
-
listing manageable Dynamic Frontend Spaces, deleting a deployed Dynamic
|
|
8
|
-
Frontend Space, or when the user mentions Dynamic Frontend Space deployment
|
|
9
|
-
through the CLI.
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Unique CLI -- Dynamic Frontend Spaces
|
|
13
|
-
|
|
14
|
-
Use `unique-cli dynamic-frontend` to create, update, list, and delete Dynamic
|
|
15
|
-
Frontend Spaces from upload-ready ZIP bundles or existing Knowledge Base
|
|
16
|
-
content IDs.
|
|
17
|
-
|
|
18
|
-
The CLI is installed via `pip install unique-sdk` and uses the same
|
|
19
|
-
`UNIQUE_USER_ID`, `UNIQUE_COMPANY_ID`, `UNIQUE_API_KEY`, `UNIQUE_APP_ID`, and
|
|
20
|
-
`UNIQUE_API_BASE` environment variables as the rest of `unique-cli`.
|
|
21
|
-
|
|
22
|
-
## Create a New Space
|
|
23
|
-
|
|
24
|
-
To upload a ZIP and create a new Dynamic Frontend Space:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
unique-cli cd /Apps
|
|
28
|
-
unique-cli dynamic-frontend deploy \
|
|
29
|
-
--file ./revenue-dashboard.zip \
|
|
30
|
-
--name "Revenue Dashboard"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
To create from an already uploaded KB content ID:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
unique-cli dynamic-frontend deploy \
|
|
37
|
-
--content-id cont_abc123 \
|
|
38
|
-
--name "Revenue Dashboard"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
The command prints the created `spaceId`, `contentId`, and **two** URLs when the
|
|
42
|
-
API returns them — the user-facing view `URL` (jump into the Space in the chat
|
|
43
|
-
app) and the `Config URL` (configure and share the Space in the admin app):
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
Created Dynamic Frontend space "Revenue Dashboard" (space_abc123)
|
|
47
|
-
Content: cont_abc123
|
|
48
|
-
URL: https://next.qa.unique.app/chat/space/space_abc123
|
|
49
|
-
Config URL: https://next.qa.unique.app/admin/dynamic-frontend-space/space_abc123
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
If the installed SDK/CLI version does not print one of these URLs yet, construct
|
|
53
|
-
it from the known frontend base URLs and `spaceId`:
|
|
54
|
-
|
|
55
|
-
```text
|
|
56
|
-
# View URL (chat app)
|
|
57
|
-
<chat-frontend-url>/space/<spaceId>
|
|
58
|
-
# Config/share URL (admin app)
|
|
59
|
-
<admin-frontend-url>/dynamic-frontend-space/<spaceId>
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
On QA, those are:
|
|
63
|
-
|
|
64
|
-
```text
|
|
65
|
-
https://next.qa.unique.app/chat/space/<spaceId>
|
|
66
|
-
https://next.qa.unique.app/admin/dynamic-frontend-space/<spaceId>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Update an Existing Space
|
|
70
|
-
|
|
71
|
-
Use `--space-id` to update an existing Dynamic Frontend Space instead of
|
|
72
|
-
creating a new one.
|
|
73
|
-
|
|
74
|
-
Upload a new ZIP and point the existing Space at it:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
unique-cli cd /Apps
|
|
78
|
-
unique-cli dynamic-frontend deploy \
|
|
79
|
-
--space-id space_abc123 \
|
|
80
|
-
--file ./revenue-dashboard-1.0.1.zip
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Update from an already uploaded KB content ID:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
unique-cli dynamic-frontend deploy \
|
|
87
|
-
--space-id space_abc123 \
|
|
88
|
-
--content-id cont_newbundle123
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Rename while updating the bundle:
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
unique-cli dynamic-frontend deploy \
|
|
95
|
-
--space-id space_abc123 \
|
|
96
|
-
--file ./revenue-dashboard-1.0.1.zip \
|
|
97
|
-
--name "Revenue Dashboard"
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
The update command prints the same `spaceId`, `contentId`, view `URL`, and
|
|
101
|
-
`Config URL` fields as create.
|
|
102
|
-
|
|
103
|
-
## Delete a Space
|
|
104
|
-
|
|
105
|
-
Remove a deployed Dynamic Frontend Space by its space id. This deletes the
|
|
106
|
-
backing BYOC app and the owning space (and its access grants):
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
unique-cli dynamic-frontend delete space_abc123
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
The command prints a confirmation:
|
|
113
|
-
|
|
114
|
-
```text
|
|
115
|
-
Deleted Dynamic Frontend space space_abc123
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Deletion is permanent and requires manage access on the space (or a
|
|
119
|
-
company-wide space-admin role). Always confirm the correct `spaceId` with the
|
|
120
|
-
user before deleting — there is no undo.
|
|
121
|
-
|
|
122
|
-
## List Spaces
|
|
123
|
-
|
|
124
|
-
List Dynamic Frontend Spaces the current user can manage:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
unique-cli dynamic-frontend list
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Use JSON output for scripts:
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
unique-cli dynamic-frontend list --json
|
|
134
|
-
unique-cli dynamic-frontend deploy --space-id space_abc123 --file ./app.zip --json
|
|
135
|
-
unique-cli dynamic-frontend delete space_abc123 --json
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Rules
|
|
139
|
-
|
|
140
|
-
- For `--file`, first `unique-cli cd` into the KB folder where the ZIP should be
|
|
141
|
-
uploaded; uploading to root is rejected.
|
|
142
|
-
- Use `--space-id` for updates. Without `--space-id`, `deploy` creates a new
|
|
143
|
-
Dynamic Frontend Space and requires `--name`.
|
|
144
|
-
- `--file` and `--content-id` are mutually exclusive.
|
|
145
|
-
- `delete` is permanent and has no undo — confirm the `spaceId` with the user
|
|
146
|
-
first, and never guess which space to delete.
|
|
147
|
-
- After create or update, return the CLI output to the user, especially both the
|
|
148
|
-
view `URL` (jump to the Space) and the `Config URL` (configure/share the Space).
|
|
149
|
-
- Never report the BYOC iframe runtime URL
|
|
150
|
-
(`https://byoc.../serve/df-assistant-...`) as the Space URL; it is an
|
|
151
|
-
internal iframe launch URL, not the navigation link users need.
|
|
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.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/__init__.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_acronyms.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_agentic_table.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_analytics_order.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_benchmarking.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_briefing.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_chat_completion.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_content.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_elicitation.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_embedding.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_integrated.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_llm_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message_log.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_message_tool.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_scheduled_task.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/api_resources/_search_string.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/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.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/agentic_table.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/cite_file.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/elicitation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/navigation.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/cli/commands/scheduled_tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/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
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/unique_sdk/utils/analytics_order_run.py
RENAMED
|
File without changes
|
{unique_sdk-2026.32.0.dev7 → unique_sdk-2026.32.0.dev9}/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
|