@yugabytedb/meko-mcp 2.3.0 → 2.5.1
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.
- package/README.md +88 -35
- package/assets/hooks-handlers/lib/capture-cleanup-cli.js +735 -74
- package/assets/hooks-handlers/lib/capture-notices.js +94 -1
- package/assets/hooks-handlers/lib/capture-state.js +111 -0
- package/assets/hooks-handlers/lib/capture.js +130 -4
- package/assets/hooks-handlers/lib/checkpoint-timer.js +394 -8
- package/assets/hooks-handlers/lib/opencode-handler.js +29 -6
- package/assets/scripts/meko-statusline.sh +17 -1
- package/assets/skills/meko-mcp-tools/SKILL.md +6 -5
- package/assets/skills/meko-mcp-tools/references/_sections.md +1 -1
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +194 -10
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +6 -3
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +11 -6
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +4 -4
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +19 -14
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +69 -8
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +3 -1
- package/assets/skills/meko-mcp-tools-desktop/SKILL.md +8 -7
- package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +4 -4
- package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +1 -1
- package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +194 -10
- package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +10 -5
- package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +4 -4
- package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +19 -14
- package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +68 -8
- package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +3 -1
- package/assets/skills/meko-select-datapack-desktop/SKILL.md +91 -12
- package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +39 -7
- package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +8 -6
- package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +13 -1
- package/bin/create-meko-setup.mjs +152 -35
- package/lib/autofix.mjs +100 -0
- package/lib/browser-login.mjs +495 -0
- package/lib/clients/codex.mjs +1 -24
- package/lib/clients/common.mjs +25 -0
- package/lib/clients/opencode.mjs +6 -1
- package/lib/migrate/datapack.mjs +254 -16
- package/lib/migrate/mcp-client.mjs +34 -0
- package/lib/migrate/orchestrator.mjs +1 -1
- package/lib/migrate.mjs +2 -6
- package/lib/validate.mjs +111 -22
- package/package.json +5 -5
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
# Knowledge Base / RAG workflow
|
|
2
2
|
|
|
3
|
-
MCP exposes
|
|
4
|
-
`
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
MCP exposes four KB tools: `knowledgebase_search` (retrieval),
|
|
4
|
+
`knowledgebase_upload_document` and `knowledgebase_document_status` (add a
|
|
5
|
+
file and track its indexing), and `knowledgebase_delete_document` (remove ONE
|
|
6
|
+
uploaded file). Creating, listing or renaming a knowledge base itself still
|
|
7
|
+
happens out of band — through the **Meko UI** (`cloud.mekodata.ai`).
|
|
7
8
|
|
|
8
9
|
## Decision table
|
|
9
10
|
|
|
10
11
|
| Situation | Use this | Why |
|
|
11
12
|
|---|---|---|
|
|
12
13
|
| Search an existing KB | `knowledgebase_search` | Retrieval over the indexed chunks |
|
|
13
|
-
| Add
|
|
14
|
+
| Add a file to a KB | `knowledgebase_upload_document` + one direct S3 POST | Requests a presigned URL, then you POST the file to it; no need to leave MCP |
|
|
15
|
+
| Track a file's indexing progress | `knowledgebase_document_status` | Poll with the `key` from the upload response, passed here as `document_key`, until `state` is terminal |
|
|
16
|
+
| Add documents to a KB from the Cloud UI instead | **Meko UI** — Datapack → Actions → **Add Knowledge** | File-upload dialog (PDF/TXT/MD/JSON/CSV/XML/HTML, 5 MB Free / 50 MB Standard / 60 MB Pro+ each, 10/batch). Same index either way — this is the human-facing path, not required when an agent can upload directly |
|
|
14
17
|
| Delete ONE uploaded file | `knowledgebase_delete_document` | Destructive; `document_id` from search hits; confirm with the user first |
|
|
15
18
|
| Anything else (list / rename / re-index / source lifecycle) | **UI** | No MCP tools for the rest of KB lifecycle |
|
|
16
19
|
|
|
@@ -58,6 +61,59 @@ Lower `distance` is closer. Promoted memories appear as hits whose `metadata_fil
|
|
|
58
61
|
Empty or nonexistent KB: `{"results": [], "count": 0}` (no error,
|
|
59
62
|
just an empty array).
|
|
60
63
|
|
|
64
|
+
## knowledgebase_upload_document — putting a file in
|
|
65
|
+
|
|
66
|
+
This tool never touches the file's bytes itself — it only requests a
|
|
67
|
+
presigned S3 URL. **You POST the file to that URL yourself**, as a
|
|
68
|
+
second step:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
knowledgebase_upload_document(
|
|
72
|
+
filename="report.pdf",
|
|
73
|
+
size=42000,
|
|
74
|
+
content_hash="<sha256 hex of the file's bytes>",
|
|
75
|
+
conversation_id="<uuid from conversation_create>",
|
|
76
|
+
agent_id="claude_desktop",
|
|
77
|
+
content_head_base64="<base64 of the file's first ~4KB>")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Build the POST from every key in the response's `fields`, not a hand-picked list:
|
|
81
|
+
a missing signed field such as `x-amz-security-token` makes S3 answer 403. Use
|
|
82
|
+
the Python, curl, or PowerShell snippet under `knowledgebase_upload_document`
|
|
83
|
+
in `tools-cookbook.md`. Confirm with the user first: the file becomes visible to
|
|
84
|
+
every datapack member.
|
|
85
|
+
|
|
86
|
+
Required: `filename`, `size` (the exact byte count — the URL accepts no
|
|
87
|
+
other length), `content_hash`, `conversation_id`, `content_head_base64`. `content_hash` is the SHA-256 hex digest of the
|
|
88
|
+
file's bytes, computed by you (e.g. `sha256sum`) — it becomes part of
|
|
89
|
+
the S3 key, so it also drives the dedup check. A response with
|
|
90
|
+
`already_uploaded: true` means identical content already exists; skip
|
|
91
|
+
the S3 POST entirely, there is nothing left to upload. Otherwise POST
|
|
92
|
+
as above: every key in `fields` as a form field (in order), then the
|
|
93
|
+
bytes last as a field named `"file"`. Meko registers the object once
|
|
94
|
+
it lands, so no separate confirm call is needed after the POST. Accepted extensions:
|
|
95
|
+
pdf, txt, text, md, json, csv, xml, html, htm; `content_head_base64` is
|
|
96
|
+
always sniffed against the extension before requesting the URL,
|
|
97
|
+
rejecting an obvious mismatch immediately instead of waiting for the
|
|
98
|
+
watcher — a missing/blank value is rejected as
|
|
99
|
+
`content_head_base64_required`, this sniff cannot be skipped.
|
|
100
|
+
Ingestion is asynchronous — save the response's
|
|
101
|
+
`key` (as `document_key`) and poll `knowledgebase_document_status`.
|
|
102
|
+
|
|
103
|
+
## knowledgebase_document_status — tracking it
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
knowledgebase_document_status(
|
|
107
|
+
document_key="<the upload response's `key`>",
|
|
108
|
+
conversation_id="<uuid from conversation_create>",
|
|
109
|
+
agent_id="claude_desktop")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`state` covers the whole lifecycle: `awaiting_upload` and `indexing`
|
|
113
|
+
are non-terminal (poll again); `completed`, `failed`, `abandoned`, and
|
|
114
|
+
`oversized` are terminal. `NOT_FOUND` means the `document_key` doesn't
|
|
115
|
+
belong to this datapack.
|
|
116
|
+
|
|
61
117
|
## UI ingestion — what the user sees
|
|
62
118
|
|
|
63
119
|
From `cloud.mekodata.ai`:
|
|
@@ -65,11 +121,15 @@ From `cloud.mekodata.ai`:
|
|
|
65
121
|
1. Open a datapack (`/datapacks/<name>`).
|
|
66
122
|
2. Click **Actions** → **Add Knowledge**.
|
|
67
123
|
3. Drag-and-drop or browse for files. Supported: PDF, TXT, MD, JSON,
|
|
68
|
-
|
|
124
|
+
CSV, XML, HTML. Per-file limit 5 MB (Free) / 50 MB (Standard) / 60 MB (Pro+). Up to 10 files per batch.
|
|
69
125
|
4. The UI handles upload, storage, and index build. The user does not
|
|
70
126
|
pick a bucket or provide credentials.
|
|
71
127
|
5. Search results from `knowledgebase_search` become available once
|
|
72
128
|
indexing completes.
|
|
73
129
|
|
|
74
|
-
If a
|
|
75
|
-
point them at this flow.
|
|
130
|
+
If a *human* asks you "how do I add a document to my knowledge base?",
|
|
131
|
+
point them at this flow. If *you* (the agent) have the file's bytes —
|
|
132
|
+
already on disk, or generated mid-conversation — and can send them in an
|
|
133
|
+
HTTPS POST to an external URL yourself (a local shell, or a code tool with
|
|
134
|
+
internet access), call `knowledgebase_upload_document` directly instead
|
|
135
|
+
of describing the UI flow to yourself.
|
|
@@ -53,9 +53,11 @@ These patterns are extracted from real agent sessions. Follow them to avoid wast
|
|
|
53
53
|
| Error | Meaning | What to do |
|
|
54
54
|
|---|---|---|
|
|
55
55
|
| `datapack_access_denied` | The `datapack_id` isn't a UUID, or it isn't owned by or shared with your account. The access check also fails closed on a transient server database error. | Retry once. If it repeats, stop; don't switch to another datapack. If the id came from a pin, ask the user to re-pin with the select-datapack skill. |
|
|
56
|
-
| `datapack_id_required` | The call couldn't resolve a datapack. Conversation reads and writes (including `conversation_list`), `datapack_describe`, and `knowledgebase_delete_document` return it. | Pass the pinned `datapack_id`. Don't drop the parameter to make the call pass. |
|
|
56
|
+
| `datapack_id_required` | The call couldn't resolve a datapack. Conversation reads and writes (including `conversation_list`), `datapack_describe`, `knowledgebase_upload_document`, `knowledgebase_document_status`, and `knowledgebase_delete_document` return it. | Pass the pinned `datapack_id`. Don't drop the parameter to make the call pass. |
|
|
57
57
|
| `not_found` from `memory_get_by_id`, `memory_update`, or `memory_delete_by_id` | The memory doesn't exist **or** belongs to another account. The server returns the same error for both on purpose. | Check the id came from a search in this datapack. |
|
|
58
58
|
| `memory_is_promoted` | The memory was promoted to shared knowledge and is read-only through MCP. | Point the user at the Cloud UI Learnings tab. |
|
|
59
|
+
| `read_only_access` | You're a viewer on this datapack. Viewers can't write conversations or memories, call `memory_promote`, `artifact_put`, or `track_token_usage`, or delete a conversation someone else started. | Don't retry, and don't switch datapacks to get around it. Tell the user; an owner or maintainer can change their role. |
|
|
60
|
+
| `role_lookup_failed` | The server couldn't read your role for this datapack, so it refused the write. | Retry. |
|
|
59
61
|
| `invalid_run_id` | `memory_delete_all` got a `run_id` that isn't a conversation id. | Pass the conversation UUID, or omit `run_id`. |
|
|
60
62
|
| `embedder_error` from `knowledgebase_search` | The server couldn't resolve the embedding setup for this datapack's index. | Report it; retrying won't help. |
|
|
61
63
|
| `invalid_force_source` from `context_search` | `force_source` isn't `auto`, `memory`, `knowledge_base`, or `conversation`. | Omit `force_source`. |
|
|
@@ -11,7 +11,7 @@ description: >-
|
|
|
11
11
|
license: MIT
|
|
12
12
|
metadata:
|
|
13
13
|
author: Meko
|
|
14
|
-
version: "1.
|
|
14
|
+
version: "1.3.1"
|
|
15
15
|
tags: meko, datapack, selection, project, claude-desktop, desktop
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -63,7 +63,7 @@ This is once per turn, not once per call. Cache within the turn.
|
|
|
63
63
|
Use a **temporary** conversation for browsing only. Call
|
|
64
64
|
`conversation_create(agent_id="claude_desktop", title="Claude
|
|
65
65
|
Desktop datapack selection")` and use its returned ID for the read-only
|
|
66
|
-
|
|
66
|
+
datapack calls below and for the pin `memory_add`/`memory_update` in step 4.
|
|
67
67
|
|
|
68
68
|
**Do not reuse this conversation for later capture.** It lives in whatever
|
|
69
69
|
datapack was active when it was created (typically the default), and a
|
|
@@ -71,12 +71,28 @@ conversation cannot move between datapacks. Once a datapack is pinned, capture
|
|
|
71
71
|
must flow through a *new* conversation created in the selected datapack — see
|
|
72
72
|
step 5.
|
|
73
73
|
|
|
74
|
+
Check your tool list. If it has `datapack_search`, use it as below. If it
|
|
75
|
+
doesn't (an older Meko server), use the fallback section at the end of step 3.
|
|
76
|
+
|
|
74
77
|
```
|
|
75
|
-
|
|
78
|
+
datapack_search(conversation_id="<this conversation's id>", limit=10, include_total=true)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The server sorts, filters and pages, so this works the same for 3 datapacks or
|
|
82
|
+
1,000,000. The response is one page:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
{"datapacks": [...], "has_more": true, "next_cursor": "<opaque token>", "total": 14}
|
|
76
86
|
```
|
|
77
87
|
|
|
78
|
-
|
|
79
|
-
`
|
|
88
|
+
- `datapacks`: up to `limit` rows, newest first (`created_at DESC`). The
|
|
89
|
+
fields you'll use are `datapack_id`, `datapack_name`, `created_at`, and
|
|
90
|
+
`grant`.
|
|
91
|
+
- `has_more`: `true` when another page exists.
|
|
92
|
+
- `next_cursor`: pass it as `cursor` to get the next page. It is `""` on the
|
|
93
|
+
last page. Treat it as opaque: never build or edit one.
|
|
94
|
+
- `total`: how many datapacks match, present because you passed
|
|
95
|
+
`include_total=true`.
|
|
80
96
|
|
|
81
97
|
`grant` is the caller's actual authorization on the datapack — one of
|
|
82
98
|
`"owner"`, `"maintainer"`, `"contributor"`, `"viewer"`. Display it verbatim in
|
|
@@ -85,13 +101,22 @@ the Role column. Do not hardcode "Owner", do not invent or normalize the value
|
|
|
85
101
|
response is the source of truth — see `references/role-display-future.md` for
|
|
86
102
|
the taxonomy.
|
|
87
103
|
|
|
88
|
-
If
|
|
104
|
+
If `total` is 0, tell the user: *"You don't have any datapacks yet. Run `datapack_create(name='<name>', conversation_id='<conversation id>')` to make one, or visit the Meko Cloud console."* Stop here.
|
|
105
|
+
|
|
106
|
+
If `total` is exactly **1**, **auto-select it**. Print: *"Only one datapack: `<name>`. Auto-selecting. Run `meko-select-datapack-desktop` again with `clear` to unset."* Skip the table; jump to step 4 (persist) and step 5 (confirm).
|
|
107
|
+
|
|
108
|
+
If `total` is missing or `null`, decide from the page instead: no rows and
|
|
109
|
+
`has_more` false means zero datapacks; one row and `has_more` false means
|
|
110
|
+
exactly one. Drop `of <total>` from the header in step 2.
|
|
89
111
|
|
|
90
|
-
|
|
112
|
+
**Keep the paging state in the conversation.** Remember the current filter
|
|
113
|
+
(none yet), the `total`, the page number, the `next_cursor`, and a list of the
|
|
114
|
+
cursors you used for each page so far (page 1 used no cursor). `next` and
|
|
115
|
+
`prev` in step 3 need them.
|
|
91
116
|
|
|
92
117
|
### 2. Render the table
|
|
93
118
|
|
|
94
|
-
For 2+ datapacks, render a numbered table. **Page size 10.**
|
|
119
|
+
For 2+ datapacks, render a numbered table of the current page. **Page size 10.** Row order is the server's (`created_at DESC`, newest first). Number rows by position in the whole list: page 1 shows 1-10, page 2 shows 11-20. The count line is `Your datapacks (showing <first>-<last> of <total>):`, for example:
|
|
95
120
|
|
|
96
121
|
```
|
|
97
122
|
Your datapacks (showing 1-10 of 14):
|
|
@@ -112,17 +137,71 @@ The **Role** column shows each datapack's `grant` value verbatim (`owner`,
|
|
|
112
137
|
datapacks legitimately carry other grants, and misreporting them (e.g. showing
|
|
113
138
|
a `maintainer` grant as "Owner") misleads the user about their own access.
|
|
114
139
|
|
|
115
|
-
Mark the currently-pinned row with `← (pinned)` based on the `memory_search` result (if any).
|
|
140
|
+
Mark the currently-pinned row with `← (pinned)` based on the `memory_search` result (if any). If the pinned datapack is not on the current page, name it in one line above the table.
|
|
141
|
+
|
|
142
|
+
In the legend, the number range is the rows on the current page (`11-20` on
|
|
143
|
+
page 2). Offer `next` only when `has_more` is true and `next_cursor` is
|
|
144
|
+
non-empty. An empty `next_cursor` with `has_more` still true means this
|
|
145
|
+
server cannot page further: tell the user to narrow with a substring, and
|
|
146
|
+
do not send an empty cursor. Offer `prev` only after page 1.
|
|
147
|
+
|
|
148
|
+
For a search (step 3), the count line is
|
|
149
|
+
`Datapacks matching "<text>" (showing <first>-<last> of <total>):`, numbered
|
|
150
|
+
from 1.
|
|
116
151
|
|
|
117
152
|
### 3. Parse the user's reply
|
|
118
153
|
|
|
119
|
-
- **Integer
|
|
120
|
-
- **Substring** →
|
|
121
|
-
|
|
154
|
+
- **Integer shown on the current page** → that row is the choice.
|
|
155
|
+
- **Substring** → search on the server; do not filter the rows you already have:
|
|
156
|
+
```
|
|
157
|
+
datapack_search(conversation_id="<this conversation's id>", query="<text>", limit=10, include_total=true)
|
|
158
|
+
```
|
|
159
|
+
This starts a new listing: reset the page number and the cursor list, and
|
|
160
|
+
keep `<text>` as the filter so `next` / `prev` page through the matches. If
|
|
161
|
+
`total` is 0, say *"No datapacks match `<text>`."* and re-prompt with the
|
|
162
|
+
legend. If `total` is exactly 1, that's the choice. Otherwise render the
|
|
163
|
+
matches with the search count line from step 2.
|
|
164
|
+
- **`next`** → if `has_more` is false, say this is the last page and
|
|
165
|
+
re-prompt. If `next_cursor` is empty, say this server cannot page further
|
|
166
|
+
and ask for a substring; do not send an empty cursor. Otherwise call
|
|
167
|
+
`datapack_search` with the same `query` (if any), `limit=10` and
|
|
168
|
+
`cursor="<next_cursor>"`, add that cursor to your list, and render the new
|
|
169
|
+
page. Reuse the `total` you already have.
|
|
170
|
+
- **`prev`** → on page 1, say this is the first page and re-prompt. Otherwise
|
|
171
|
+
drop the last cursor from your list and call `datapack_search` again with
|
|
172
|
+
the same `query` and the cursor now at the end of the list (no cursor for
|
|
173
|
+
page 1).
|
|
122
174
|
- **`cancel`** → leave any existing pin in place; print *"Cancelled. Active datapack unchanged."* Stop.
|
|
123
175
|
- **`clear` / `none` / `unpin`** → see step 4's clear path.
|
|
124
176
|
- **Unrecognized** → re-prompt with the legend.
|
|
125
177
|
|
|
178
|
+
If a call with a `cursor` returns an error, the cursor is no longer usable.
|
|
179
|
+
Tell the user, then start again from the first page of the same filter.
|
|
180
|
+
|
|
181
|
+
When the user names a datapack in the request itself ("pin prod-research"),
|
|
182
|
+
skip the first listing and go straight to the substring search with that name.
|
|
183
|
+
|
|
184
|
+
### Fallback: servers without `datapack_search`
|
|
185
|
+
|
|
186
|
+
An older Meko server has only `datapack_list`. Run the same steps with these
|
|
187
|
+
changes:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
datapack_list(conversation_id="<this conversation's id>")
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
- The response is one array of every datapack, with the same row fields.
|
|
194
|
+
`total` is the array length.
|
|
195
|
+
- Sort it `created_at DESC` yourself, show 10 rows per page, and page
|
|
196
|
+
`next` / `prev` over the array you already have.
|
|
197
|
+
- Filter substrings client-side on `datapack_name` (case-insensitive) and
|
|
198
|
+
re-render the matching rows numbered from 1. If the filter narrows to one
|
|
199
|
+
row, that's the choice.
|
|
200
|
+
|
|
201
|
+
If `datapack_list` returns `{"error": "too_many_datapacks", ...}`, the server
|
|
202
|
+
does have `datapack_search`; your tool list is stale. Reload the Meko tools and
|
|
203
|
+
use the main flow.
|
|
204
|
+
|
|
126
205
|
### 4. Persist
|
|
127
206
|
|
|
128
207
|
**On first pin (no existing pin memory):**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cookbook — meko-select-datapack-desktop
|
|
2
2
|
|
|
3
|
-
Concrete transcripts of the
|
|
3
|
+
Concrete transcripts of the flows the skill supports on Claude Desktop.
|
|
4
4
|
|
|
5
5
|
## Flow 1 — First pin (no existing pin memory)
|
|
6
6
|
|
|
@@ -11,8 +11,8 @@ Concrete transcripts of the four flows the skill supports on Claude Desktop.
|
|
|
11
11
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", conversation_id="<conv-id>", limit=1)
|
|
12
12
|
[empty]
|
|
13
13
|
|
|
14
|
-
>
|
|
15
|
-
[
|
|
14
|
+
> datapack_search(conversation_id="<conv-id>", query="prod-research", limit=10, include_total=true)
|
|
15
|
+
[1 row, has_more=false, next_cursor="", total=1]
|
|
16
16
|
|
|
17
17
|
One match: `prod-research`. Pinning.
|
|
18
18
|
|
|
@@ -44,8 +44,8 @@ datapack_id flows through automatically.
|
|
|
44
44
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", conversation_id="<conv-id>", limit=1)
|
|
45
45
|
[returns id=mem_abc123, text="meko_active_datapack=8b1c…f4a2 name=prod-research …"]
|
|
46
46
|
|
|
47
|
-
>
|
|
48
|
-
[
|
|
47
|
+
> datapack_search(conversation_id="<conv-id>", query="q2-roadmap-deck", limit=10, include_total=true)
|
|
48
|
+
[1 row, has_more=false, next_cursor="", total=1]
|
|
49
49
|
|
|
50
50
|
One match: `q2-roadmap-deck`. Switching pin.
|
|
51
51
|
|
|
@@ -69,8 +69,8 @@ The `memory_update` is critical here — using `memory_add` again would create a
|
|
|
69
69
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", conversation_id="<conv-id>", limit=1)
|
|
70
70
|
[empty]
|
|
71
71
|
|
|
72
|
-
>
|
|
73
|
-
[1
|
|
72
|
+
> datapack_search(conversation_id="<conv-id>", limit=10, include_total=true)
|
|
73
|
+
[1 row, has_more=false, next_cursor="", total=1]
|
|
74
74
|
|
|
75
75
|
Only one datapack: `meko-local-setup`. Auto-selecting.
|
|
76
76
|
|
|
@@ -119,3 +119,35 @@ This isn't a user-triggered flow — it's the per-turn lookup the skill teaches
|
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
Cache the UUID for the rest of the turn — don't call `memory_search` once per Meko tool call.
|
|
122
|
+
|
|
123
|
+
## Flow 6: Browse and page
|
|
124
|
+
|
|
125
|
+
**User:** `list my datapacks`
|
|
126
|
+
|
|
127
|
+
**Skill:**
|
|
128
|
+
```
|
|
129
|
+
> datapack_search(conversation_id="<conv-id>", limit=10, include_total=true)
|
|
130
|
+
[10 rows, has_more=true, next_cursor="eyJ2Ijox…", total=14]
|
|
131
|
+
|
|
132
|
+
Your datapacks (showing 1-10 of 14):
|
|
133
|
+
…
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**User:** `next`
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
> datapack_search(conversation_id="<conv-id>", limit=10, cursor="eyJ2Ijox…")
|
|
140
|
+
[4 rows, has_more=false, next_cursor=""]
|
|
141
|
+
|
|
142
|
+
Your datapacks (showing 11-14 of 14):
|
|
143
|
+
…
|
|
144
|
+
|
|
145
|
+
Reply with: a number (11-14) to pin · a substring to search · `prev` to page
|
|
146
|
+
· `clear` to unset · `cancel` to leave the current pin alone
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The skill remembers each cursor it used. On `prev` it drops the last one and repeats the call for page 1, which had no cursor. The total (14) is reused from page 1. A substring reply calls `datapack_search(query="<text>", limit=10, include_total=true)` and starts a new listing.
|
|
150
|
+
|
|
151
|
+
## Flow 7: Older server without `datapack_search`
|
|
152
|
+
|
|
153
|
+
The tool list has `datapack_list` but no `datapack_search`. The skill calls `datapack_list(conversation_id="<conv-id>")` once, then sorts, pages and filters that array in the conversation. The table and replies look the same.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Today: render `grant` verbatim
|
|
4
4
|
|
|
5
|
-
The deployed Meko `GET /datapacks` response includes a `grant` field on every datapack. Possible values (per maintainer guidance, 2026-05-26):
|
|
5
|
+
The deployed Meko `GET /datapacks` response includes a `grant` field on every datapack, and so does every row that `datapack_search` and `datapack_list` return. Possible values (per maintainer guidance, 2026-05-26):
|
|
6
6
|
|
|
7
7
|
- `"owner"` — datapacks the caller created.
|
|
8
8
|
- `"maintainer"` — write access to a shared datapack including memories AND collective learnings/knowledge.
|
|
@@ -20,11 +20,11 @@ Use the field directly in the **Role** column:
|
|
|
20
20
|
|
|
21
21
|
Do not invent values, do not normalize the casing, do not display `"Owner"` if the field says `"owner"`. The deployed schema is the source of truth.
|
|
22
22
|
|
|
23
|
-
Note that the
|
|
23
|
+
Note that the server's `Datapack` model doesn't declare `grant`: the deployed server enriches the response beyond what the public Go code lists. Don't rely on the public struct for the wire schema; trust the actual response.
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Counts are not on the list response
|
|
26
26
|
|
|
27
|
-
`datapack_list`
|
|
27
|
+
Neither `datapack_search` nor `datapack_list` computes counts; their rows carry no count fields. If the user asks for counts, call `datapack_describe(datapack_id=<id>, conversation_id="<conversation id>")` and read them from that response:
|
|
28
28
|
|
|
29
29
|
- `memory_count`: all memories stored in the datapack.
|
|
30
30
|
- `collective_memory_count`: memories promoted to shared knowledge.
|
|
@@ -34,9 +34,11 @@ Note that the upstream Go source (the `Datapack` struct in `api_server/internal/
|
|
|
34
34
|
|
|
35
35
|
Don't add counts to the table silently, and never invent the numbers.
|
|
36
36
|
|
|
37
|
-
## Sharing
|
|
37
|
+
## Sharing a datapack
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
An owner or maintainer shares a datapack from the Cloud console's **Share** page. Each datapack has one share link. The owner or maintainer can turn it on or off, reset it, and choose whether people who open it join as viewer or contributor. Anyone signed in who opens an active link joins straight away. There are no MCP tools to manage sharing.
|
|
40
|
+
|
|
41
|
+
A viewer is read-only, and the server enforces it: over MCP, conversation and memory writes return `read_only_access`. If the user picks a datapack where they're a viewer, tell them that Meko won't record conversations or save memories there.
|
|
40
42
|
|
|
41
43
|
## Why the skill ships without Mine / Shared / All filter tabs
|
|
42
44
|
|
|
@@ -33,7 +33,7 @@ Then either re-run the skill or delete the pin memory. Do not silently fall back
|
|
|
33
33
|
|
|
34
34
|
Never auto-pick when there's ambiguity. Re-render just the matching rows numbered from 1, and ask the user to pick a number from the filtered subset. Same as the Claude Code variant.
|
|
35
35
|
|
|
36
|
-
## Symptom: `datapack_list` returns an empty array
|
|
36
|
+
## Symptom: The account has no datapacks (`total` is 0, or `datapack_list` returns an empty array)
|
|
37
37
|
|
|
38
38
|
The user has zero datapacks. Print:
|
|
39
39
|
|
|
@@ -47,6 +47,18 @@ Or visit the Meko Cloud console (Datapacks → New datapack).
|
|
|
47
47
|
|
|
48
48
|
Stop. Don't `memory_add` an empty pin.
|
|
49
49
|
|
|
50
|
+
## Symptom: `next` or `prev` returns an error about the cursor
|
|
51
|
+
|
|
52
|
+
The cursor is tied to the search it came from. It stops working if you change `query`, `sort` or `grant` while paging, or if you edit it. Always send the cursor back unchanged, with the same filters as the call that returned it. Tell the user the page could not be loaded and start again from page 1 of the same search (no cursor).
|
|
53
|
+
|
|
54
|
+
## Symptom: `datapack_list` returns `too_many_datapacks`
|
|
55
|
+
|
|
56
|
+
The account can see more datapacks than `datapack_list` returns in one array (1000 by default). The server that sends this error also has `datapack_search`. Use the main flow with `datapack_search`; if it is missing from your tool list, the list is stale, so reload the Meko tools.
|
|
57
|
+
|
|
58
|
+
## Symptom: The tool list has no `datapack_search`
|
|
59
|
+
|
|
60
|
+
The Meko server is older than that tool. Use the skill's fallback flow with `datapack_list`: one call, then sort, page and filter the array in the conversation. On an older server, this call can fail for an account with a very large number of datapacks; that account needs a server that has `datapack_search`.
|
|
61
|
+
|
|
50
62
|
## Symptom: User typed `cancel` after the table rendered
|
|
51
63
|
|
|
52
64
|
Leave the existing pin memory alone. Print:
|