unique-sdk 2026.26.0.dev5__tar.gz → 2026.26.0.dev7__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.26.0.dev5 → unique_sdk-2026.26.0.dev7}/PKG-INFO +1 -1
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/pyproject.toml +1 -1
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/cli.py +30 -0
- unique_sdk-2026.26.0.dev7/unique_sdk/cli/commands/read.py +93 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/shell.py +23 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-search/SKILL.md +42 -1
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/README.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/__init__.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_api_requestor.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_api_resource.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_api_version.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_error.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_http_client.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_list_object.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_object_classes.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_request_options.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_unique_object.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_unique_ql.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_unique_response.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_util.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_version.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/_webhook.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/__init__.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_acronyms.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_agentic_table.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_analytics_order.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_benchmarking.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_briefing.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_chat_completion.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_content.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_elicitation.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_embedding.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_event.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_folder.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_group.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_integrated.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_llm_models.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_mcp.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message_assessment.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message_execution.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message_log.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message_tool.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_module.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_scheduled_task.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_search.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_search_string.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_short_term_memory.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_space.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_user.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_web_search.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/__init__.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/__main__.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/__init__.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/_citation_manifest.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/cite_file.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/elicitation.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/files.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/folders.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/mcp.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/navigation.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/scheduled_tasks.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/search.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/subagent.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/web_search.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/web_search_config.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/config.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/formatting.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-elicitation/SKILL.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-file-management/SKILL.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-mcp/SKILL.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-scheduled-tasks/SKILL.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-subagent/SKILL.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/skills/unique-cli-web-search/SKILL.md +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/state.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/analytics_order_run.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/benchmarking_run.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/chat_history.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/chat_in_space.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/file_io.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/sources.py +0 -0
- {unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/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.26.0.
|
|
3
|
+
Version: 2026.26.0.dev7
|
|
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>
|
|
@@ -20,6 +20,10 @@ from unique_sdk.cli.commands.files import cmd_download, cmd_mv_file, cmd_rm, cmd
|
|
|
20
20
|
from unique_sdk.cli.commands.folders import cmd_mkdir, cmd_mvdir, cmd_rmdir
|
|
21
21
|
from unique_sdk.cli.commands.mcp import cmd_mcp
|
|
22
22
|
from unique_sdk.cli.commands.navigation import cmd_cd, cmd_ls, cmd_pwd
|
|
23
|
+
from unique_sdk.cli.commands.read import cmd_read
|
|
24
|
+
from unique_sdk.cli.commands.read import (
|
|
25
|
+
is_error_output as _is_read_error_output,
|
|
26
|
+
)
|
|
23
27
|
from unique_sdk.cli.commands.scheduled_tasks import (
|
|
24
28
|
cmd_schedule_create,
|
|
25
29
|
cmd_schedule_delete,
|
|
@@ -329,6 +333,32 @@ def cite(
|
|
|
329
333
|
click.echo(cmd_cite_file(LazyState.get(ctx), name_or_id, pages))
|
|
330
334
|
|
|
331
335
|
|
|
336
|
+
@main.command(name="read")
|
|
337
|
+
@click.argument("cont_id")
|
|
338
|
+
@click.pass_context
|
|
339
|
+
def read_cmd(ctx: click.Context, cont_id: str) -> None:
|
|
340
|
+
"""Read all indexed text chunks for a known content ID.
|
|
341
|
+
|
|
342
|
+
\b
|
|
343
|
+
CONT_ID must be a content ID (cont_...) obtained from a prior `ls` or
|
|
344
|
+
`search` result. Retrieves every indexed chunk directly from the database
|
|
345
|
+
— no vector search, no query string needed.
|
|
346
|
+
|
|
347
|
+
\b
|
|
348
|
+
Use `search` when you need to find documents by topic or keyword.
|
|
349
|
+
Use `read` when you already know the content ID and want the full text.
|
|
350
|
+
|
|
351
|
+
\b
|
|
352
|
+
Examples:
|
|
353
|
+
unique-cli read cont_abc123
|
|
354
|
+
"""
|
|
355
|
+
output = cmd_read(LazyState.get(ctx), cont_id)
|
|
356
|
+
if _is_read_error_output(output):
|
|
357
|
+
click.echo(output, err=True)
|
|
358
|
+
raise SystemExit(1)
|
|
359
|
+
click.echo(output)
|
|
360
|
+
|
|
361
|
+
|
|
332
362
|
@main.command()
|
|
333
363
|
@click.argument("name_or_id")
|
|
334
364
|
@click.pass_context
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Read command: retrieve all indexed text chunks for a known content ID.
|
|
2
|
+
|
|
3
|
+
Calls ``Content.search(where={"id": {"equals": cont_id}})`` — a direct
|
|
4
|
+
Postgres lookup that returns every indexed chunk for the document in one
|
|
5
|
+
request, no vector search involved.
|
|
6
|
+
|
|
7
|
+
Use this when you already know the ``cont_*`` ID (e.g. from a prior ``ls``
|
|
8
|
+
or ``unique-cli search`` result) and want to read the full document text.
|
|
9
|
+
For discovery or query-based retrieval use ``unique-cli search`` instead.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import unique_sdk
|
|
15
|
+
from unique_sdk.cli.state import ShellState
|
|
16
|
+
|
|
17
|
+
READ_ERROR_PREFIX = "read:"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def cmd_read(state: ShellState, cont_id: str) -> str:
|
|
21
|
+
"""Return all indexed text chunks for *cont_id* as plain text.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
state: Shell state carrying user/company credentials.
|
|
25
|
+
cont_id: A content ID (``cont_...``) to retrieve.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
A formatted string of chunks, or an error message prefixed with
|
|
29
|
+
``read:``.
|
|
30
|
+
"""
|
|
31
|
+
if not cont_id.startswith("cont_"):
|
|
32
|
+
return f"{READ_ERROR_PREFIX} expected a content ID starting with 'cont_', got: {cont_id!r}"
|
|
33
|
+
|
|
34
|
+
# Enforce the same .unique-search.json workspace boundary as search/ls/rm.
|
|
35
|
+
# Content.search has no scopeIds param, so we guard by owner scope before
|
|
36
|
+
# the point-lookup — matching rm/mv, not search's API-level scopeIds filter.
|
|
37
|
+
if not state.is_content_within_workspace(cont_id):
|
|
38
|
+
return f"{READ_ERROR_PREFIX} permission denied (outside workspace scope)"
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
results = unique_sdk.Content.search(
|
|
42
|
+
user_id=state.config.user_id,
|
|
43
|
+
company_id=state.config.company_id,
|
|
44
|
+
where={"id": {"equals": cont_id}},
|
|
45
|
+
)
|
|
46
|
+
except unique_sdk.APIError as e:
|
|
47
|
+
return f"{READ_ERROR_PREFIX} {e}"
|
|
48
|
+
|
|
49
|
+
if not results:
|
|
50
|
+
return f"{READ_ERROR_PREFIX} no content found for ID: {cont_id}"
|
|
51
|
+
|
|
52
|
+
content = results[0]
|
|
53
|
+
title = getattr(content, "title", None) or getattr(content, "key", None) or cont_id
|
|
54
|
+
chunks = getattr(content, "chunks", None) or []
|
|
55
|
+
|
|
56
|
+
if not chunks:
|
|
57
|
+
return (
|
|
58
|
+
f"Content: {title} ({cont_id})\n"
|
|
59
|
+
"No indexed chunks found — the document may still be ingesting or ingestion failed."
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
sorted_chunks = sorted(chunks, key=lambda c: c.get("order") or 0)
|
|
63
|
+
|
|
64
|
+
lines: list[str] = [
|
|
65
|
+
f"Content: {title} ({cont_id}) — {len(sorted_chunks)} chunk(s)\n"
|
|
66
|
+
]
|
|
67
|
+
for chunk in sorted_chunks:
|
|
68
|
+
text = (chunk.get("text") or "").strip()
|
|
69
|
+
if not text:
|
|
70
|
+
continue
|
|
71
|
+
start = chunk.get("startPage")
|
|
72
|
+
end = chunk.get("endPage")
|
|
73
|
+
if start is not None or end is not None:
|
|
74
|
+
page_start = start if start is not None else end
|
|
75
|
+
page_end = end if end is not None else start
|
|
76
|
+
if page_start is not None and page_end is not None:
|
|
77
|
+
page_ref = (
|
|
78
|
+
f"[p.{page_start}]"
|
|
79
|
+
if page_start == page_end
|
|
80
|
+
else f"[p.{page_start}-{page_end}]"
|
|
81
|
+
)
|
|
82
|
+
lines.append(f"{page_ref} {text}")
|
|
83
|
+
else:
|
|
84
|
+
lines.append(text)
|
|
85
|
+
else:
|
|
86
|
+
lines.append(text)
|
|
87
|
+
|
|
88
|
+
return "\n\n".join(lines)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def is_error_output(output: str) -> bool:
|
|
92
|
+
"""Return ``True`` when *output* is an error message from ``cmd_read``."""
|
|
93
|
+
return output.startswith(READ_ERROR_PREFIX)
|
|
@@ -59,6 +59,7 @@ OVERVIEW_HELP = textwrap.dedent("""\
|
|
|
59
59
|
--folder <path|id> Restrict to a folder
|
|
60
60
|
--metadata <key=value> Filter by metadata (repeatable)
|
|
61
61
|
--limit <N> Max results (default: 200)
|
|
62
|
+
read <cont_id> Read all indexed text chunks for a content ID
|
|
62
63
|
|
|
63
64
|
MCP:
|
|
64
65
|
mcp [options] <json> Call an MCP server tool
|
|
@@ -394,6 +395,28 @@ class UniqueShell(cmd.Cmd):
|
|
|
394
395
|
return
|
|
395
396
|
self._print(cmd_cite_file(self.state, positional[0], pages))
|
|
396
397
|
|
|
398
|
+
def do_read(self, arg: str) -> None:
|
|
399
|
+
"""Read all indexed text chunks for a known content ID.
|
|
400
|
+
|
|
401
|
+
Usage: read <cont_id>
|
|
402
|
+
|
|
403
|
+
Retrieves every indexed chunk for the document directly from the
|
|
404
|
+
database — no vector search, no query string needed.
|
|
405
|
+
|
|
406
|
+
Use `search` to find documents by topic; use `read` once you have
|
|
407
|
+
the content ID and want the full text.
|
|
408
|
+
|
|
409
|
+
Examples:
|
|
410
|
+
/Reports> read cont_abc123
|
|
411
|
+
"""
|
|
412
|
+
from unique_sdk.cli.commands.read import cmd_read
|
|
413
|
+
|
|
414
|
+
parts = shlex.split(arg)
|
|
415
|
+
if not parts:
|
|
416
|
+
self._print("Usage: read <cont_id>")
|
|
417
|
+
return
|
|
418
|
+
self._print(cmd_read(self.state, parts[0]))
|
|
419
|
+
|
|
397
420
|
def do_rm(self, arg: str) -> None:
|
|
398
421
|
"""Delete a file.
|
|
399
422
|
|
|
@@ -6,6 +6,8 @@ description: >-
|
|
|
6
6
|
as clickable reference chips and `<sup>N</sup>` footnotes on the Unique
|
|
7
7
|
platform. Use whenever the user asks to find, search, or query documents
|
|
8
8
|
or content on Unique, including filtering by folder or metadata.
|
|
9
|
+
Also covers `unique-cli read <cont_id>` for reading the full indexed text
|
|
10
|
+
of a document when its content ID is already known.
|
|
9
11
|
NOTE: This search uses combined vector + full-text indexing. Excel
|
|
10
12
|
(.xlsx/.xls), CSV (.csv), and image files are NOT full-text indexed,
|
|
11
13
|
so they will not appear in search results. To locate these file types,
|
|
@@ -13,7 +15,20 @@ description: >-
|
|
|
13
15
|
`unique-cli ls` to find them by name).
|
|
14
16
|
---
|
|
15
17
|
|
|
16
|
-
# Unique CLI -- Knowledge Base Search
|
|
18
|
+
# Unique CLI -- Knowledge Base Search & Document Read
|
|
19
|
+
|
|
20
|
+
## `search` vs `read` — which command to use
|
|
21
|
+
|
|
22
|
+
| Situation | Command |
|
|
23
|
+
|-----------|---------|
|
|
24
|
+
| You have a **query or topic** and want to find relevant chunks across documents | `unique-cli search "<query>"` |
|
|
25
|
+
| You already have a **`cont_*` ID** and want the **full indexed text** of that document | `unique-cli read <cont_id>` |
|
|
26
|
+
|
|
27
|
+
**What "full indexed text" means:** the platform has already ingested the document — OCR for scanned pages, extracted text from PDFs and Office files, and image descriptions from figures/charts. `read` returns that pre-processed text directly; you do **not** need to download the file or run OCR yourself. If `read` returns no chunks after ingestion should be complete, download the file with `unique-cli download` and inspect it directly — ingestion occasionally fails and the raw file must be checked.
|
|
28
|
+
|
|
29
|
+
Use `read` after a `ls` or `search` surfaces a content ID and you need to go deeper into that specific document — it retrieves every chunk directly from the database with no query needed. Use `search` for discovery.
|
|
30
|
+
|
|
31
|
+
---
|
|
17
32
|
|
|
18
33
|
Search the Unique knowledge base using combined vector + full-text search via the `unique-cli search` command. Every invocation wraps each result in a `<sourceN>...</sourceN>` block and records a per-turn citation manifest at `.unique/kb-search-refs.jsonl`, so any fact you cite as `[sourceN]` is rendered with a footnote and a clickable reference chip in the chat UI.
|
|
19
34
|
|
|
@@ -131,6 +146,32 @@ unique-cli search "Q4 earnings" \
|
|
|
131
146
|
--limit 100
|
|
132
147
|
```
|
|
133
148
|
|
|
149
|
+
## Reading a Document by ID (`read`)
|
|
150
|
+
|
|
151
|
+
When you already know a `cont_*` ID, use `read` to retrieve every indexed chunk in one call:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
unique-cli read cont_abc123
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Output:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
Content: annual-report.pdf (cont_abc123) — 42 chunk(s)
|
|
161
|
+
|
|
162
|
+
[p.1] The company was founded in 1998 with a focus on...
|
|
163
|
+
|
|
164
|
+
[p.2-3] Revenue grew 15% year over year, driven by...
|
|
165
|
+
|
|
166
|
+
[p.4] Key risks include supply chain disruptions...
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Each paragraph is one ingested chunk (OCR, extracted text, image descriptions) prefixed with its page range when available. No further file parsing or OCR is required on your side.
|
|
170
|
+
|
|
171
|
+
**When chunks are empty:** if the document was just uploaded and ingestion hasn't finished, `read` returns a message saying so — retry after a short wait. If chunks stay empty after a reasonable wait, download the file (`unique-cli download <cont_id>`) and inspect it yourself; some files are not ingested correctly and must be read directly.
|
|
172
|
+
|
|
173
|
+
**`read` does not produce `[sourceN]` citations.** It is for reading and understanding document content. If you need to cite specific facts in your answer, run `unique-cli search "<relevant query>"` against the same document's folder to generate proper `[sourceN]` references.
|
|
174
|
+
|
|
134
175
|
## Prerequisites
|
|
135
176
|
|
|
136
177
|
Requires these environment variables:
|
|
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.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/__init__.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_acronyms.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_agentic_table.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_analytics_order.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_benchmarking.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_briefing.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_chat_completion.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_content.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_elicitation.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_embedding.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_integrated.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_llm_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message_log.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_message_tool.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_scheduled_task.py
RENAMED
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/api_resources/_search_string.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/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.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/cite_file.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/elicitation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/navigation.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/scheduled_tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/cli/commands/web_search.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/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
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/unique_sdk/utils/analytics_order_run.py
RENAMED
|
File without changes
|
{unique_sdk-2026.26.0.dev5 → unique_sdk-2026.26.0.dev7}/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
|