primethink-cli 1.5.0__tar.gz → 1.6.0__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.
- {primethink_cli-1.5.0/primethink_cli.egg-info → primethink_cli-1.6.0}/PKG-INFO +3 -2
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/README.md +1 -1
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/SPECS.md +6 -6
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/USER_GUIDE.md +18 -5
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/docs/agent-tools.md +1 -1
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/docs/cli-reference.md +36 -10
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink.py +179 -15
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_agent_tools/tools.py +3 -3
- {primethink_cli-1.5.0 → primethink_cli-1.6.0/primethink_cli.egg-info}/PKG-INFO +3 -2
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_cli.egg-info/requires.txt +1 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_mcp.py +46 -14
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/pyproject.toml +4 -1
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/skills/primethink-cli/SKILL.md +8 -3
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_agent_tools.py +10 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_cli.py +130 -3
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_install_developer_skill.py +28 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_live_app.py +188 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_mcp_server.py +47 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/DEVELOPER.md +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/LICENSE +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/MANIFEST.in +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/docs/install.md +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/docs/primethink_help_llms.txt +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/install/homebrew/primethink-cli.rb +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/install/install.cmd +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/install/install.ps1 +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/install/install.sh +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_agent_tools/__init__.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_agent_tools/client.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_agent_tools/settings.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_cli.egg-info/SOURCES.txt +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_cli.egg-info/dependency_links.txt +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_cli.egg-info/entry_points.txt +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/primethink_cli.egg-info/top_level.txt +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/pytest.ini +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/scripts/build.sh +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/scripts/deploy.sh +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/scripts/publish.sh +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/setup.cfg +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/setup.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/skills/__init__.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/__init__.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/conftest.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_agent_commands.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_env_config.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_install_skill.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_packaging.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_project_workflows.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_search_commands.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_task_commands.py +0 -0
- {primethink_cli-1.5.0 → primethink_cli-1.6.0}/tests/test_whoami.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: primethink-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: PrimeThink CLI - A powerful tool for interacting with PrimeThink AI API
|
|
5
5
|
Author-email: PrimeThink <support@primethink.ai>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,6 +26,7 @@ Requires-Dist: click>=8.0.0
|
|
|
26
26
|
Requires-Dist: requests>=2.25.0
|
|
27
27
|
Provides-Extra: mcp
|
|
28
28
|
Requires-Dist: mcp<2,>=1.2.0; extra == "mcp"
|
|
29
|
+
Requires-Dist: pydantic>=2.0; extra == "mcp"
|
|
29
30
|
Provides-Extra: agent-tools
|
|
30
31
|
Requires-Dist: langchain-core>=0.3.0; extra == "agent-tools"
|
|
31
32
|
Requires-Dist: pydantic>=2.0; extra == "agent-tools"
|
|
@@ -104,7 +105,7 @@ pt chat send --agent AGENT_ID --message "your message"
|
|
|
104
105
|
| `pt chat sync-from` | Sync a chat's files to a local directory |
|
|
105
106
|
| `pt chat sync` | Two-way sync between a chat folder and a local directory |
|
|
106
107
|
| `pt chatdb init` | Initialize a chat's ChatDB (Live App data) store |
|
|
107
|
-
| `pt chatdb list` | List entities in a chat's ChatDB store |
|
|
108
|
+
| `pt chatdb list` | List entities in a chat's ChatDB store (or an attached DB Collection via `--collection`/`--collection-id`) |
|
|
108
109
|
| `pt chatdb get` | Get one ChatDB entity by ID |
|
|
109
110
|
| `pt chatdb add` | Add one or more rows to a ChatDB entity |
|
|
110
111
|
| `pt chatdb update` | Update ChatDB entities (single or bulk) |
|
|
@@ -65,7 +65,7 @@ pt chat send --agent AGENT_ID --message "your message"
|
|
|
65
65
|
| `pt chat sync-from` | Sync a chat's files to a local directory |
|
|
66
66
|
| `pt chat sync` | Two-way sync between a chat folder and a local directory |
|
|
67
67
|
| `pt chatdb init` | Initialize a chat's ChatDB (Live App data) store |
|
|
68
|
-
| `pt chatdb list` | List entities in a chat's ChatDB store |
|
|
68
|
+
| `pt chatdb list` | List entities in a chat's ChatDB store (or an attached DB Collection via `--collection`/`--collection-id`) |
|
|
69
69
|
| `pt chatdb get` | Get one ChatDB entity by ID |
|
|
70
70
|
| `pt chatdb add` | Add one or more rows to a ChatDB entity |
|
|
71
71
|
| `pt chatdb update` | Update ChatDB entities (single or bulk) |
|
|
@@ -66,13 +66,13 @@ To obtain an API key, go to `Settings > API Keys` in the PrimeThink app and gene
|
|
|
66
66
|
| `pt scheduled-job delete` | `DELETE /api/v1/scheduled_jobs/scheduled_job_in_chat/{job_id}` |
|
|
67
67
|
| document download (used by `download-file` and `sync-from`) | `GET /api/v1/documents/{document_id}/download` |
|
|
68
68
|
| `pt chatdb init` | `POST /api/v1/chats/{chat_id}/chatdb/init` |
|
|
69
|
-
| `pt chatdb list` | `POST /api/v1/chats/{chat_id}/chatdb/list` |
|
|
70
|
-
| `pt chatdb get` | `GET /api/v1/chats/{chat_id}/chatdb/entities/{entity_id}` |
|
|
71
|
-
| `pt chatdb add` | `POST /api/v1/chats/{chat_id}/chatdb/entities` |
|
|
72
|
-
| `pt chatdb update` | `PATCH /api/v1/chats/{chat_id}/chatdb/entities` |
|
|
73
|
-
| `pt chatdb delete` | `DELETE /api/v1/chats/{chat_id}/chatdb/entities` |
|
|
69
|
+
| `pt chatdb list` | `POST /api/v1/chats/{chat_id}/chatdb/list` (body may add `collection_name`/`collection_id`) |
|
|
70
|
+
| `pt chatdb get` | `GET /api/v1/chats/{chat_id}/chatdb/entities/{entity_id}` (query: `collection_name`, `collection_id`) |
|
|
71
|
+
| `pt chatdb add` | `POST /api/v1/chats/{chat_id}/chatdb/entities` (body may add `collection_name`/`collection_id`) |
|
|
72
|
+
| `pt chatdb update` | `PATCH /api/v1/chats/{chat_id}/chatdb/entities` (body may add `collection_name`/`collection_id`) |
|
|
73
|
+
| `pt chatdb delete` | `DELETE /api/v1/chats/{chat_id}/chatdb/entities` (body may add `collection_name`/`collection_id`) |
|
|
74
74
|
| `pt collection list` | `GET /api/v1/collections` |
|
|
75
|
-
| `pt collection create` | `POST /api/v1/collections` (params: `name`, `description`, `type`, `public`) |
|
|
75
|
+
| `pt collection create` | `POST /api/v1/collections` (params: `name`, `description`, `type` = `collection`/`skill`/`external_source`/`db`, `public`) |
|
|
76
76
|
| `pt collection get` | `GET /api/v1/collections/{collection_id}` |
|
|
77
77
|
| `pt collection update` | `PATCH /api/v1/collections/{collection_id}` |
|
|
78
78
|
| `pt collection reindex` | `POST /api/v1/collections/{collection_id}/reindex` |
|
|
@@ -77,7 +77,7 @@ pt version
|
|
|
77
77
|
|
|
78
78
|
You should see output like:
|
|
79
79
|
```
|
|
80
|
-
PrimeThink CLI v1.
|
|
80
|
+
PrimeThink CLI v1.6.0
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
## Getting Started
|
|
@@ -713,6 +713,19 @@ pt chatdb delete 123 --entity-id 7 # asks for confirmation; --yes to sk
|
|
|
713
713
|
|
|
714
714
|
`--data` takes a single JSON object; `--items` takes a JSON array for bulk operations. On update, `--merge` patches the existing row while `--replace` overwrites it, and `--if-unchanged-since TIMESTAMP` guards against overwriting a row that changed underneath you.
|
|
715
715
|
|
|
716
|
+
### DB Collections
|
|
717
|
+
|
|
718
|
+
A **DB Collection** is a collection of type `db` that holds the same kind of entities, but can be shared between chats. Once one is attached to a chat, `list`, `get`, `add`, `update` and `delete` can target it instead of the chat's own ChatDB, by name or by ID:
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
pt collection create --name project-db --type db # note the id, e.g. 42
|
|
722
|
+
# attach it to the chat in the web app, then:
|
|
723
|
+
pt chatdb add 123 --entity tasks --data '{"title": "a"}' --collection project-db
|
|
724
|
+
pt chatdb list 123 --entity tasks --collection-id 42
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
Prefer `--collection-id` when two attached DB Collections share a name, or in scripts that should survive a rename. If you pass both, they must identify the same collection. A collection attached read-only accepts `list`/`get` but rejects writes. This mirrors `pt.db('project-db')` / `pt.db(42)` in a Live App.
|
|
728
|
+
|
|
716
729
|
> Building the Live App itself (the front-end that uses this data) is covered by the **primethink-developer** skill; `pt chatdb` is the deterministic data plane underneath it.
|
|
717
730
|
|
|
718
731
|
## Semantic Search
|
|
@@ -1144,10 +1157,10 @@ pt eval delete 99 EVAL_ID
|
|
|
1144
1157
|
### 2. Configure how evaluations run
|
|
1145
1158
|
|
|
1146
1159
|
```bash
|
|
1147
|
-
pt eval settings 99 --active --run-time daily --evaluator-agent-id 7 --pass-threshold
|
|
1160
|
+
pt eval settings 99 --active --run-time daily --evaluator-agent-id 7 --pass-threshold 80
|
|
1148
1161
|
```
|
|
1149
1162
|
|
|
1150
|
-
`--run-time` is `manual`, `daily`, `weekly`, or `monthly`; `--pass-threshold` is the minimum score to count as a pass; `--message-delay-ms` throttles messages during a run.
|
|
1163
|
+
`--run-time` is `manual`, `daily`, `weekly`, or `monthly`; `--pass-threshold` is the minimum score to count as a pass, as a whole-number percentage from 1 to 100 (`80`, not `0.8`) — anything outside that range is rejected by the CLI before a request is made; `--message-delay-ms` throttles messages during a run.
|
|
1151
1164
|
|
|
1152
1165
|
### 3. Run it, then read the results
|
|
1153
1166
|
|
|
@@ -1270,8 +1283,8 @@ Defaults are `--framework react --tailwind --flowbite`. Flowbite depends on Tail
|
|
|
1270
1283
|
After generation:
|
|
1271
1284
|
|
|
1272
1285
|
1. Read the generated `README.md`; build and deployment steps differ by template.
|
|
1273
|
-
2.
|
|
1274
|
-
3.
|
|
1286
|
+
2. Name every Chat DB entity for your app. The templates ship none, and a generic name such as `item` collides with a sibling app in the same chat.
|
|
1287
|
+
3. Build the interface on the blank starter, keeping the PrimeThink wiring it ships: the runtime, the host-theme bridge, and the deployment configuration.
|
|
1275
1288
|
4. Build if required, then upload the files described by the template README.
|
|
1276
1289
|
|
|
1277
1290
|
The default Flowbite React starter is a Vite project and requires a local `npm install` and build. The other default starters are no-build, one-file HTML applications. The CLI itself intentionally runs neither package installation nor generated code.
|
|
@@ -60,7 +60,7 @@ resolve on 3.8. The `dev` extra installs the plugin's test dependencies only on
|
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
62
|
# In the API image (production): one pinned line in requirements.txt
|
|
63
|
-
primethink-cli[agent-tools]==1.
|
|
63
|
+
primethink-cli[agent-tools]==1.6.0
|
|
64
64
|
|
|
65
65
|
# From a checkout (dev): the dev extra already includes langchain-core
|
|
66
66
|
pip install -e ".[dev]"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PrimeThink CLI — Command Reference
|
|
2
2
|
|
|
3
|
-
Complete reference for every command in the PrimeThink CLI (`pt`), version 1.
|
|
3
|
+
Complete reference for every command in the PrimeThink CLI (`pt`), version 1.6.0.
|
|
4
4
|
|
|
5
5
|
Commands are organized into noun groups: `profile`, `live-app`, `chat`, `collection`, `agent`, `task`, `search`, and `image`.
|
|
6
6
|
|
|
@@ -221,7 +221,7 @@ Display the CLI version.
|
|
|
221
221
|
|
|
222
222
|
```bash
|
|
223
223
|
pt version
|
|
224
|
-
# PrimeThink CLI v1.
|
|
224
|
+
# PrimeThink CLI v1.6.0
|
|
225
225
|
```
|
|
226
226
|
|
|
227
227
|
### `pt whoami`
|
|
@@ -1021,6 +1021,13 @@ Entities are grouped by name (think tables); each row has an `id`. Initialize th
|
|
|
1021
1021
|
|
|
1022
1022
|
> Unlike `pt chat`/`pt collection`, this group *does* use `-p` for `--profile` (there is no `--path` here).
|
|
1023
1023
|
|
|
1024
|
+
**Targeting a DB Collection.** By default every command below except `init` reads and writes the chat's own ChatDB. Pass `--collection NAME` and/or `--collection-id N` to target a **DB Collection** (a collection of type `db`, see `pt collection create --type db`) attached to the chat instead. The ID is unambiguous when several attached DB Collections share a name, and it survives a rename; when you pass both, they must identify the same collection or the API answers 404. Writes (`add`, `update`, `delete`) to a collection attached read-only are rejected with 403. The target is sent as `collection_name`/`collection_id` in the request body, or as query parameters for `get`. There is no `pt` command to attach a collection to a chat yet — attach it in the web app.
|
|
1025
|
+
|
|
1026
|
+
```bash
|
|
1027
|
+
pt chatdb list 123 --entity tasks --collection project-db
|
|
1028
|
+
pt chatdb add 123 --entity tasks --data '{"title": "a"}' --collection-id 42
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1024
1031
|
### `pt chatdb init`
|
|
1025
1032
|
|
|
1026
1033
|
Initialize the ChatDB store for a chat.
|
|
@@ -1047,6 +1054,8 @@ pt chatdb list CHAT_ID [OPTIONS]
|
|
|
1047
1054
|
| `--offset` | Row offset |
|
|
1048
1055
|
| `--page` | Page number |
|
|
1049
1056
|
| `--page-size` | Results per page |
|
|
1057
|
+
| `--collection` | Target an attached DB Collection by name instead of the chat's own ChatDB |
|
|
1058
|
+
| `--collection-id` | Target an attached DB Collection by ID (≥ 1; unambiguous when names repeat) |
|
|
1050
1059
|
|
|
1051
1060
|
Calls `POST /api/v1/chats/{chat_id}/chatdb/list`.
|
|
1052
1061
|
|
|
@@ -1060,9 +1069,14 @@ pt chatdb list 123 --entity todos --filters '{"done": false}' --limit 20
|
|
|
1060
1069
|
Get a single ChatDB entity by its ID.
|
|
1061
1070
|
|
|
1062
1071
|
```bash
|
|
1063
|
-
pt chatdb get CHAT_ID ENTITY_ID [--profile NAME] [--api-url URL]
|
|
1072
|
+
pt chatdb get CHAT_ID ENTITY_ID [--collection NAME] [--collection-id N] [--profile NAME] [--api-url URL]
|
|
1064
1073
|
```
|
|
1065
1074
|
|
|
1075
|
+
| Option | Description |
|
|
1076
|
+
|---|---|
|
|
1077
|
+
| `--collection` | Target an attached DB Collection by name instead of the chat's own ChatDB |
|
|
1078
|
+
| `--collection-id` | Target an attached DB Collection by ID (≥ 1; unambiguous when names repeat) |
|
|
1079
|
+
|
|
1066
1080
|
Calls `GET /api/v1/chats/{chat_id}/chatdb/entities/{entity_id}`.
|
|
1067
1081
|
|
|
1068
1082
|
### `pt chatdb add`
|
|
@@ -1078,6 +1092,8 @@ pt chatdb add CHAT_ID --entity NAME [--data JSON] [--items JSON]
|
|
|
1078
1092
|
| `--entity` | Entity name to add to (required) |
|
|
1079
1093
|
| `--data` | A single row as a JSON object |
|
|
1080
1094
|
| `--items` | Multiple rows as a JSON array (bulk insert) |
|
|
1095
|
+
| `--collection` | Target an attached DB Collection by name instead of the chat's own ChatDB |
|
|
1096
|
+
| `--collection-id` | Target an attached DB Collection by ID (≥ 1; unambiguous when names repeat) |
|
|
1081
1097
|
|
|
1082
1098
|
Calls `POST /api/v1/chats/{chat_id}/chatdb/entities`.
|
|
1083
1099
|
|
|
@@ -1101,8 +1117,10 @@ pt chatdb update CHAT_ID [OPTIONS]
|
|
|
1101
1117
|
| `--merge` / `--replace` | Merge `--data` into the existing row or replace it (server default applies if unset) |
|
|
1102
1118
|
| `--items` | Bulk updates as a JSON array |
|
|
1103
1119
|
| `--if-unchanged-since` | Only update if the row is unchanged since this timestamp (optimistic concurrency) |
|
|
1120
|
+
| `--collection` | Target an attached DB Collection by name instead of the chat's own ChatDB |
|
|
1121
|
+
| `--collection-id` | Target an attached DB Collection by ID (≥ 1; unambiguous when names repeat) |
|
|
1104
1122
|
|
|
1105
|
-
Requires at least one of `--entity-id`/`--data` or `--items
|
|
1123
|
+
Requires at least one of `--entity-id`/`--data` or `--items`; a collection target on its own does not count. Calls `PATCH /api/v1/chats/{chat_id}/chatdb/entities`.
|
|
1106
1124
|
|
|
1107
1125
|
```bash
|
|
1108
1126
|
pt chatdb update 123 --entity-id 7 --data '{"done": true}' --merge
|
|
@@ -1113,9 +1131,17 @@ pt chatdb update 123 --entity-id 7 --data '{"done": true}' --merge
|
|
|
1113
1131
|
Delete a single row (`--entity-id`) or several (`--ids`). **Destructive and irreversible** — prompts for confirmation unless `--yes` is passed.
|
|
1114
1132
|
|
|
1115
1133
|
```bash
|
|
1116
|
-
pt chatdb delete CHAT_ID [--entity-id N | --ids 1,2,3] [--yes]
|
|
1134
|
+
pt chatdb delete CHAT_ID [--entity-id N | --ids 1,2,3] [--collection NAME] [--collection-id N] [--yes]
|
|
1117
1135
|
```
|
|
1118
1136
|
|
|
1137
|
+
| Option | Description |
|
|
1138
|
+
|---|---|
|
|
1139
|
+
| `--entity-id` | ID of a single row to delete |
|
|
1140
|
+
| `--ids` | Comma-separated row IDs to delete |
|
|
1141
|
+
| `--collection` | Target an attached DB Collection by name instead of the chat's own ChatDB |
|
|
1142
|
+
| `--collection-id` | Target an attached DB Collection by ID (≥ 1; unambiguous when names repeat) |
|
|
1143
|
+
| `--yes` | Skip the confirmation prompt |
|
|
1144
|
+
|
|
1119
1145
|
Requires `--entity-id` or `--ids`. Calls `DELETE /api/v1/chats/{chat_id}/chatdb/entities`.
|
|
1120
1146
|
|
|
1121
1147
|
```bash
|
|
@@ -1162,7 +1188,7 @@ pt collection create --name NAME [OPTIONS]
|
|
|
1162
1188
|
|---|---|
|
|
1163
1189
|
| `--name` | Collection name (required) |
|
|
1164
1190
|
| `--description` | Collection description |
|
|
1165
|
-
| `--type` | Collection type: `collection`, `skill`, or `
|
|
1191
|
+
| `--type` | Collection type: `collection`, `skill`, `external_source`, or `db` (a DB Collection: structured entities that `pt chatdb --collection` and Live Apps' `pt.db()` read and write) (server default: `collection`) |
|
|
1166
1192
|
| `--public` / `--private` | Make the collection public or private (server default: private) |
|
|
1167
1193
|
|
|
1168
1194
|
Calls `POST /api/v1/collections` and prints the created collection as JSON.
|
|
@@ -1198,7 +1224,7 @@ pt collection update COLLECTION_ID [OPTIONS]
|
|
|
1198
1224
|
|---|---|
|
|
1199
1225
|
| `--name` | Collection name |
|
|
1200
1226
|
| `--description` | Collection description |
|
|
1201
|
-
| `--type` | Collection type: `collection`, `skill`, or `
|
|
1227
|
+
| `--type` | Collection type: `collection`, `skill`, `external_source`, or `db` |
|
|
1202
1228
|
| `--public` / `--private` | Make the collection public or private |
|
|
1203
1229
|
| `--indexed` / `--not-indexed` | Enable or disable indexing |
|
|
1204
1230
|
| `--ocr-instructions` | OCR instructions for document processing |
|
|
@@ -2472,7 +2498,7 @@ pt eval update TASK_ID EVAL_ID [--user-query …] [--ideal-response …] [--type
|
|
|
2472
2498
|
pt eval delete TASK_ID EVAL_ID [--yes] # DESTRUCTIVE
|
|
2473
2499
|
|
|
2474
2500
|
# Configure how evaluations run
|
|
2475
|
-
pt eval settings TASK_ID [--active | --inactive] [--run-time manual|daily|weekly|monthly] [--evaluator-agent-id N] [--pass-threshold
|
|
2501
|
+
pt eval settings TASK_ID [--active | --inactive] [--run-time manual|daily|weekly|monthly] [--evaluator-agent-id N] [--pass-threshold 1-100] [--message-delay-ms N]
|
|
2476
2502
|
|
|
2477
2503
|
# Run an evaluation and inspect its runs/results
|
|
2478
2504
|
pt eval run TASK_ID [--version N] [--model-override M]
|
|
@@ -2503,13 +2529,13 @@ pt eval delete-simulation TASK_ID SIM_ID [--yes] # DESTRUCTIVE
|
|
|
2503
2529
|
| `simulations` | `GET /api/v1/tasks/{id}/simulations` | `list_task_simulations` |
|
|
2504
2530
|
| `delete-simulation` | `DELETE /api/v1/tasks/{id}/simulations/{sim_id}` | `delete_task_simulation` |
|
|
2505
2531
|
|
|
2506
|
-
`--type` for a test case is `exact` (exact-match), `similar` (fuzzy/semantic match), or `agent` (an evaluator agent judges the response). `--examples` takes a JSON object of good/bad example fields. `--chat-group` (default `1`) groups related test cases.
|
|
2532
|
+
`--pass-threshold` is the minimum score that counts as a pass, as a whole-number percentage from 1 to 100 (`80`, not `0.8`); the CLI rejects anything outside that range with a usage error before any request is made. `--type` for a test case is `exact` (exact-match), `similar` (fuzzy/semantic match), or `agent` (an evaluator agent judges the response). `--examples` takes a JSON object of good/bad example fields. `--chat-group` (default `1`) groups related test cases.
|
|
2507
2533
|
|
|
2508
2534
|
```bash
|
|
2509
2535
|
# Build a two-case plan, make it evaluator-judged and daily, then run it
|
|
2510
2536
|
pt eval add 99 --user-query "What's your return window?" --ideal-response "30 days" --type similar
|
|
2511
2537
|
pt eval add 99 --user-query "Refund a gift?" --ideal-response "Yes, store credit" --type agent --evaluator-agent-id 7
|
|
2512
|
-
pt eval settings 99 --active --run-time daily --evaluator-agent-id 7 --pass-threshold
|
|
2538
|
+
pt eval settings 99 --active --run-time daily --evaluator-agent-id 7 --pass-threshold 80
|
|
2513
2539
|
pt eval run 99
|
|
2514
2540
|
pt eval results 99 | jq '.[] | {case, passed, score}'
|
|
2515
2541
|
```
|
|
@@ -7,6 +7,8 @@ import json
|
|
|
7
7
|
import shutil
|
|
8
8
|
import tempfile
|
|
9
9
|
import zipfile
|
|
10
|
+
import re
|
|
11
|
+
import html as html_module
|
|
10
12
|
import contextlib
|
|
11
13
|
import mimetypes
|
|
12
14
|
import webbrowser
|
|
@@ -921,7 +923,7 @@ def cli():
|
|
|
921
923
|
@cli.command()
|
|
922
924
|
def version():
|
|
923
925
|
"""Display the version of PrimeThink CLI."""
|
|
924
|
-
click.echo("PrimeThink CLI v1.
|
|
926
|
+
click.echo("PrimeThink CLI v1.6.0")
|
|
925
927
|
|
|
926
928
|
|
|
927
929
|
@cli.command()
|
|
@@ -1208,6 +1210,107 @@ def _select_live_app_template(templates, framework, tailwind, flowbite):
|
|
|
1208
1210
|
return template_id, _safe_catalog_path(item.get('path'), 'template path')
|
|
1209
1211
|
|
|
1210
1212
|
|
|
1213
|
+
# ---------------------------------------------------------------------------
|
|
1214
|
+
# Scaffold identity
|
|
1215
|
+
#
|
|
1216
|
+
# `pt live-app new` used to extract the archive verbatim, so the TEMPLATE's own
|
|
1217
|
+
# <title> and meta description shipped with the app. In a reported build they
|
|
1218
|
+
# reached production: nothing downstream rewrites them, `verify-dist` cannot tell a
|
|
1219
|
+
# placeholder from a deliberate title, and the browser tab is the last place anyone
|
|
1220
|
+
# looks. This is the one point in the whole flow where the app has a name, so it is
|
|
1221
|
+
# the only place the rewrite can happen.
|
|
1222
|
+
# ---------------------------------------------------------------------------
|
|
1223
|
+
|
|
1224
|
+
_TITLE_TAG = re.compile(r'(<title\b[^>]*>)(.*?)(</title>)', re.IGNORECASE | re.DOTALL)
|
|
1225
|
+
# The quotes are back-referenced, not just "one of ' or \"". Matching them
|
|
1226
|
+
# independently breaks on an apostrophe inside a double-quoted attribute:
|
|
1227
|
+
# content="Bob's canvas" would end the match at the apostrophe and leave
|
|
1228
|
+
# `s canvas"` dangling in the markup after the replacement.
|
|
1229
|
+
_DESCRIPTION_META = re.compile(
|
|
1230
|
+
r'(<meta\b[^>]*\bname=(["\'])description\2[^>]*?\bcontent=(["\']))(.*?)\3',
|
|
1231
|
+
re.IGNORECASE | re.DOTALL,
|
|
1232
|
+
)
|
|
1233
|
+
|
|
1234
|
+
# npm rejects a package name longer than this.
|
|
1235
|
+
_MAX_PACKAGE_NAME = 214
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
# Directory names that describe a slot rather than an app. A repo convention that
|
|
1239
|
+
# scaffolds into `<app>/sandbox` would otherwise title every app "Sandbox" — which it
|
|
1240
|
+
# did, and it reached a published task before anyone noticed.
|
|
1241
|
+
_CONTAINER_DIR_NAMES = {'sandbox', 'app', 'apps', 'src', 'dist', 'web', 'client', 'frontend'}
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
def _app_identity(destination):
|
|
1245
|
+
"""A display title and an npm-safe package name, from the target directory name.
|
|
1246
|
+
|
|
1247
|
+
``my-cool-app`` -> ``("My Cool App", "my-cool-app")``. When the target is a
|
|
1248
|
+
container directory, the parent names the app instead:
|
|
1249
|
+
``word-painter/sandbox`` -> ``("Word Painter", "word-painter")``.
|
|
1250
|
+
"""
|
|
1251
|
+
resolved = Path(destination).resolve()
|
|
1252
|
+
raw = resolved.name
|
|
1253
|
+
if raw.lower() in _CONTAINER_DIR_NAMES and resolved.parent.name:
|
|
1254
|
+
raw = resolved.parent.name
|
|
1255
|
+
words = [w for w in re.split(r'[-_\s]+', raw) if w]
|
|
1256
|
+
title = ' '.join(w[:1].upper() + w[1:] for w in words) if words else raw
|
|
1257
|
+
package = re.sub(r'[^a-z0-9._-]+', '-', raw.lower()).strip('-._')
|
|
1258
|
+
package = package[:_MAX_PACKAGE_NAME].rstrip('-._')
|
|
1259
|
+
return title, (package or 'primethink-live-app')
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
def _personalise_live_app_template(staging, title, package_name):
|
|
1263
|
+
"""Stamp the new app's identity over the template's, in the staging directory.
|
|
1264
|
+
|
|
1265
|
+
Best-effort: a template that ships no index.html or no package.json is left
|
|
1266
|
+
alone, and an unreadable or malformed file is skipped rather than failing the
|
|
1267
|
+
scaffold. Returns the list of files actually changed, for the command output.
|
|
1268
|
+
"""
|
|
1269
|
+
changed = []
|
|
1270
|
+
|
|
1271
|
+
index_html = Path(staging) / 'index.html'
|
|
1272
|
+
if index_html.is_file():
|
|
1273
|
+
try:
|
|
1274
|
+
source = index_html.read_text(encoding='utf-8')
|
|
1275
|
+
except (OSError, UnicodeDecodeError):
|
|
1276
|
+
source = None
|
|
1277
|
+
if source is not None:
|
|
1278
|
+
escaped = html_module.escape(title, quote=True)
|
|
1279
|
+
description = html_module.escape(
|
|
1280
|
+
f'{title} \u2014 a PrimeThink Live App', quote=True
|
|
1281
|
+
)
|
|
1282
|
+
updated, titles = _TITLE_TAG.subn(
|
|
1283
|
+
lambda m: m.group(1) + escaped + m.group(3), source, count=1
|
|
1284
|
+
)
|
|
1285
|
+
updated, metas = _DESCRIPTION_META.subn(
|
|
1286
|
+
lambda m: m.group(1) + description + m.group(3), updated, count=1
|
|
1287
|
+
) # group(3) is the opening content quote, reused as the closing one
|
|
1288
|
+
if (titles or metas) and updated != source:
|
|
1289
|
+
try:
|
|
1290
|
+
index_html.write_text(updated, encoding='utf-8')
|
|
1291
|
+
changed.append('index.html')
|
|
1292
|
+
except OSError:
|
|
1293
|
+
pass
|
|
1294
|
+
|
|
1295
|
+
package_json = Path(staging) / 'package.json'
|
|
1296
|
+
if package_json.is_file():
|
|
1297
|
+
try:
|
|
1298
|
+
manifest = json.loads(package_json.read_text(encoding='utf-8'))
|
|
1299
|
+
except (OSError, UnicodeDecodeError, ValueError):
|
|
1300
|
+
manifest = None
|
|
1301
|
+
if isinstance(manifest, dict) and manifest.get('name') != package_name:
|
|
1302
|
+
manifest['name'] = package_name
|
|
1303
|
+
try:
|
|
1304
|
+
package_json.write_text(
|
|
1305
|
+
json.dumps(manifest, indent=2) + '\n', encoding='utf-8'
|
|
1306
|
+
)
|
|
1307
|
+
changed.append('package.json')
|
|
1308
|
+
except OSError:
|
|
1309
|
+
pass
|
|
1310
|
+
|
|
1311
|
+
return changed
|
|
1312
|
+
|
|
1313
|
+
|
|
1211
1314
|
def _extract_live_app_template(archive_bytes, destination, framework, tailwind, flowbite):
|
|
1212
1315
|
"""Safely and atomically extract one selected template into destination."""
|
|
1213
1316
|
destination = Path(destination)
|
|
@@ -1275,6 +1378,8 @@ def _extract_live_app_template(archive_bytes, destination, framework, tailwind,
|
|
|
1275
1378
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
1276
1379
|
with archive.open(info) as source, open(target, 'wb') as output:
|
|
1277
1380
|
shutil.copyfileobj(source, output)
|
|
1381
|
+
title, package_name = _app_identity(destination)
|
|
1382
|
+
personalised = _personalise_live_app_template(staging, title, package_name)
|
|
1278
1383
|
if destination.exists():
|
|
1279
1384
|
raise click.ClickException(f"destination already exists: {destination}")
|
|
1280
1385
|
staging.replace(destination)
|
|
@@ -1282,7 +1387,7 @@ def _extract_live_app_template(archive_bytes, destination, framework, tailwind,
|
|
|
1282
1387
|
raise
|
|
1283
1388
|
except (OSError, RuntimeError, zipfile.BadZipFile) as e:
|
|
1284
1389
|
raise click.ClickException(f"could not create live app at {destination}: {e}")
|
|
1285
|
-
return template_id
|
|
1390
|
+
return template_id, title, personalised
|
|
1286
1391
|
|
|
1287
1392
|
|
|
1288
1393
|
@cli.group(name='live-app')
|
|
@@ -1310,11 +1415,13 @@ def live_app_new(directory, framework, tailwind, flowbite, repo_url, ref):
|
|
|
1310
1415
|
if directory.exists():
|
|
1311
1416
|
raise click.ClickException(f"destination already exists: {directory}")
|
|
1312
1417
|
archive = _download_template_archive(repo_url, ref)
|
|
1313
|
-
template_id = _extract_live_app_template(
|
|
1418
|
+
template_id, title, personalised = _extract_live_app_template(
|
|
1314
1419
|
archive, directory, framework, tailwind, flowbite
|
|
1315
1420
|
)
|
|
1316
1421
|
click.echo(f"Created PrimeThink Live App at {directory}")
|
|
1317
1422
|
click.echo(f"Template: {template_id} ({framework}, tailwind={'yes' if tailwind else 'no'}, flowbite={'yes' if flowbite else 'no'})")
|
|
1423
|
+
if personalised:
|
|
1424
|
+
click.echo(f"Named \"{title}\" in {', '.join(personalised)} — edit if you want something else.")
|
|
1318
1425
|
click.echo("Next: read the generated README.md and learn how to build Live Apps.")
|
|
1319
1426
|
|
|
1320
1427
|
|
|
@@ -1936,8 +2043,31 @@ def install_developer_skill(target, custom_dir, force, repo_url, ref):
|
|
|
1936
2043
|
file_count = _extract_github_subdirectory(
|
|
1937
2044
|
archive, DEVELOPER_SKILL_PATH, destination, force=force
|
|
1938
2045
|
)
|
|
2046
|
+
# Record what was installed. Three build reports in a row could not cite which
|
|
2047
|
+
# revision of the skill they were reporting against, because the installed tree
|
|
2048
|
+
# carries no marker at all — which makes a finding unfixable by anyone who was
|
|
2049
|
+
# not in that session.
|
|
2050
|
+
from datetime import datetime, timezone
|
|
2051
|
+
installed_at = datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
|
2052
|
+
marker = destination / 'VERSION'
|
|
2053
|
+
try:
|
|
2054
|
+
marker.write_text(
|
|
2055
|
+
f"ref: {ref}\n"
|
|
2056
|
+
f"repo: {repo_url}\n"
|
|
2057
|
+
f"path: {DEVELOPER_SKILL_PATH}\n"
|
|
2058
|
+
f"files: {file_count}\n"
|
|
2059
|
+
f"installed_at: {installed_at}\n",
|
|
2060
|
+
encoding='utf-8',
|
|
2061
|
+
)
|
|
2062
|
+
except OSError as exc:
|
|
2063
|
+
# A missing marker must never fail an otherwise good install.
|
|
2064
|
+
marker_line = f"Version marker not written ({exc}); installed ref {ref}"
|
|
2065
|
+
else:
|
|
2066
|
+
marker_line = f"Version marker: {marker} (ref {ref})"
|
|
2067
|
+
|
|
1939
2068
|
click.echo(f"Installed skill '{DEVELOPER_SKILL_NAME}' to {destination}")
|
|
1940
2069
|
click.echo(f"Included {file_count} files from {DEVELOPER_SKILL_PATH}, including subdirectories.")
|
|
2070
|
+
click.echo(marker_line)
|
|
1941
2071
|
click.echo("Compatible agents will pick it up on their next session in that scope.")
|
|
1942
2072
|
|
|
1943
2073
|
# ============================================================================
|
|
@@ -2644,10 +2774,28 @@ def sync(chat_id, local_dir, path, prefer, dry_run, profile, api_url):
|
|
|
2644
2774
|
|
|
2645
2775
|
@cli.group(name='chatdb')
|
|
2646
2776
|
def chatdb():
|
|
2647
|
-
"""ChatDB commands: read and write a chat's Live App data store.
|
|
2777
|
+
"""ChatDB commands: read and write a chat's Live App data store.
|
|
2778
|
+
|
|
2779
|
+
By default each command targets the chat's own ChatDB. Pass --collection NAME
|
|
2780
|
+
and/or --collection-id N to target a DB Collection attached to the chat instead.
|
|
2781
|
+
"""
|
|
2648
2782
|
pass
|
|
2649
2783
|
|
|
2650
2784
|
|
|
2785
|
+
def _chatdb_target_options(f):
|
|
2786
|
+
"""Apply the --collection/--collection-id DB Collection target options to a chatdb command."""
|
|
2787
|
+
f = click.option('--collection-id', 'collection_id', default=None, type=click.IntRange(min=1),
|
|
2788
|
+
help="Target an attached DB Collection by ID (unambiguous when names repeat)")(f)
|
|
2789
|
+
f = click.option('--collection', 'collection_name', default=None,
|
|
2790
|
+
help="Target an attached DB Collection by name instead of the chat's own ChatDB")(f)
|
|
2791
|
+
return f
|
|
2792
|
+
|
|
2793
|
+
|
|
2794
|
+
def _chatdb_target(collection_name, collection_id):
|
|
2795
|
+
"""The DB Collection target fields; empty (the chat's own ChatDB) when neither is set."""
|
|
2796
|
+
return _clean_payload({'collection_name': collection_name, 'collection_id': collection_id}, {})
|
|
2797
|
+
|
|
2798
|
+
|
|
2651
2799
|
@chatdb.command(name='init')
|
|
2652
2800
|
@click.argument('chat_id')
|
|
2653
2801
|
@_connection_options
|
|
@@ -2669,8 +2817,10 @@ def chatdb_init(chat_id, profile, api_url):
|
|
|
2669
2817
|
@click.option('--offset', default=None, type=int, help='Row offset')
|
|
2670
2818
|
@click.option('--page', default=None, type=int, help='Page number')
|
|
2671
2819
|
@click.option('--page-size', default=None, type=int, help='Results per page')
|
|
2820
|
+
@_chatdb_target_options
|
|
2672
2821
|
@_connection_options
|
|
2673
|
-
def chatdb_list(chat_id, entity_names, filters, limit, offset, page, page_size,
|
|
2822
|
+
def chatdb_list(chat_id, entity_names, filters, limit, offset, page, page_size,
|
|
2823
|
+
collection_name, collection_id, profile, api_url):
|
|
2674
2824
|
"""List entities in a chat's ChatDB store."""
|
|
2675
2825
|
api_url, token = _resolve_connection(profile, api_url)
|
|
2676
2826
|
filters = _parse_json_option(filters, '--filters')
|
|
@@ -2678,6 +2828,7 @@ def chatdb_list(chat_id, entity_names, filters, limit, offset, page, page_size,
|
|
|
2678
2828
|
'entity_names': list(entity_names) or None, 'filters': filters,
|
|
2679
2829
|
'limit': limit, 'offset': offset, 'page': page, 'page_size': page_size,
|
|
2680
2830
|
}, {})
|
|
2831
|
+
payload.update(_chatdb_target(collection_name, collection_id))
|
|
2681
2832
|
response = _api_request('POST', f"{api_url}/api/v1/chats/{chat_id}/chatdb/list", token,
|
|
2682
2833
|
ok_status=(200, 201), json=payload)
|
|
2683
2834
|
click.echo(json.dumps(response.json(), indent=2))
|
|
@@ -2686,11 +2837,13 @@ def chatdb_list(chat_id, entity_names, filters, limit, offset, page, page_size,
|
|
|
2686
2837
|
@chatdb.command(name='get')
|
|
2687
2838
|
@click.argument('chat_id')
|
|
2688
2839
|
@click.argument('entity_id')
|
|
2840
|
+
@_chatdb_target_options
|
|
2689
2841
|
@_connection_options
|
|
2690
|
-
def chatdb_get(chat_id, entity_id, profile, api_url):
|
|
2842
|
+
def chatdb_get(chat_id, entity_id, collection_name, collection_id, profile, api_url):
|
|
2691
2843
|
"""Get one ChatDB entity by its ID."""
|
|
2692
2844
|
api_url, token = _resolve_connection(profile, api_url)
|
|
2693
|
-
response = _api_request('GET', f"{api_url}/api/v1/chats/{chat_id}/chatdb/entities/{entity_id}", token
|
|
2845
|
+
response = _api_request('GET', f"{api_url}/api/v1/chats/{chat_id}/chatdb/entities/{entity_id}", token,
|
|
2846
|
+
params=_chatdb_target(collection_name, collection_id) or None)
|
|
2694
2847
|
click.echo(json.dumps(response.json(), indent=2))
|
|
2695
2848
|
|
|
2696
2849
|
|
|
@@ -2699,8 +2852,9 @@ def chatdb_get(chat_id, entity_id, profile, api_url):
|
|
|
2699
2852
|
@click.option('--entity', 'entity_name', required=True, help='Entity name (collection/table)')
|
|
2700
2853
|
@click.option('--data', default=None, help='A single entity as a JSON object')
|
|
2701
2854
|
@click.option('--items', default=None, help='Multiple entities as a JSON array (bulk insert)')
|
|
2855
|
+
@_chatdb_target_options
|
|
2702
2856
|
@_connection_options
|
|
2703
|
-
def chatdb_add(chat_id, entity_name, data, items, profile, api_url):
|
|
2857
|
+
def chatdb_add(chat_id, entity_name, data, items, collection_name, collection_id, profile, api_url):
|
|
2704
2858
|
"""Add one entity (--data) or many (--items) to a ChatDB entity."""
|
|
2705
2859
|
api_url, token = _resolve_connection(profile, api_url)
|
|
2706
2860
|
payload = _clean_payload({
|
|
@@ -2708,6 +2862,7 @@ def chatdb_add(chat_id, entity_name, data, items, profile, api_url):
|
|
|
2708
2862
|
'data': _parse_json_option(data, '--data'),
|
|
2709
2863
|
'items': _parse_json_option(items, '--items'),
|
|
2710
2864
|
}, {})
|
|
2865
|
+
payload.update(_chatdb_target(collection_name, collection_id))
|
|
2711
2866
|
response = _api_request('POST', f"{api_url}/api/v1/chats/{chat_id}/chatdb/entities", token,
|
|
2712
2867
|
ok_status=(200, 201), json=payload)
|
|
2713
2868
|
click.echo(json.dumps(response.json(), indent=2))
|
|
@@ -2722,8 +2877,10 @@ def chatdb_add(chat_id, entity_name, data, items, profile, api_url):
|
|
|
2722
2877
|
@click.option('--items', default=None, help='Bulk updates as a JSON array')
|
|
2723
2878
|
@click.option('--if-unchanged-since', default=None,
|
|
2724
2879
|
help='Only update if the row is unchanged since this timestamp (optimistic concurrency)')
|
|
2880
|
+
@_chatdb_target_options
|
|
2725
2881
|
@_connection_options
|
|
2726
|
-
def chatdb_update(chat_id, entity_id, data, merge, items, if_unchanged_since,
|
|
2882
|
+
def chatdb_update(chat_id, entity_id, data, merge, items, if_unchanged_since,
|
|
2883
|
+
collection_name, collection_id, profile, api_url):
|
|
2727
2884
|
"""Update ChatDB entities (by --entity-id, or in bulk via --items)."""
|
|
2728
2885
|
api_url, token = _resolve_connection(profile, api_url)
|
|
2729
2886
|
payload = _clean_payload({
|
|
@@ -2734,6 +2891,7 @@ def chatdb_update(chat_id, entity_id, data, merge, items, if_unchanged_since, pr
|
|
|
2734
2891
|
if not payload:
|
|
2735
2892
|
click.echo("Error: Nothing to update. Provide --entity-id/--data or --items.")
|
|
2736
2893
|
sys.exit(1)
|
|
2894
|
+
payload.update(_chatdb_target(collection_name, collection_id))
|
|
2737
2895
|
response = _api_request('PATCH', f"{api_url}/api/v1/chats/{chat_id}/chatdb/entities", token,
|
|
2738
2896
|
json=payload)
|
|
2739
2897
|
click.echo(json.dumps(response.json(), indent=2))
|
|
@@ -2744,8 +2902,9 @@ def chatdb_update(chat_id, entity_id, data, merge, items, if_unchanged_since, pr
|
|
|
2744
2902
|
@click.option('--entity-id', default=None, type=int, help='ID of a single entity to delete')
|
|
2745
2903
|
@click.option('--ids', default=None, help='Comma-separated entity IDs to delete')
|
|
2746
2904
|
@click.confirmation_option('--yes', prompt='Delete the specified ChatDB entities? This cannot be undone.')
|
|
2905
|
+
@_chatdb_target_options
|
|
2747
2906
|
@_connection_options
|
|
2748
|
-
def chatdb_delete(chat_id, entity_id, ids, profile, api_url):
|
|
2907
|
+
def chatdb_delete(chat_id, entity_id, ids, collection_name, collection_id, profile, api_url):
|
|
2749
2908
|
"""Delete ChatDB entities by --entity-id or a list of --ids."""
|
|
2750
2909
|
api_url, token = _resolve_connection(profile, api_url)
|
|
2751
2910
|
id_list = None
|
|
@@ -2759,6 +2918,7 @@ def chatdb_delete(chat_id, entity_id, ids, profile, api_url):
|
|
|
2759
2918
|
if not payload:
|
|
2760
2919
|
click.echo("Error: Provide --entity-id or --ids.")
|
|
2761
2920
|
sys.exit(1)
|
|
2921
|
+
payload.update(_chatdb_target(collection_name, collection_id))
|
|
2762
2922
|
_api_request('DELETE', f"{api_url}/api/v1/chats/{chat_id}/chatdb/entities", token,
|
|
2763
2923
|
ok_status=(200, 204), json=payload)
|
|
2764
2924
|
click.echo(f"Deleted ChatDB entities from chat {chat_id}")
|
|
@@ -2793,7 +2953,7 @@ def collections_list(page, page_size, search, profile, api_url):
|
|
|
2793
2953
|
@click.option('--name', required=True, help='Collection name')
|
|
2794
2954
|
@click.option('--description', default=None, help='Collection description')
|
|
2795
2955
|
@click.option('--type', 'collection_type', default=None,
|
|
2796
|
-
type=click.Choice(['collection', 'skill', 'external_source']),
|
|
2956
|
+
type=click.Choice(['collection', 'skill', 'external_source', 'db']),
|
|
2797
2957
|
help='Collection type (server default: collection)')
|
|
2798
2958
|
@click.option('--public/--private', 'public', default=None, help='Make the collection public (server default: private)')
|
|
2799
2959
|
@_connection_options(profile_short=False)
|
|
@@ -2825,7 +2985,7 @@ def collection_get(collection_id, profile, api_url):
|
|
|
2825
2985
|
@click.option('--name', default=None, help='Collection name')
|
|
2826
2986
|
@click.option('--description', default=None, help='Collection description')
|
|
2827
2987
|
@click.option('--type', 'collection_type', default=None,
|
|
2828
|
-
type=click.Choice(['collection', 'skill', 'external_source']),
|
|
2988
|
+
type=click.Choice(['collection', 'skill', 'external_source', 'db']),
|
|
2829
2989
|
help='Collection type')
|
|
2830
2990
|
@click.option('--public/--private', 'public', default=None, help='Make the collection public or private')
|
|
2831
2991
|
@click.option('--indexed/--not-indexed', 'indexed', default=None, help='Enable or disable indexing')
|
|
@@ -3128,7 +3288,11 @@ def _build_task_payload(**kwargs):
|
|
|
3128
3288
|
|
|
3129
3289
|
@cli.group()
|
|
3130
3290
|
def task():
|
|
3131
|
-
"""Task management commands.
|
|
3291
|
+
"""Task management commands.
|
|
3292
|
+
|
|
3293
|
+
Evaluations and simulations of a task live under `pt eval`
|
|
3294
|
+
(add/run/results, simulate/simulations) — they are not subcommands here.
|
|
3295
|
+
"""
|
|
3132
3296
|
pass
|
|
3133
3297
|
|
|
3134
3298
|
|
|
@@ -4789,8 +4953,8 @@ def eval_delete(task_id, evaluation_data_id, profile, api_url):
|
|
|
4789
4953
|
help='When evaluations run: manual/daily/weekly/monthly')
|
|
4790
4954
|
@click.option('--evaluator-agent-id', 'default_evaluator_agent_id', default=None, type=int,
|
|
4791
4955
|
help='Default grading agent')
|
|
4792
|
-
@click.option('--pass-threshold', 'evaluation_pass_threshold', default=None, type=
|
|
4793
|
-
help='Pass threshold (
|
|
4956
|
+
@click.option('--pass-threshold', 'evaluation_pass_threshold', default=None, type=click.IntRange(1, 100),
|
|
4957
|
+
help='Pass threshold as a percentage, 1-100 (e.g. 80)')
|
|
4794
4958
|
@click.option('--message-delay-ms', 'evaluation_message_delay_ms', default=None, type=int,
|
|
4795
4959
|
help='Delay between messages during a run')
|
|
4796
4960
|
@_connection_options
|
|
@@ -696,7 +696,7 @@ async def create_collection(
|
|
|
696
696
|
config: RunnableConfig,
|
|
697
697
|
name: Annotated[str, Field(description="Collection name")],
|
|
698
698
|
description: Annotated[Optional[str], Field(description="Collection description")] = None,
|
|
699
|
-
collection_type: Annotated[Optional[str], Field(description="collection/skill/external_source (server default: collection)")] = None,
|
|
699
|
+
collection_type: Annotated[Optional[str], Field(description="collection/skill/external_source/db (server default: collection)")] = None,
|
|
700
700
|
public: Annotated[Optional[bool], Field(description="Make the collection public (server default: private)")] = None,
|
|
701
701
|
) -> str:
|
|
702
702
|
"""Create a PrimeThink collection."""
|
|
@@ -722,7 +722,7 @@ async def update_collection(
|
|
|
722
722
|
collection_id: Annotated[str, Field(description="Collection ID")],
|
|
723
723
|
name: Annotated[Optional[str], Field(description="Collection name")] = None,
|
|
724
724
|
description: Annotated[Optional[str], Field(description="Collection description")] = None,
|
|
725
|
-
collection_type: Annotated[Optional[str], Field(description="collection/skill/external_source")] = None,
|
|
725
|
+
collection_type: Annotated[Optional[str], Field(description="collection/skill/external_source/db")] = None,
|
|
726
726
|
public: Annotated[Optional[bool], Field(description="Make the collection public")] = None,
|
|
727
727
|
indexed: Annotated[Optional[bool], Field(description="Enable or disable indexing")] = None,
|
|
728
728
|
ocr_instructions: Annotated[Optional[str], Field(description="OCR instructions for document processing")] = None,
|
|
@@ -1452,7 +1452,7 @@ async def set_task_evaluation_settings(
|
|
|
1452
1452
|
evaluation_active: Annotated[Optional[bool], Field(description="Enable/disable evaluation")] = None,
|
|
1453
1453
|
evaluation_run_time: Annotated[Optional[str], Field(description="manual/daily/weekly/monthly")] = None,
|
|
1454
1454
|
default_evaluator_agent_id: Annotated[Optional[int], Field(description="Default grading agent")] = None,
|
|
1455
|
-
evaluation_pass_threshold: Annotated[Optional[
|
|
1455
|
+
evaluation_pass_threshold: Annotated[Optional[int], Field(ge=1, le=100, description="Pass threshold as a percentage, 1-100 (e.g. 80)")] = None,
|
|
1456
1456
|
evaluation_message_delay_ms: Annotated[Optional[int], Field(description="Delay between messages")] = None,
|
|
1457
1457
|
) -> str:
|
|
1458
1458
|
"""Update a task's evaluation settings (the plan configuration)."""
|