papiers 0.1.3 → 0.1.5
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 +91 -17
- package/dist/index.js +340 -84
- package/package.json +1 -1
- package/skills/papiers-research/SKILL.md +11 -8
package/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Search and read your Papiers library from the terminal.
|
|
4
4
|
|
|
5
|
+
The CLI is read-only: it can inspect your saved documents, highlights, notes,
|
|
6
|
+
and conversations, but it cannot change your library.
|
|
7
|
+
|
|
5
8
|
## Install
|
|
6
9
|
|
|
7
10
|
```bash
|
|
@@ -10,17 +13,60 @@ npm install -g papiers
|
|
|
10
13
|
|
|
11
14
|
Requires Node.js 22 or newer.
|
|
12
15
|
|
|
13
|
-
##
|
|
16
|
+
## First run
|
|
14
17
|
|
|
15
|
-
In Papiers, open Settings -> API tokens
|
|
18
|
+
1. In Papiers, open Settings -> API tokens and create a token.
|
|
19
|
+
2. Sign in and check the connection:
|
|
16
20
|
|
|
17
21
|
```bash
|
|
18
22
|
papiers auth login
|
|
23
|
+
papiers auth status
|
|
24
|
+
papiers doctor
|
|
19
25
|
```
|
|
20
26
|
|
|
21
27
|
Paste the token when prompted. The CLI saves it locally so you do not need to
|
|
22
28
|
paste it again.
|
|
23
29
|
|
|
30
|
+
3. Explore your library with human-readable output:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# See what you saved recently.
|
|
34
|
+
papiers list --kind document --limit 5 --pretty
|
|
35
|
+
|
|
36
|
+
# Search across documents, passages, highlights, notes, and conversations.
|
|
37
|
+
papiers search "retrieval augmented generation" --limit 5 --pretty
|
|
38
|
+
|
|
39
|
+
# List notes, then read one using the nte_... ID from the result.
|
|
40
|
+
papiers list --kind note --limit 5 --pretty
|
|
41
|
+
papiers read nte_... --format markdown --pretty
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Run `papiers <command> --help` for command-specific options or
|
|
45
|
+
`papiers help --all` for the complete CLI reference.
|
|
46
|
+
|
|
47
|
+
## Common workflows
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Recent highlights.
|
|
51
|
+
papiers list --kind highlight --since 30d --limit 10 --pretty
|
|
52
|
+
|
|
53
|
+
# Read the matching passages from a search through stdin.
|
|
54
|
+
papiers search "retrieval" --kind passage --limit 5 --passage-ids \
|
|
55
|
+
| papiers read @- --format plain --pretty
|
|
56
|
+
|
|
57
|
+
# Read document metadata without fetching its full content.
|
|
58
|
+
papiers read doc_... --format metadata --pretty
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Data commands emit stable JSON by default. Use `--pretty` for terminal reading;
|
|
62
|
+
use `--json`, `--ids`, `--ids0`, and `--doc-ids` for scripts and pipelines.
|
|
63
|
+
|
|
64
|
+
To forget the locally saved token:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
papiers auth logout
|
|
68
|
+
```
|
|
69
|
+
|
|
24
70
|
## Use with an AI agent
|
|
25
71
|
|
|
26
72
|
This is what `papiers` is really for. Point a coding or research agent (Claude
|
|
@@ -31,10 +77,28 @@ you wrote, the conversations you had — instead of generic web knowledge.
|
|
|
31
77
|
The package ships a ready-to-use agent skill at
|
|
32
78
|
[`skills/papiers-research/SKILL.md`](skills/papiers-research/SKILL.md). It
|
|
33
79
|
encodes the loop — survey what you've been reading, search across passages +
|
|
34
|
-
highlights + conversations in one ranking, then read and cite your own
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
80
|
+
highlights + notes + conversations in one ranking, then read and cite your own
|
|
81
|
+
sources.
|
|
82
|
+
|
|
83
|
+
After a global install, locate the packaged skill under the npm root:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
PAPIERS_ROOT="$(npm root -g)/papiers"
|
|
87
|
+
|
|
88
|
+
# Claude Code, project-local skill
|
|
89
|
+
mkdir -p .claude/skills/papiers-research
|
|
90
|
+
cp "$PAPIERS_ROOT/skills/papiers-research/SKILL.md" \
|
|
91
|
+
.claude/skills/papiers-research/SKILL.md
|
|
92
|
+
|
|
93
|
+
# Codex, project-local skill
|
|
94
|
+
mkdir -p .codex/skills/papiers-research
|
|
95
|
+
cp "$PAPIERS_ROOT/skills/papiers-research/SKILL.md" \
|
|
96
|
+
.codex/skills/papiers-research/SKILL.md
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
For another agent, add the same file through its normal skill or project
|
|
100
|
+
instructions mechanism. Then ask the agent to propose an idea, design an
|
|
101
|
+
experiment, or review a draft. It will think with your library, not around it.
|
|
38
102
|
|
|
39
103
|
```bash
|
|
40
104
|
# the agent only needs your token in its environment:
|
|
@@ -44,18 +108,28 @@ export PAPIERS_TOKEN=pap_live_...
|
|
|
44
108
|
Every data command emits a stable JSON envelope (`--json` makes errors JSON
|
|
45
109
|
too), so an agent can learn the whole tool from `papiers --help --all` alone.
|
|
46
110
|
|
|
47
|
-
##
|
|
111
|
+
## Automation
|
|
48
112
|
|
|
49
113
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
papiers
|
|
114
|
+
# Keep the token in the process environment rather than passing it as an
|
|
115
|
+
# argument. Do not commit it to source control.
|
|
116
|
+
export PAPIERS_TOKEN=pap_live_...
|
|
117
|
+
papiers search "mixture of experts" --limit 10 --json
|
|
54
118
|
```
|
|
55
119
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
|
|
120
|
+
`PAPIERS_TOKEN` takes precedence over a token saved by `papiers auth login`.
|
|
121
|
+
Run `papiers doctor` to see which token source and API endpoint are active.
|
|
122
|
+
|
|
123
|
+
## Troubleshooting
|
|
124
|
+
|
|
125
|
+
- **`papiers: command not found`:** run `npm prefix -g` and make sure that
|
|
126
|
+
installation's binary directory is on `PATH`.
|
|
127
|
+
- **Unsupported Node.js version:** run `node --version` and install Node.js 22
|
|
128
|
+
or newer.
|
|
129
|
+
- **Authentication failed:** run `papiers auth status`. If necessary, run
|
|
130
|
+
`papiers auth logout`, create a fresh token in Papiers, and sign in again.
|
|
131
|
+
- **Wrong token or endpoint:** run `papiers doctor`. Unset `PAPIERS_TOKEN` or
|
|
132
|
+
`PAPIERS_API_BASE_URL` if an automation environment is overriding your saved
|
|
133
|
+
login or the production endpoint.
|
|
134
|
+
- **Connection or API error:** run `papiers doctor`, then retry the failing
|
|
135
|
+
command with `--json` to get a machine-readable error and request ID.
|
package/dist/index.js
CHANGED
|
@@ -412,13 +412,41 @@ function isNodeError(error) {
|
|
|
412
412
|
return Boolean(error && typeof error === "object" && "code" in error);
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
// ../../src/shared/papiers-resource-locators.ts
|
|
416
|
+
var UUID_PATTERN = "[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
|
|
417
|
+
var PAPIERS_RESOURCE_LOCATOR_PATTERN_SOURCE = `papiers://(?:note|highlight|item|conversation|artifact)/${UUID_PATTERN}`;
|
|
418
|
+
var RESOURCE_LOCATOR_PATTERN = new RegExp(
|
|
419
|
+
`^papiers://(note|highlight|item|conversation|artifact)/(${UUID_PATTERN})$`,
|
|
420
|
+
"u"
|
|
421
|
+
);
|
|
422
|
+
var UUID_REGEX = new RegExp(`^${UUID_PATTERN}$`, "iu");
|
|
423
|
+
var READ_KIND_BY_LOCATOR_KIND = {
|
|
424
|
+
note: "note",
|
|
425
|
+
highlight: "highlight",
|
|
426
|
+
item: "document",
|
|
427
|
+
conversation: "conversation",
|
|
428
|
+
artifact: "artifact"
|
|
429
|
+
};
|
|
430
|
+
function parsePapiersResourceLocator(value) {
|
|
431
|
+
const match = RESOURCE_LOCATOR_PATTERN.exec(value);
|
|
432
|
+
if (!match) return null;
|
|
433
|
+
const kind = match[1];
|
|
434
|
+
return {
|
|
435
|
+
value,
|
|
436
|
+
kind,
|
|
437
|
+
readKind: READ_KIND_BY_LOCATOR_KIND[kind],
|
|
438
|
+
internalId: match[2].toLowerCase()
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
415
442
|
// src/document-contract.ts
|
|
416
443
|
var PUBLIC_KINDS = [
|
|
417
444
|
"document",
|
|
418
445
|
"passage",
|
|
419
446
|
"highlight",
|
|
420
447
|
"conversation",
|
|
421
|
-
"equation"
|
|
448
|
+
"equation",
|
|
449
|
+
"note"
|
|
422
450
|
];
|
|
423
451
|
var EXPECTED_DOCUMENT_READ_FORMATS = [
|
|
424
452
|
"metadata",
|
|
@@ -440,6 +468,10 @@ var EXPECTED_CONVERSATION_READ_FORMATS = [
|
|
|
440
468
|
var EXPECTED_EQUATION_READ_FORMATS = [
|
|
441
469
|
"metadata"
|
|
442
470
|
];
|
|
471
|
+
var EXPECTED_NOTE_READ_FORMATS = [
|
|
472
|
+
"markdown",
|
|
473
|
+
"plain"
|
|
474
|
+
];
|
|
443
475
|
var DOCUMENT_READ_REQUEST_FORMATS = [
|
|
444
476
|
...EXPECTED_DOCUMENT_READ_FORMATS,
|
|
445
477
|
"auto"
|
|
@@ -506,6 +538,7 @@ var PASSAGE_PUBLIC_ID_PATTERN = /^pas_[a-f0-9]{32}$/u;
|
|
|
506
538
|
var HIGHLIGHT_PUBLIC_ID_PATTERN = /^hl_[a-f0-9]{32}$/u;
|
|
507
539
|
var CONVERSATION_PUBLIC_ID_PATTERN = /^cnv_[a-f0-9]{32}$/u;
|
|
508
540
|
var EQUATION_PUBLIC_ID_PATTERN = /^eq_[a-f0-9]{32}$/u;
|
|
541
|
+
var NOTE_PUBLIC_ID_PATTERN = /^nte_[a-f0-9]{32}$/u;
|
|
509
542
|
var SEARCH_RANKING_ID_PATTERN = /^srch_[a-f0-9]{32}$/u;
|
|
510
543
|
function isSearchRankingId(value) {
|
|
511
544
|
return SEARCH_RANKING_ID_PATTERN.test(value);
|
|
@@ -525,6 +558,9 @@ function isConversationPublicId(value) {
|
|
|
525
558
|
function isEquationPublicId(value) {
|
|
526
559
|
return EQUATION_PUBLIC_ID_PATTERN.test(value);
|
|
527
560
|
}
|
|
561
|
+
function isNotePublicId(value) {
|
|
562
|
+
return NOTE_PUBLIC_ID_PATTERN.test(value);
|
|
563
|
+
}
|
|
528
564
|
function publicReadKindForId(value) {
|
|
529
565
|
if (isDocumentPublicId(value)) {
|
|
530
566
|
return "document";
|
|
@@ -541,8 +577,22 @@ function publicReadKindForId(value) {
|
|
|
541
577
|
if (isEquationPublicId(value)) {
|
|
542
578
|
return "equation";
|
|
543
579
|
}
|
|
580
|
+
if (isNotePublicId(value)) {
|
|
581
|
+
return "note";
|
|
582
|
+
}
|
|
544
583
|
return null;
|
|
545
584
|
}
|
|
585
|
+
function readKindForIdentifier(value) {
|
|
586
|
+
const publicKind = publicReadKindForId(value);
|
|
587
|
+
if (publicKind) {
|
|
588
|
+
return publicKind;
|
|
589
|
+
}
|
|
590
|
+
const locatorKind = parsePapiersResourceLocator(value)?.readKind;
|
|
591
|
+
return locatorKind === "artifact" ? null : locatorKind ?? null;
|
|
592
|
+
}
|
|
593
|
+
function isDocumentReadIdentifier(value) {
|
|
594
|
+
return isDocumentPublicId(value) || parsePapiersResourceLocator(value)?.kind === "item";
|
|
595
|
+
}
|
|
546
596
|
function isPublicIdForKind(value, kind) {
|
|
547
597
|
return publicReadKindForId(value) === kind;
|
|
548
598
|
}
|
|
@@ -593,7 +643,8 @@ var PAPIERS_SEARCH_QUALITY_SIGNALS = [
|
|
|
593
643
|
];
|
|
594
644
|
var PAPIERS_SEARCH_RESULT_KINDS = [
|
|
595
645
|
"document",
|
|
596
|
-
"conversation"
|
|
646
|
+
"conversation",
|
|
647
|
+
"note"
|
|
597
648
|
];
|
|
598
649
|
var PAPIERS_SEARCH_EVIDENCE_KINDS = [
|
|
599
650
|
"passage",
|
|
@@ -608,7 +659,8 @@ var PAPIERS_SEARCH_MATCH_REASONS = [
|
|
|
608
659
|
"passage",
|
|
609
660
|
"highlight",
|
|
610
661
|
"equation",
|
|
611
|
-
"conversation"
|
|
662
|
+
"conversation",
|
|
663
|
+
"note"
|
|
612
664
|
];
|
|
613
665
|
var PAPIERS_PUBLIC_NOT_READY_REASONS_BY_FEATURE = {
|
|
614
666
|
document_content_read: ["explicit_enablement_required"],
|
|
@@ -651,6 +703,8 @@ var PAPIERS_PUBLIC_ERROR_CODES = [
|
|
|
651
703
|
"invalid_request",
|
|
652
704
|
"not_found",
|
|
653
705
|
"source_superseded",
|
|
706
|
+
"content_limit_exceeded",
|
|
707
|
+
"request_limit_exceeded",
|
|
654
708
|
"rate_limited",
|
|
655
709
|
"internal_error"
|
|
656
710
|
];
|
|
@@ -789,6 +843,7 @@ var RANKED_SEARCH_CURSOR_WARNING_MESSAGES = /* @__PURE__ */ new Set([
|
|
|
789
843
|
var DOCUMENT_READ_TRUNCATED_WARNING_CODE = "read_truncated";
|
|
790
844
|
var DOCUMENT_READ_TRUNCATED_WARNING_MESSAGE = "Document content was truncated by public read limits.";
|
|
791
845
|
var PASSAGE_READ_TRUNCATED_WARNING_MESSAGE = "Passage content was truncated by public read limits.";
|
|
846
|
+
var NOTE_READ_TRUNCATED_WARNING_MESSAGE = "Note content was truncated by public read limits.";
|
|
792
847
|
var READ_RESPONSE_KEYS = /* @__PURE__ */ new Set([
|
|
793
848
|
"schemaVersion",
|
|
794
849
|
"requestId",
|
|
@@ -858,6 +913,11 @@ var SEARCH_CONVERSATION_RESULT_KEYS = /* @__PURE__ */ new Set([
|
|
|
858
913
|
...SEARCH_RESULT_BASE_KEYS,
|
|
859
914
|
"snippet"
|
|
860
915
|
]);
|
|
916
|
+
var SEARCH_NOTE_RESULT_KEYS = /* @__PURE__ */ new Set([
|
|
917
|
+
...SEARCH_RESULT_BASE_KEYS,
|
|
918
|
+
"snippet",
|
|
919
|
+
"metadata"
|
|
920
|
+
]);
|
|
861
921
|
var SEARCH_EVIDENCE_KEYS = /* @__PURE__ */ new Set([
|
|
862
922
|
"kind",
|
|
863
923
|
"id",
|
|
@@ -910,6 +970,19 @@ var READ_SUCCESS_EQUATION_ITEM_KEYS = /* @__PURE__ */ new Set([
|
|
|
910
970
|
"format",
|
|
911
971
|
"metadata"
|
|
912
972
|
]);
|
|
973
|
+
var READ_SUCCESS_NOTE_ITEM_KEYS = /* @__PURE__ */ new Set([
|
|
974
|
+
"id",
|
|
975
|
+
"kind",
|
|
976
|
+
"ok",
|
|
977
|
+
"format",
|
|
978
|
+
"content",
|
|
979
|
+
"truncated",
|
|
980
|
+
"charCount",
|
|
981
|
+
"tokenEstimate",
|
|
982
|
+
"metadata",
|
|
983
|
+
"nextCursor",
|
|
984
|
+
"warnings"
|
|
985
|
+
]);
|
|
913
986
|
var READ_ERROR_DOCUMENT_ITEM_KEYS = /* @__PURE__ */ new Set(["id", "kind", "ok", "error"]);
|
|
914
987
|
var READ_ITEM_ERROR_KEYS = /* @__PURE__ */ new Set(["code", "message", "retryable"]);
|
|
915
988
|
var HIGHLIGHT_READ_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -919,6 +992,8 @@ var HIGHLIGHT_READ_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
|
919
992
|
"anchorType",
|
|
920
993
|
"annotationText",
|
|
921
994
|
"quoteContext",
|
|
995
|
+
"quotePrefix",
|
|
996
|
+
"quoteSuffix",
|
|
922
997
|
"createdAt",
|
|
923
998
|
"updatedAt"
|
|
924
999
|
]);
|
|
@@ -940,6 +1015,14 @@ var EQUATION_READ_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
|
940
1015
|
"nodeType",
|
|
941
1016
|
"updatedAt"
|
|
942
1017
|
]);
|
|
1018
|
+
var NOTE_READ_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
1019
|
+
"documentId",
|
|
1020
|
+
"attachedTitle",
|
|
1021
|
+
"editedAt",
|
|
1022
|
+
"createdAt",
|
|
1023
|
+
"updatedAt",
|
|
1024
|
+
"title"
|
|
1025
|
+
]);
|
|
943
1026
|
var READ_LOCATIONS_KEYS = /* @__PURE__ */ new Set(["pages", "scope", "truncated"]);
|
|
944
1027
|
var READ_LOCATION_PAGE_KEYS = /* @__PURE__ */ new Set(["page", "sections"]);
|
|
945
1028
|
var READ_LOCATION_SCOPE_KEYS = /* @__PURE__ */ new Set(["pages"]);
|
|
@@ -971,9 +1054,16 @@ var PASSAGE_READ_NOT_FOUND_MESSAGE = "Passage is not available.";
|
|
|
971
1054
|
var HIGHLIGHT_READ_NOT_FOUND_MESSAGE = "Highlight is not available.";
|
|
972
1055
|
var CONVERSATION_READ_NOT_FOUND_MESSAGE = "Conversation is not available.";
|
|
973
1056
|
var EQUATION_READ_NOT_FOUND_MESSAGE = "Equation is not available.";
|
|
1057
|
+
var NOTE_READ_NOT_FOUND_MESSAGE = "Note is not available.";
|
|
974
1058
|
var DOCUMENT_READ_SOURCE_SUPERSEDED_CODE = "source_superseded";
|
|
1059
|
+
var CONVERSATION_READ_CONTENT_LIMIT_CODE = "content_limit_exceeded";
|
|
1060
|
+
var CONVERSATION_READ_REQUEST_LIMIT_CODE = "request_limit_exceeded";
|
|
975
1061
|
var DOCUMENT_READ_SOURCE_SUPERSEDED_MESSAGE = "Document content is not available for the current source.";
|
|
1062
|
+
var NOTE_READ_SOURCE_SUPERSEDED_MESSAGE = "Note content changed since this cursor was issued.";
|
|
976
1063
|
var PASSAGE_READ_CONTENT_UNAVAILABLE_MESSAGE = "Passage content is not available.";
|
|
1064
|
+
var CONVERSATION_READ_SOURCE_SUPERSEDED_MESSAGE = "Conversation source is no longer available. Search again for a current result.";
|
|
1065
|
+
var CONVERSATION_READ_CONTENT_LIMIT_MESSAGE = "Conversation content exceeds the public read limit.";
|
|
1066
|
+
var CONVERSATION_READ_REQUEST_LIMIT_MESSAGE = "Conversation read batch is too large. Retry this item in a smaller batch.";
|
|
977
1067
|
var PUBLIC_CURSOR_BASE64URL_PATTERN = /^[A-Za-z0-9_-]{1,4096}$/u;
|
|
978
1068
|
var PUBLIC_CURSOR_SIGNATURE_PATTERN = /^[A-Za-z0-9_-]{43}$/u;
|
|
979
1069
|
var PUBLIC_CURSOR_HASH_PATTERN = /^[A-Za-z0-9_-]{43}$/u;
|
|
@@ -1033,6 +1123,8 @@ var INTERNAL_RESPONSE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1033
1123
|
"latexTokens",
|
|
1034
1124
|
"library_item_id",
|
|
1035
1125
|
"libraryItemId",
|
|
1126
|
+
"note_id",
|
|
1127
|
+
"noteId",
|
|
1036
1128
|
"actor_id",
|
|
1037
1129
|
"actorId",
|
|
1038
1130
|
"owner_user_id",
|
|
@@ -1056,7 +1148,7 @@ var INTERNAL_RESPONSE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1056
1148
|
"last_used_ip_hash",
|
|
1057
1149
|
"lastUsedIpHash"
|
|
1058
1150
|
]);
|
|
1059
|
-
var UNSAFE_PUBLIC_EXCERPT_MARKER_PATTERN = /\b(?:artifact_id|artifactId|astNodeId|atom_id|atomId|branchKey|contentHash|conversation_id|conversationId|current_artifact_id|currentArtifactId|current_internal_target_json|currentInternalTargetJson|internal_locator|internalLocator|latexTokens|library_item_id|libraryItemId|actor_id|actorId|owner_user_id|ownerUserId|secret_hash|secretHash|source_id|sourceId|source_url|sourceUrl|source_locator|sourceLocator|source_locator_hash|sourceLocatorHash|source_locator_json|sourceLocatorJson|projectionHash|search_row_id|searchRowId|last_used_ip_hash|lastUsedIpHash)\b/u;
|
|
1151
|
+
var UNSAFE_PUBLIC_EXCERPT_MARKER_PATTERN = /\b(?:artifact_id|artifactId|astNodeId|atom_id|atomId|branchKey|contentHash|conversation_id|conversationId|current_artifact_id|currentArtifactId|current_internal_target_json|currentInternalTargetJson|internal_locator|internalLocator|latexTokens|library_item_id|libraryItemId|note_id|noteId|actor_id|actorId|owner_user_id|ownerUserId|secret_hash|secretHash|source_id|sourceId|source_url|sourceUrl|source_locator|sourceLocator|source_locator_hash|sourceLocatorHash|source_locator_json|sourceLocatorJson|projectionHash|search_row_id|searchRowId|last_used_ip_hash|lastUsedIpHash)\b/u;
|
|
1060
1152
|
var UNSAFE_PUBLIC_EXCERPT_URL_PATTERN = /\bhttps?:\/\/\S+[?&](?:access_token|key|secret|sig|signature|token)=/iu;
|
|
1061
1153
|
var UNSAFE_PUBLIC_EXCERPT_SIGNED_URL_PATTERN = /\bsigned[_-]?url\b/iu;
|
|
1062
1154
|
var CLI_DOCUMENT_READ_FORMAT_SET = new Set(
|
|
@@ -1279,10 +1371,10 @@ function validatePapiersReadResponse(label, body, options = {}) {
|
|
|
1279
1371
|
const expectedInclude = options.expectedInclude ? new Set(options.expectedInclude) : void 0;
|
|
1280
1372
|
for (const [index, rawItem] of items.entries()) {
|
|
1281
1373
|
const item = assertRecord(`${label} item ${index}`, rawItem);
|
|
1282
|
-
const id =
|
|
1374
|
+
const id = assertReadIdentifier(`${label} item ${index} id`, item.id);
|
|
1283
1375
|
if (options.expectedIds !== void 0 && id !== options.expectedIds[index]) {
|
|
1284
1376
|
throw new PapiersCliResponseValidationError(
|
|
1285
|
-
`${label} did not echo the requested
|
|
1377
|
+
`${label} did not echo the requested identifiers in order.`
|
|
1286
1378
|
);
|
|
1287
1379
|
}
|
|
1288
1380
|
const kind = validateReadItemKind(
|
|
@@ -1388,10 +1480,16 @@ function validateSearchResults(label, results, options = {}) {
|
|
|
1388
1480
|
`${label} result ${index} kind was not one of the requested kinds.`
|
|
1389
1481
|
);
|
|
1390
1482
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1483
|
+
switch (kind) {
|
|
1484
|
+
case "document":
|
|
1485
|
+
validateSearchDocumentResult(`${label} result ${index}`, result);
|
|
1486
|
+
break;
|
|
1487
|
+
case "conversation":
|
|
1488
|
+
validateSearchConversationResult(`${label} result ${index}`, result);
|
|
1489
|
+
break;
|
|
1490
|
+
case "note":
|
|
1491
|
+
validateSearchNoteResult(`${label} result ${index}`, result);
|
|
1492
|
+
break;
|
|
1395
1493
|
}
|
|
1396
1494
|
}
|
|
1397
1495
|
return values.length;
|
|
@@ -1412,6 +1510,9 @@ function validateSearchResultKind(label, value, id) {
|
|
|
1412
1510
|
if (value === "conversation" && isPublicIdForKind(id, "conversation")) {
|
|
1413
1511
|
return "conversation";
|
|
1414
1512
|
}
|
|
1513
|
+
if (value === "note" && isPublicIdForKind(id, "note")) {
|
|
1514
|
+
return "note";
|
|
1515
|
+
}
|
|
1415
1516
|
throw new PapiersCliResponseValidationError(
|
|
1416
1517
|
`${label} did not match the public id kind.`
|
|
1417
1518
|
);
|
|
@@ -1465,6 +1566,23 @@ function validateSearchConversationResult(label, result) {
|
|
|
1465
1566
|
validateOptionalNullableString(`${label} title`, result.title);
|
|
1466
1567
|
validateOptionalPublicExcerpt(`${label} snippet`, result.snippet);
|
|
1467
1568
|
}
|
|
1569
|
+
function validateSearchNoteResult(label, result) {
|
|
1570
|
+
rejectUnexpectedKeys(label, result, SEARCH_NOTE_RESULT_KEYS);
|
|
1571
|
+
const id = assertNonEmptyString(`${label} id`, result.id);
|
|
1572
|
+
if (!isPublicIdForKind(id, "note")) {
|
|
1573
|
+
throw new PapiersCliResponseValidationError(
|
|
1574
|
+
`${label} id was not an nte_* public id.`
|
|
1575
|
+
);
|
|
1576
|
+
}
|
|
1577
|
+
assertPositiveInteger(`${label} rank`, result.rank);
|
|
1578
|
+
validateSearchScore(`${label} score`, result.score);
|
|
1579
|
+
validateSearchMatchedBy(`${label} matchedBy`, result.matchedBy, {
|
|
1580
|
+
allow: /* @__PURE__ */ new Set(["note"])
|
|
1581
|
+
});
|
|
1582
|
+
validateOptionalNullableString(`${label} title`, result.title);
|
|
1583
|
+
validateOptionalPublicExcerpt(`${label} snippet`, result.snippet);
|
|
1584
|
+
validateNoteMetadata(`${label} metadata`, result.metadata, assertDocId);
|
|
1585
|
+
}
|
|
1468
1586
|
function validateSearchEvidenceList(label, value) {
|
|
1469
1587
|
const evidence = assertArray(label, value);
|
|
1470
1588
|
for (const [index, rawEvidence] of evidence.entries()) {
|
|
@@ -1666,9 +1784,9 @@ function validateOptionalDocumentIdForKind(label, value, kind) {
|
|
|
1666
1784
|
}
|
|
1667
1785
|
return void 0;
|
|
1668
1786
|
}
|
|
1669
|
-
if (kind === "conversation") {
|
|
1787
|
+
if (kind === "conversation" || kind === "note") {
|
|
1670
1788
|
throw new PapiersCliResponseValidationError(
|
|
1671
|
-
`${label} was not supported for
|
|
1789
|
+
`${label} was not supported for ${kind} items.`
|
|
1672
1790
|
);
|
|
1673
1791
|
}
|
|
1674
1792
|
return assertDocId(label, value);
|
|
@@ -1692,12 +1810,15 @@ function validateOptionalListSearchMetadata(label, value, kind) {
|
|
|
1692
1810
|
return validatePassageListSearchMetadata(label, value);
|
|
1693
1811
|
}
|
|
1694
1812
|
if (kind === "highlight") {
|
|
1695
|
-
return
|
|
1813
|
+
return validateHighlightMetadata(label, value, assertDocId);
|
|
1696
1814
|
}
|
|
1697
1815
|
if (kind === "conversation") {
|
|
1698
1816
|
validateConversationReadMetadata(label, value);
|
|
1699
1817
|
return void 0;
|
|
1700
1818
|
}
|
|
1819
|
+
if (kind === "note") {
|
|
1820
|
+
return validateNoteMetadata(label, value, assertDocId);
|
|
1821
|
+
}
|
|
1701
1822
|
return validateEquationReadMetadata(label, value);
|
|
1702
1823
|
}
|
|
1703
1824
|
function validatePassageListSearchMetadata(label, value) {
|
|
@@ -1728,11 +1849,54 @@ function validateReadSuccessItem(label, item, kind, options) {
|
|
|
1728
1849
|
return validateConversationReadSuccessItem(label, item, options);
|
|
1729
1850
|
case "equation":
|
|
1730
1851
|
return validateEquationReadSuccessItem(label, item, options);
|
|
1852
|
+
case "note":
|
|
1853
|
+
return validateNoteReadSuccessItem(label, item, options);
|
|
1731
1854
|
}
|
|
1732
1855
|
}
|
|
1856
|
+
function validateNoteReadSuccessItem(label, item, options) {
|
|
1857
|
+
rejectUnexpectedKeys(label, item, READ_SUCCESS_NOTE_ITEM_KEYS);
|
|
1858
|
+
const itemFormat = validateCliReadFormat(`${label} format`, item.format);
|
|
1859
|
+
if (!EXPECTED_NOTE_READ_FORMATS.some((format) => format === itemFormat)) {
|
|
1860
|
+
throw new PapiersCliResponseValidationError(
|
|
1861
|
+
`${label} format was not supported for note reads.`
|
|
1862
|
+
);
|
|
1863
|
+
}
|
|
1864
|
+
if (options.expectedFormat !== void 0 && !isResolvedReadFormatAllowed(itemFormat, options.expectedFormat)) {
|
|
1865
|
+
throw new PapiersCliResponseValidationError(
|
|
1866
|
+
`${label} did not echo the requested read format.`
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1869
|
+
const contentResult = validateReadContent(label, item, itemFormat, {
|
|
1870
|
+
expectedMaxCharsPerItem: options.expectedMaxCharsPerItem
|
|
1871
|
+
});
|
|
1872
|
+
validateReadItemCursor(
|
|
1873
|
+
label,
|
|
1874
|
+
item.nextCursor,
|
|
1875
|
+
itemFormat,
|
|
1876
|
+
contentResult.truncated,
|
|
1877
|
+
options.singleItemRead
|
|
1878
|
+
);
|
|
1879
|
+
validateNoteMetadata(
|
|
1880
|
+
`${label} metadata`,
|
|
1881
|
+
item.metadata,
|
|
1882
|
+
assertDocumentReadIdentifier
|
|
1883
|
+
);
|
|
1884
|
+
const hasReadTruncatedWarning = validateOptionalReadWarnings(
|
|
1885
|
+
`${label} warnings`,
|
|
1886
|
+
item.warnings,
|
|
1887
|
+
itemFormat,
|
|
1888
|
+
"note"
|
|
1889
|
+
);
|
|
1890
|
+
if (hasReadTruncatedWarning && !contentResult.truncated) {
|
|
1891
|
+
throw new PapiersCliResponseValidationError(
|
|
1892
|
+
`${label} returned read_truncated without truncated=true.`
|
|
1893
|
+
);
|
|
1894
|
+
}
|
|
1895
|
+
return { ...contentResult, contentRead: true };
|
|
1896
|
+
}
|
|
1733
1897
|
function validateDocumentReadSuccessItem(label, item, options) {
|
|
1734
1898
|
rejectUnexpectedKeys(label, item, READ_SUCCESS_DOCUMENT_ITEM_KEYS);
|
|
1735
|
-
|
|
1899
|
+
assertDocumentReadIdentifier(`${label} id`, item.id);
|
|
1736
1900
|
const itemFormat = validateCliReadFormat(`${label} format`, item.format);
|
|
1737
1901
|
if (options.expectedFormat !== void 0 && !isResolvedReadFormatAllowed(itemFormat, options.expectedFormat)) {
|
|
1738
1902
|
throw new PapiersCliResponseValidationError(
|
|
@@ -1854,11 +2018,19 @@ function validateHighlightReadSuccessItem(label, item, options) {
|
|
|
1854
2018
|
}
|
|
1855
2019
|
if (itemFormat === "plain") {
|
|
1856
2020
|
const contentResult = validatePlainReadContentFields(label, item);
|
|
1857
|
-
|
|
2021
|
+
validateHighlightMetadata(
|
|
2022
|
+
`${label} metadata`,
|
|
2023
|
+
item.metadata,
|
|
2024
|
+
assertDocumentReadIdentifier
|
|
2025
|
+
);
|
|
1858
2026
|
return { ...contentResult, contentRead: true };
|
|
1859
2027
|
}
|
|
1860
2028
|
rejectMetadataOnlyContentFields(label, item);
|
|
1861
|
-
|
|
2029
|
+
validateHighlightMetadata(
|
|
2030
|
+
`${label} metadata`,
|
|
2031
|
+
item.metadata,
|
|
2032
|
+
assertDocumentReadIdentifier
|
|
2033
|
+
);
|
|
1862
2034
|
return { returnedChars: 0, truncated: false, contentRead: false };
|
|
1863
2035
|
}
|
|
1864
2036
|
function validateConversationReadSuccessItem(label, item, options) {
|
|
@@ -1900,18 +2072,21 @@ function validateEquationReadSuccessItem(label, item, options) {
|
|
|
1900
2072
|
return { returnedChars: 0, truncated: false, contentRead: false };
|
|
1901
2073
|
}
|
|
1902
2074
|
function validateReadItemKind(label, value, id) {
|
|
1903
|
-
const expectedKind =
|
|
1904
|
-
if (expectedKind === null || value !== expectedKind || value !== "document" && value !== "passage" && value !== "highlight" && value !== "conversation" && value !== "equation") {
|
|
2075
|
+
const expectedKind = readKindForIdentifier(id);
|
|
2076
|
+
if (expectedKind === null || value !== expectedKind || value !== "document" && value !== "passage" && value !== "highlight" && value !== "conversation" && value !== "equation" && value !== "note") {
|
|
1905
2077
|
throw new PapiersCliResponseValidationError(
|
|
1906
|
-
`${label} did not match the
|
|
2078
|
+
`${label} did not match the read identifier kind.`
|
|
1907
2079
|
);
|
|
1908
2080
|
}
|
|
1909
2081
|
return value;
|
|
1910
2082
|
}
|
|
1911
|
-
function
|
|
2083
|
+
function validateHighlightMetadata(label, value, validateDocumentId) {
|
|
1912
2084
|
const metadata = assertRecord(label, value);
|
|
1913
2085
|
rejectUnexpectedKeys(label, metadata, HIGHLIGHT_READ_METADATA_KEYS);
|
|
1914
|
-
const documentId =
|
|
2086
|
+
const documentId = validateDocumentId(
|
|
2087
|
+
`${label}.documentId`,
|
|
2088
|
+
metadata.documentId
|
|
2089
|
+
);
|
|
1915
2090
|
validateOptionalNullableString(
|
|
1916
2091
|
`${label}.documentTitle`,
|
|
1917
2092
|
metadata.documentTitle
|
|
@@ -1930,6 +2105,8 @@ function validateHighlightReadMetadata(label, value) {
|
|
|
1930
2105
|
`${label}.quoteContext`,
|
|
1931
2106
|
metadata.quoteContext
|
|
1932
2107
|
);
|
|
2108
|
+
validateOptionalNullableString(`${label}.quotePrefix`, metadata.quotePrefix);
|
|
2109
|
+
validateOptionalNullableString(`${label}.quoteSuffix`, metadata.quoteSuffix);
|
|
1933
2110
|
validateOptionalTimestamp(`${label}.createdAt`, metadata.createdAt);
|
|
1934
2111
|
validateOptionalTimestamp(`${label}.updatedAt`, metadata.updatedAt);
|
|
1935
2112
|
return documentId;
|
|
@@ -1961,6 +2138,21 @@ function validateEquationReadMetadata(label, value) {
|
|
|
1961
2138
|
validateOptionalTimestamp(`${label}.updatedAt`, metadata.updatedAt);
|
|
1962
2139
|
return documentId;
|
|
1963
2140
|
}
|
|
2141
|
+
function validateNoteMetadata(label, value, validateDocumentId) {
|
|
2142
|
+
const metadata = assertRecord(label, value);
|
|
2143
|
+
rejectUnexpectedKeys(label, metadata, NOTE_READ_METADATA_KEYS);
|
|
2144
|
+
const documentId = metadata.documentId === null ? void 0 : validateDocumentId(`${label}.documentId`, metadata.documentId);
|
|
2145
|
+
if (metadata.attachedTitle !== null && typeof metadata.attachedTitle !== "string") {
|
|
2146
|
+
throw new PapiersCliResponseValidationError(
|
|
2147
|
+
`${label}.attachedTitle was not a string or null.`
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
assertTimestampString(`${label}.editedAt`, metadata.editedAt);
|
|
2151
|
+
assertTimestampString(`${label}.createdAt`, metadata.createdAt);
|
|
2152
|
+
assertTimestampString(`${label}.updatedAt`, metadata.updatedAt);
|
|
2153
|
+
assertNonEmptyString(`${label}.title`, metadata.title);
|
|
2154
|
+
return documentId;
|
|
2155
|
+
}
|
|
1964
2156
|
function rejectUnexpectedContent(label, item) {
|
|
1965
2157
|
if (item.content !== void 0 && item.content !== null) {
|
|
1966
2158
|
throw new PapiersCliResponseValidationError(
|
|
@@ -2188,19 +2380,20 @@ function validateReadUsage(label, rawUsage, options) {
|
|
|
2188
2380
|
function validateReadItemError(label, value, kind, expectedFormat) {
|
|
2189
2381
|
const error = assertRecord(label, value);
|
|
2190
2382
|
rejectUnexpectedKeys(label, error, READ_ITEM_ERROR_KEYS);
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2383
|
+
const sourceSupersededAllowed = error.code === DOCUMENT_READ_SOURCE_SUPERSEDED_CODE && (kind === "document" || kind === "passage" || kind === "note" || kind === "conversation");
|
|
2384
|
+
const contentLimitAllowed = error.code === CONVERSATION_READ_CONTENT_LIMIT_CODE && kind === "conversation";
|
|
2385
|
+
const requestLimitAllowed = error.code === CONVERSATION_READ_REQUEST_LIMIT_CODE && kind === "conversation";
|
|
2386
|
+
if (error.code !== DOCUMENT_READ_NOT_FOUND_CODE && !sourceSupersededAllowed && !contentLimitAllowed && !requestLimitAllowed) {
|
|
2387
|
+
throw new PapiersCliResponseValidationError(
|
|
2388
|
+
`${label}.code was not a supported read error code.`
|
|
2389
|
+
);
|
|
2197
2390
|
}
|
|
2198
|
-
if (expectedFormat === "metadata" && error.code === DOCUMENT_READ_SOURCE_SUPERSEDED_CODE) {
|
|
2391
|
+
if (expectedFormat === "metadata" && (error.code === DOCUMENT_READ_SOURCE_SUPERSEDED_CODE || error.code === CONVERSATION_READ_CONTENT_LIMIT_CODE || error.code === CONVERSATION_READ_REQUEST_LIMIT_CODE)) {
|
|
2199
2392
|
throw new PapiersCliResponseValidationError(
|
|
2200
2393
|
`${label}.code was not supported for metadata reads.`
|
|
2201
2394
|
);
|
|
2202
2395
|
}
|
|
2203
|
-
const expectedMessage = error.code === DOCUMENT_READ_NOT_FOUND_CODE ? readNotFoundMessageForKind(kind) : kind === "passage" ? PASSAGE_READ_CONTENT_UNAVAILABLE_MESSAGE : DOCUMENT_READ_SOURCE_SUPERSEDED_MESSAGE;
|
|
2396
|
+
const expectedMessage = error.code === DOCUMENT_READ_NOT_FOUND_CODE ? readNotFoundMessageForKind(kind) : error.code === CONVERSATION_READ_CONTENT_LIMIT_CODE ? CONVERSATION_READ_CONTENT_LIMIT_MESSAGE : error.code === CONVERSATION_READ_REQUEST_LIMIT_CODE ? CONVERSATION_READ_REQUEST_LIMIT_MESSAGE : kind === "conversation" ? CONVERSATION_READ_SOURCE_SUPERSEDED_MESSAGE : kind === "passage" ? PASSAGE_READ_CONTENT_UNAVAILABLE_MESSAGE : kind === "note" ? NOTE_READ_SOURCE_SUPERSEDED_MESSAGE : DOCUMENT_READ_SOURCE_SUPERSEDED_MESSAGE;
|
|
2204
2397
|
if (error.message !== expectedMessage) {
|
|
2205
2398
|
throw new PapiersCliResponseValidationError(
|
|
2206
2399
|
`${label}.message was not a supported read error message.`
|
|
@@ -2225,6 +2418,8 @@ function readNotFoundMessageForKind(kind) {
|
|
|
2225
2418
|
return CONVERSATION_READ_NOT_FOUND_MESSAGE;
|
|
2226
2419
|
case "equation":
|
|
2227
2420
|
return EQUATION_READ_NOT_FOUND_MESSAGE;
|
|
2421
|
+
case "note":
|
|
2422
|
+
return NOTE_READ_NOT_FOUND_MESSAGE;
|
|
2228
2423
|
}
|
|
2229
2424
|
}
|
|
2230
2425
|
function validateOptionalSearchQuality(label, value) {
|
|
@@ -2289,7 +2484,7 @@ function validateOptionalReadWarnings(label, value, format, kind) {
|
|
|
2289
2484
|
);
|
|
2290
2485
|
}
|
|
2291
2486
|
hasReadTruncatedWarning = true;
|
|
2292
|
-
const expectedMessage = kind === "document" ? DOCUMENT_READ_TRUNCATED_WARNING_MESSAGE : PASSAGE_READ_TRUNCATED_WARNING_MESSAGE;
|
|
2487
|
+
const expectedMessage = kind === "document" ? DOCUMENT_READ_TRUNCATED_WARNING_MESSAGE : kind === "passage" ? PASSAGE_READ_TRUNCATED_WARNING_MESSAGE : NOTE_READ_TRUNCATED_WARNING_MESSAGE;
|
|
2293
2488
|
if (warning.message !== expectedMessage) {
|
|
2294
2489
|
throw new PapiersCliResponseValidationError(
|
|
2295
2490
|
`${label} ${index}.message was not a supported warning message.`
|
|
@@ -2709,10 +2904,18 @@ function assertDocId(label, value) {
|
|
|
2709
2904
|
}
|
|
2710
2905
|
return value;
|
|
2711
2906
|
}
|
|
2712
|
-
function
|
|
2713
|
-
if (typeof value !== "string" ||
|
|
2907
|
+
function assertDocumentReadIdentifier(label, value) {
|
|
2908
|
+
if (typeof value !== "string" || !isDocumentReadIdentifier(value)) {
|
|
2714
2909
|
throw new PapiersCliResponseValidationError(
|
|
2715
|
-
`${label} was not a
|
|
2910
|
+
`${label} was not a doc_* public id or papiers://item locator.`
|
|
2911
|
+
);
|
|
2912
|
+
}
|
|
2913
|
+
return value;
|
|
2914
|
+
}
|
|
2915
|
+
function assertReadIdentifier(label, value) {
|
|
2916
|
+
if (typeof value !== "string" || readKindForIdentifier(value) === null) {
|
|
2917
|
+
throw new PapiersCliResponseValidationError(
|
|
2918
|
+
`${label} was not a supported read identifier.`
|
|
2716
2919
|
);
|
|
2717
2920
|
}
|
|
2718
2921
|
return value;
|
|
@@ -2856,7 +3059,7 @@ async function readDocuments(config, fetchImpl, request) {
|
|
|
2856
3059
|
"/api/v1/papiers/read",
|
|
2857
3060
|
{ method: "POST", body: request, retryable: true }
|
|
2858
3061
|
);
|
|
2859
|
-
const readKind =
|
|
3062
|
+
const readKind = readKindForIdentifier(request.ids[0] ?? "");
|
|
2860
3063
|
assertPapiersReadResponse("read", body, request.ids, {
|
|
2861
3064
|
// Every kind resolves an omitted format server-side (auto semantics),
|
|
2862
3065
|
// so there is nothing to echo-check unless the caller pinned one;
|
|
@@ -2903,7 +3106,7 @@ function expectedKindForListSearchRequest(request) {
|
|
|
2903
3106
|
function expectedKindsForSearchRequest(request) {
|
|
2904
3107
|
const kinds = request.kinds;
|
|
2905
3108
|
if (kinds === void 0) {
|
|
2906
|
-
return { expectedKinds: /* @__PURE__ */ new Set(["document", "conversation"]) };
|
|
3109
|
+
return { expectedKinds: /* @__PURE__ */ new Set(["document", "conversation", "note"]) };
|
|
2907
3110
|
}
|
|
2908
3111
|
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
2909
3112
|
throw new CliUsageError(
|
|
@@ -2923,11 +3126,14 @@ function expectedKindsForSearchRequest(request) {
|
|
|
2923
3126
|
);
|
|
2924
3127
|
}
|
|
2925
3128
|
}
|
|
2926
|
-
const
|
|
2927
|
-
|
|
2928
|
-
|
|
3129
|
+
const expectedKinds = /* @__PURE__ */ new Set();
|
|
3130
|
+
for (const kind of rawKinds) {
|
|
3131
|
+
expectedKinds.add(
|
|
3132
|
+
kind === "conversation" || kind === "note" ? kind : "document"
|
|
3133
|
+
);
|
|
2929
3134
|
}
|
|
2930
|
-
|
|
3135
|
+
const [onlyKind] = expectedKinds;
|
|
3136
|
+
return expectedKinds.size === 1 ? { expectedKind: onlyKind } : { expectedKinds };
|
|
2931
3137
|
}
|
|
2932
3138
|
async function requestPapiersApi(config, fetchImpl, path, init) {
|
|
2933
3139
|
if (!config.token) {
|
|
@@ -3598,16 +3804,18 @@ var FORMER_KIND_ALIASES = /* @__PURE__ */ new Map([
|
|
|
3598
3804
|
["chat", "conversation"],
|
|
3599
3805
|
["chats", "conversation"],
|
|
3600
3806
|
["conversations", "conversation"],
|
|
3601
|
-
["equations", "equation"]
|
|
3807
|
+
["equations", "equation"],
|
|
3808
|
+
["notes", "note"]
|
|
3602
3809
|
]);
|
|
3603
3810
|
var MULTI_SEARCH_KINDS = [
|
|
3604
3811
|
"passage",
|
|
3605
3812
|
"highlight",
|
|
3606
3813
|
"conversation",
|
|
3607
|
-
"equation"
|
|
3814
|
+
"equation",
|
|
3815
|
+
"note"
|
|
3608
3816
|
];
|
|
3609
3817
|
var GLOBAL_HELP = `Papiers CLI: search and read your library from the terminal.
|
|
3610
|
-
Your saved papers, highlights, and conversations (your chats) \u2014 for you or an AI agent.
|
|
3818
|
+
Your saved papers, highlights, notes, and conversations (your chats) \u2014 for you or an AI agent.
|
|
3611
3819
|
|
|
3612
3820
|
GETTING STARTED
|
|
3613
3821
|
papiers auth login Sign in with a token from Papiers (Settings -> API tokens)
|
|
@@ -3616,8 +3824,8 @@ GETTING STARTED
|
|
|
3616
3824
|
|
|
3617
3825
|
COMMANDS
|
|
3618
3826
|
search Search across your library
|
|
3619
|
-
list List your documents, highlights, and conversations
|
|
3620
|
-
read Print a document, highlight, or conversation
|
|
3827
|
+
list List your documents, highlights, notes, and conversations
|
|
3828
|
+
read Print a document, highlight, note, or conversation
|
|
3621
3829
|
browse Page through an earlier search's results
|
|
3622
3830
|
auth Sign in, check status, or sign out
|
|
3623
3831
|
tokens List or revoke your API tokens
|
|
@@ -3654,8 +3862,8 @@ USAGE
|
|
|
3654
3862
|
|
|
3655
3863
|
OPTIONS
|
|
3656
3864
|
--kind KIND what to search. Defaults to all \u2014 your passages, highlights,
|
|
3657
|
-
equations, conversations, and matching titles. Or focus on one:
|
|
3658
|
-
passage \xB7 highlight \xB7 conversation \xB7 equation.
|
|
3865
|
+
equations, notes, conversations, and matching titles. Or focus on one:
|
|
3866
|
+
passage \xB7 highlight \xB7 conversation \xB7 equation \xB7 note.
|
|
3659
3867
|
--filter FIELD.OP=VALUE narrow parent documents \u2014 repeatable, up to 25.
|
|
3660
3868
|
e.g. --filter publishedYear.gte=2020 --filter author.contains=hinton. Fields/ops: help --all.
|
|
3661
3869
|
--document-id ID scope to documents: doc_\u2026 (comma-separated or repeated), or @-/@file.
|
|
@@ -3670,7 +3878,7 @@ EXAMPLES
|
|
|
3670
3878
|
papiers search retrieval --kind passage --limit 5 --passage-ids | papiers read @- --format plain --json
|
|
3671
3879
|
|
|
3672
3880
|
When capabilities.searchResultsBrowse.enabled is true, a search may return ranking.searchId \u2014 pass it to \`papiers browse\` for more pages.`,
|
|
3673
|
-
list: `papiers list \u2014 list your documents, highlights, and conversations.
|
|
3881
|
+
list: `papiers list \u2014 list your documents, highlights, notes, and conversations.
|
|
3674
3882
|
|
|
3675
3883
|
USAGE
|
|
3676
3884
|
papiers list [--kind KIND] [--limit N] [--cursor CURSOR] [--pretty|--json|--ids|--ids0|--doc-ids]
|
|
@@ -3678,7 +3886,7 @@ USAGE
|
|
|
3678
3886
|
papiers list --kind highlight|conversation [--since WHEN]
|
|
3679
3887
|
|
|
3680
3888
|
OPTIONS
|
|
3681
|
-
--kind KIND document (default) \xB7 passage \xB7 highlight \xB7 conversation \xB7 equation.
|
|
3889
|
+
--kind KIND document (default) \xB7 passage \xB7 highlight \xB7 conversation \xB7 equation \xB7 note.
|
|
3682
3890
|
--filter FIELD.OP=VALUE narrow document results \u2014 repeatable, up to 25. document kind only.
|
|
3683
3891
|
e.g. --filter lastEngagedAt.gte=30d --filter annotated=true. Fields/ops: help --all.
|
|
3684
3892
|
--order-by KEY addedAt:desc (default) or lastEngagedAt:desc. document kind only.
|
|
@@ -3695,29 +3903,32 @@ EXAMPLES
|
|
|
3695
3903
|
papiers list --kind highlight --since 30d --pretty
|
|
3696
3904
|
papiers list --kind document --filter lastEngagedAt.gte=30d --json
|
|
3697
3905
|
papiers list --kind document --filter annotated=true --json`,
|
|
3698
|
-
read: `papiers read \u2014 print documents, highlights, conversations, passages, or equations.
|
|
3906
|
+
read: `papiers read \u2014 print documents, highlights, notes, conversations, passages, or equations.
|
|
3699
3907
|
|
|
3700
3908
|
USAGE
|
|
3701
3909
|
papiers read ID [ID ...] [--format FORMAT] [--max-chars-per-item N] [--fail-fast] [--json|--pretty]
|
|
3702
3910
|
papiers read @- | @file [--input0] [--format FORMAT] [--max-chars-per-item N] [--json|--pretty]
|
|
3703
|
-
|
|
3911
|
+
Read public IDs or papiers://note|highlight|item|conversation/<uuid> locators; don't mix resource kinds.
|
|
3704
3912
|
|
|
3705
3913
|
OPTIONS
|
|
3706
3914
|
--format FORMAT how to render each item. Default auto (equation defaults to metadata).
|
|
3707
3915
|
document: auto|metadata|markdown|plain. passage: markdown|plain.
|
|
3708
|
-
highlight, conversation: metadata|plain.
|
|
3916
|
+
highlight, conversation: metadata|plain. note: markdown|plain.
|
|
3917
|
+
equation: metadata.
|
|
3709
3918
|
--include SECTION extra sections, comma-separated: metadata, source, locations.
|
|
3710
|
-
document only (highlight/conversation/equation: metadata only; passage: none).
|
|
3919
|
+
document only (highlight/conversation/equation/note: metadata only; passage: none).
|
|
3711
3920
|
--pages RANGE restrict a document read to pages, e.g. 1,3-5. document only.
|
|
3712
3921
|
--max-chars-per-item N truncate each item's content to N chars, 1\u2013200000.
|
|
3713
|
-
--cursor CURSOR continue one long document \u2014 use items[].nextCursor from the
|
|
3714
|
-
response. One literal
|
|
3922
|
+
--cursor CURSOR continue one long document or note \u2014 use items[].nextCursor from the
|
|
3923
|
+
previous response. One literal document or note identifier only, with
|
|
3924
|
+
--format auto, markdown, or plain.
|
|
3715
3925
|
--fail-fast exit non-zero if any item fails (default: succeed if at least one does).
|
|
3716
3926
|
--json machine-readable JSON (the default)
|
|
3717
3927
|
--pretty human-readable text
|
|
3718
3928
|
|
|
3719
3929
|
EXAMPLES
|
|
3720
3930
|
papiers read doc_<id> --format markdown --max-chars-per-item 2000 --json
|
|
3931
|
+
papiers read nte_<id> --format markdown --json
|
|
3721
3932
|
papiers read hl_<id> --json
|
|
3722
3933
|
papiers search retrieval --doc-ids | papiers read @- --format metadata --json`,
|
|
3723
3934
|
browse: `papiers browse \u2014 page deeper into an earlier search's results.
|
|
@@ -3771,21 +3982,27 @@ var REFERENCE = `REFERENCE \u2014 IDs, piping, pagination, and limits.
|
|
|
3771
3982
|
|
|
3772
3983
|
ID PREFIXES
|
|
3773
3984
|
doc_ document pas_ passage hl_ highlight
|
|
3774
|
-
cnv_ conversation eq_ equation
|
|
3985
|
+
cnv_ conversation eq_ equation nte_ note
|
|
3986
|
+
srch_ a saved search ranking (for browse)
|
|
3775
3987
|
On read, the kind \u2014 and which --format/--include apply \u2014 is read from the prefix.
|
|
3776
3988
|
|
|
3989
|
+
RESOURCE LOCATORS
|
|
3990
|
+
papiers://note/<uuid> papiers://highlight/<uuid>
|
|
3991
|
+
papiers://item/<uuid> papiers://conversation/<uuid>
|
|
3992
|
+
Locators are accepted by read and resolved with the same ownership checks as public IDs.
|
|
3993
|
+
|
|
3777
3994
|
PIPING IDS BETWEEN COMMANDS
|
|
3778
3995
|
--ids result IDs, one per line, with their native prefix
|
|
3779
3996
|
--ids0 the same IDs, NUL-separated (for \`xargs -0\`)
|
|
3780
3997
|
--doc-ids parent document IDs only (doc_\u2026), deduped; conversation hits are skipped
|
|
3781
|
-
@- read
|
|
3782
|
-
--input0 read piped
|
|
3783
|
-
@- and @file accept
|
|
3998
|
+
@- read identifiers from stdin @file read identifiers from a file
|
|
3999
|
+
--input0 read piped identifiers NUL-separated instead of whitespace/newlines
|
|
4000
|
+
@- and @file accept IDs, resource locators, or a Papiers JSON envelope, and may be mixed with literals.
|
|
3784
4001
|
|
|
3785
4002
|
PAGINATION \u2014 three separate mechanisms
|
|
3786
4003
|
list response has page.nextCursor \u2192 papiers list \u2026 --cursor CURSOR
|
|
3787
4004
|
search response has ranking.searchId \u2192 papiers browse srch_\u2026 --offset N
|
|
3788
|
-
read a truncated item has items[].nextCursor \u2192 papiers read
|
|
4005
|
+
read a truncated item has items[].nextCursor \u2192 papiers read NOTE_OR_DOCUMENT --cursor CURSOR
|
|
3789
4006
|
|
|
3790
4007
|
LIMITS
|
|
3791
4008
|
--limit 1\u201350 \xB7 --max-chars-per-item 1\u2013200000 \xB7 up to 25 filters \xB7 up to 100 IDs per request
|
|
@@ -4085,7 +4302,7 @@ function buildReadRequest(parsed) {
|
|
|
4085
4302
|
const ids = orderedReadIdValues(parsed);
|
|
4086
4303
|
if (ids.length === 0) {
|
|
4087
4304
|
throw new CliUsageError(
|
|
4088
|
-
"papiers read requires at least one
|
|
4305
|
+
"papiers read requires at least one public ID or papiers:// resource locator."
|
|
4089
4306
|
);
|
|
4090
4307
|
}
|
|
4091
4308
|
if (ids.filter((id) => id === "@-").length > 1) {
|
|
@@ -4099,7 +4316,7 @@ function buildReadRequest(parsed) {
|
|
|
4099
4316
|
const literalKinds = readKindsForLiteralIds(ids);
|
|
4100
4317
|
if (literalKinds.length > 1) {
|
|
4101
4318
|
throw new CliUsageError(
|
|
4102
|
-
"papiers read
|
|
4319
|
+
"papiers read identifiers must all use the same resource kind."
|
|
4103
4320
|
);
|
|
4104
4321
|
}
|
|
4105
4322
|
const inferredKind = literalKinds[0] ?? requestedKind ?? "document";
|
|
@@ -4115,9 +4332,9 @@ function buildReadRequest(parsed) {
|
|
|
4115
4332
|
}
|
|
4116
4333
|
const format = parseReadFormat(parsed, inferredKind);
|
|
4117
4334
|
const cursor = singleFlagValue(parsed, "cursor");
|
|
4118
|
-
if (cursor !== void 0 && (inferredKind !== "document" || ids.length !== 1 || ids.some((id) => isDocumentIdSource(id)) ||
|
|
4335
|
+
if (cursor !== void 0 && (inferredKind !== "document" && inferredKind !== "note" || ids.length !== 1 || ids.some((id) => isDocumentIdSource(id)) || readKindForIdentifier(ids[0]) !== inferredKind)) {
|
|
4119
4336
|
throw new CliUsageError(
|
|
4120
|
-
"papiers read --cursor requires exactly one literal
|
|
4337
|
+
"papiers read --cursor requires exactly one literal document or note identifier."
|
|
4121
4338
|
);
|
|
4122
4339
|
}
|
|
4123
4340
|
if (cursor !== void 0 && format !== "auto" && !DOCUMENT_CONTENT_READ_FORMATS.some((supported) => supported === format)) {
|
|
@@ -4237,7 +4454,7 @@ function parseSearchKindScopes(parsed) {
|
|
|
4237
4454
|
const kind = normalizeCliPublicKind(rawKind);
|
|
4238
4455
|
if (!kind) {
|
|
4239
4456
|
throw new CliUsageError(
|
|
4240
|
-
`papiers search supports --kind passage, highlight, conversation, or
|
|
4457
|
+
`papiers search supports --kind passage, highlight, conversation, equation, or note; received "${rawKind}".${didYouMeanKind(rawKind)}`
|
|
4241
4458
|
);
|
|
4242
4459
|
}
|
|
4243
4460
|
if (kind === "document") {
|
|
@@ -4247,7 +4464,7 @@ function parseSearchKindScopes(parsed) {
|
|
|
4247
4464
|
}
|
|
4248
4465
|
if (!MULTI_SEARCH_KINDS.includes(kind)) {
|
|
4249
4466
|
throw new CliUsageError(
|
|
4250
|
-
`papiers search supports --kind passage, highlight, conversation, or
|
|
4467
|
+
`papiers search supports --kind passage, highlight, conversation, equation, or note; received "${rawKind}".`
|
|
4251
4468
|
);
|
|
4252
4469
|
}
|
|
4253
4470
|
kinds.push(kind);
|
|
@@ -4327,7 +4544,7 @@ function parseReadKind(parsed) {
|
|
|
4327
4544
|
return normalized;
|
|
4328
4545
|
}
|
|
4329
4546
|
throw new CliUsageError(
|
|
4330
|
-
`Public CLI read currently supports --kind document, passage, highlight, conversation, or
|
|
4547
|
+
`Public CLI read currently supports --kind document, passage, highlight, conversation, equation, or note only; received "${kind}".${didYouMeanKind(kind)}`
|
|
4331
4548
|
);
|
|
4332
4549
|
}
|
|
4333
4550
|
function readKindsForLiteralIds(ids) {
|
|
@@ -4336,10 +4553,10 @@ function readKindsForLiteralIds(ids) {
|
|
|
4336
4553
|
if (isDocumentIdSource(id)) {
|
|
4337
4554
|
continue;
|
|
4338
4555
|
}
|
|
4339
|
-
const kind =
|
|
4556
|
+
const kind = readKindForIdentifier(id);
|
|
4340
4557
|
if (!kind) {
|
|
4341
4558
|
throw new CliUsageError(
|
|
4342
|
-
"papiers read
|
|
4559
|
+
"papiers read accepts public IDs or papiers://note, highlight, item, and conversation locators."
|
|
4343
4560
|
);
|
|
4344
4561
|
}
|
|
4345
4562
|
kinds.add(kind);
|
|
@@ -4447,6 +4664,21 @@ function validateReadOptionsForKind(parsed, kind, format) {
|
|
|
4447
4664
|
});
|
|
4448
4665
|
return;
|
|
4449
4666
|
}
|
|
4667
|
+
if (kind === "note") {
|
|
4668
|
+
if (format !== "auto" && !EXPECTED_NOTE_READ_FORMATS.some((supported) => supported === format)) {
|
|
4669
|
+
throw new CliUsageError(
|
|
4670
|
+
"Public note read supports --format markdown, plain, or auto."
|
|
4671
|
+
);
|
|
4672
|
+
}
|
|
4673
|
+
const includes = parseReadInclude(parsed);
|
|
4674
|
+
if (includes?.some((include) => include !== "metadata")) {
|
|
4675
|
+
throw new CliUsageError(
|
|
4676
|
+
"Public note read supports only --include metadata."
|
|
4677
|
+
);
|
|
4678
|
+
}
|
|
4679
|
+
rejectReadFlagsForKind(parsed, kind, ["pages"]);
|
|
4680
|
+
return;
|
|
4681
|
+
}
|
|
4450
4682
|
validateMetadataReadOptionsForKind(parsed, kind, format, {
|
|
4451
4683
|
supportedFormats: EXPECTED_EQUATION_READ_FORMATS
|
|
4452
4684
|
});
|
|
@@ -4614,7 +4846,7 @@ function parseListSearchKind(parsed, command) {
|
|
|
4614
4846
|
);
|
|
4615
4847
|
}
|
|
4616
4848
|
throw new CliUsageError(
|
|
4617
|
-
`papiers ${command} supports --kind document, passage, highlight, conversation, or
|
|
4849
|
+
`papiers ${command} supports --kind document, passage, highlight, conversation, equation, or note; received "${kind}".${didYouMeanKind(kind)}`
|
|
4618
4850
|
);
|
|
4619
4851
|
}
|
|
4620
4852
|
function normalizeCliPublicKind(value) {
|
|
@@ -4921,6 +5153,13 @@ function assertSupportedDocumentCapabilities(value) {
|
|
|
4921
5153
|
EXPECTED_EQUATION_READ_FORMATS
|
|
4922
5154
|
);
|
|
4923
5155
|
continue;
|
|
5156
|
+
case "note":
|
|
5157
|
+
assertOptionalReadFormats(
|
|
5158
|
+
`capabilities readFormatsByKind.${kind}`,
|
|
5159
|
+
actualFormats,
|
|
5160
|
+
EXPECTED_NOTE_READ_FORMATS
|
|
5161
|
+
);
|
|
5162
|
+
continue;
|
|
4924
5163
|
default:
|
|
4925
5164
|
assertSameStringSet(
|
|
4926
5165
|
`capabilities readFormatsByKind.${kind}`,
|
|
@@ -5661,16 +5900,13 @@ async function runAuthLogin(params) {
|
|
|
5661
5900
|
}
|
|
5662
5901
|
assertSafeBearerApiBaseUrl(params.config.apiBaseUrl);
|
|
5663
5902
|
const token = await loginWithPatStdin(params);
|
|
5664
|
-
const validationConfig = cliConfigWithToken(
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5903
|
+
const validationConfig = cliConfigWithToken(params.config, token, "stdin");
|
|
5904
|
+
const capabilities = await getCapabilities(
|
|
5905
|
+
validationConfig,
|
|
5906
|
+
params.fetchImpl
|
|
5668
5907
|
);
|
|
5669
|
-
let capabilities;
|
|
5670
|
-
capabilities = await getCapabilities(validationConfig, params.fetchImpl);
|
|
5671
5908
|
assertCliSupportedCapabilities(capabilities);
|
|
5672
|
-
|
|
5673
|
-
update = writeLocalAuthToken({
|
|
5909
|
+
const update = writeLocalAuthToken({
|
|
5674
5910
|
root: params.envRoot,
|
|
5675
5911
|
token,
|
|
5676
5912
|
apiBaseUrl: params.config.apiBaseUrl
|
|
@@ -6085,7 +6321,8 @@ function writeParentDocumentIds(stdout, items) {
|
|
|
6085
6321
|
const seen = /* @__PURE__ */ new Set();
|
|
6086
6322
|
const ids = [];
|
|
6087
6323
|
for (const item of items) {
|
|
6088
|
-
const
|
|
6324
|
+
const metadataDocumentId = item.kind === "note" && typeof item.metadata === "object" && item.metadata !== null && !Array.isArray(item.metadata) ? item.metadata.documentId : void 0;
|
|
6325
|
+
const docId = item.kind === "document" ? item.id : item.documentId ?? metadataDocumentId;
|
|
6089
6326
|
if (typeof docId !== "string" || !docId) {
|
|
6090
6327
|
continue;
|
|
6091
6328
|
}
|
|
@@ -6348,23 +6585,23 @@ function validateReadIds(ids, context, sourceLabel) {
|
|
|
6348
6585
|
}
|
|
6349
6586
|
const kinds = /* @__PURE__ */ new Set();
|
|
6350
6587
|
for (const [index, id] of ids.entries()) {
|
|
6351
|
-
const kind =
|
|
6588
|
+
const kind = readKindForIdentifier(id);
|
|
6352
6589
|
if (!kind) {
|
|
6353
6590
|
throw new CliUsageError(
|
|
6354
|
-
`${context} ${sourceLabel} item ${index + 1} was not a
|
|
6591
|
+
`${context} ${sourceLabel} item ${index + 1} was not a public ID or papiers:// resource locator.`
|
|
6355
6592
|
);
|
|
6356
6593
|
}
|
|
6357
6594
|
kinds.add(kind);
|
|
6358
6595
|
}
|
|
6359
6596
|
if (kinds.size > 1) {
|
|
6360
6597
|
throw new CliUsageError(
|
|
6361
|
-
`${context} ${sourceLabel}
|
|
6598
|
+
`${context} ${sourceLabel} identifiers must all use the same resource kind.`
|
|
6362
6599
|
);
|
|
6363
6600
|
}
|
|
6364
6601
|
return ids;
|
|
6365
6602
|
}
|
|
6366
6603
|
function validateExpandedReadRequest(request, ids, requestedReadKind) {
|
|
6367
|
-
const kind =
|
|
6604
|
+
const kind = readKindForIdentifier(ids[0] ?? "");
|
|
6368
6605
|
if (requestedReadKind && kind && requestedReadKind !== kind) {
|
|
6369
6606
|
throw new CliUsageError(
|
|
6370
6607
|
`papiers read --kind ${requestedReadKind} does not match ${kind} IDs.`
|
|
@@ -6395,6 +6632,25 @@ function validateExpandedReadRequest(request, ids, requestedReadKind) {
|
|
|
6395
6632
|
}
|
|
6396
6633
|
if (kind === "equation") {
|
|
6397
6634
|
validateMetadataOnlyReadRequest(request, kind);
|
|
6635
|
+
return;
|
|
6636
|
+
}
|
|
6637
|
+
if (kind === "note") {
|
|
6638
|
+
validateNoteReadRequest(request);
|
|
6639
|
+
}
|
|
6640
|
+
}
|
|
6641
|
+
function validateNoteReadRequest(request) {
|
|
6642
|
+
if (request.format !== void 0 && request.format !== "auto" && request.format !== "markdown" && request.format !== "plain") {
|
|
6643
|
+
throw new CliUsageError(
|
|
6644
|
+
"Public note read supports --format markdown, plain, or auto."
|
|
6645
|
+
);
|
|
6646
|
+
}
|
|
6647
|
+
if (request.include?.some((include) => include !== "metadata")) {
|
|
6648
|
+
throw new CliUsageError(
|
|
6649
|
+
"Public note read supports only --include metadata."
|
|
6650
|
+
);
|
|
6651
|
+
}
|
|
6652
|
+
if (request.scope?.pages || request.scope?.sectionId) {
|
|
6653
|
+
throw new CliUsageError("Public note read does not support --pages.");
|
|
6398
6654
|
}
|
|
6399
6655
|
}
|
|
6400
6656
|
function validateContentCapableReadRequest(request, kind) {
|
|
@@ -6501,10 +6757,10 @@ function parseJsonEnvelopeIds(input, context, sourceLabel) {
|
|
|
6501
6757
|
);
|
|
6502
6758
|
}
|
|
6503
6759
|
const kind = item.kind;
|
|
6504
|
-
const idKind = publicReadKindForId(id);
|
|
6760
|
+
const idKind = envelope.schemaVersion === PAPIERS_SCHEMA_VERSIONS.read ? readKindForIdentifier(id) : publicReadKindForId(id);
|
|
6505
6761
|
if (kind !== idKind) {
|
|
6506
6762
|
throw new CliUsageError(
|
|
6507
|
-
`${context} JSON item ${index} kind did not match its
|
|
6763
|
+
`${context} JSON item ${index} kind did not match its identifier.`
|
|
6508
6764
|
);
|
|
6509
6765
|
}
|
|
6510
6766
|
return id;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: papiers-research
|
|
3
|
-
version: 1.2.
|
|
3
|
+
version: 1.2.1
|
|
4
4
|
description: |
|
|
5
5
|
Ground proposals, experiment designs, reviews, and writing in the user's
|
|
6
|
-
Papiers library — their highlights, annotations, conversations, and
|
|
6
|
+
Papiers library — their highlights, notes, annotations, conversations, and
|
|
7
7
|
curated-but-unread saves — before generating. Use whenever output should
|
|
8
8
|
be shaped by what the user has read and thought, not generic knowledge:
|
|
9
9
|
proposing research ideas, designing experiments, advising on decisions,
|
|
@@ -17,7 +17,7 @@ allowed-tools:
|
|
|
17
17
|
The `papiers` CLI is the agent-readable memory of what the user has read and
|
|
18
18
|
thought. It holds two kinds of signal, and you must treat them differently:
|
|
19
19
|
|
|
20
|
-
- **Judgement** (read and marked): highlights, annotations, and past
|
|
20
|
+
- **Judgement** (read and marked): highlights, notes, annotations, and past
|
|
21
21
|
conversations. These are the user's own words — stances, open questions,
|
|
22
22
|
connections. The strongest signal you have.
|
|
23
23
|
- **Curation** (saved, possibly unread): library membership itself. The user
|
|
@@ -36,13 +36,14 @@ once for the full contract. `PAPIERS_TOKEN` must be configured.
|
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
papiers list --kind highlight --since 30d --limit 20 --json
|
|
39
|
+
papiers list --kind note --limit 20 --json
|
|
39
40
|
papiers list --kind document --limit 20 --json # scan recent titles
|
|
40
41
|
```
|
|
41
42
|
|
|
42
43
|
2. **Facet sweep.** Decompose the task into 3–6 facets (for "improve MoE
|
|
43
44
|
router load balancing": expert routing, load balancing loss, expert
|
|
44
45
|
collapse, capacity factor…). One default search covers matching titles,
|
|
45
|
-
passages, highlights, equations, and conversations in a single fused
|
|
46
|
+
passages, highlights, equations, notes, and conversations in a single fused
|
|
46
47
|
ranking:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
@@ -56,9 +57,10 @@ once for the full contract. `PAPIERS_TOKEN` must be configured.
|
|
|
56
57
|
for an author surname or `author.contains=karpathy` for a handle.
|
|
57
58
|
|
|
58
59
|
Document results carry nested `evidence[]` for passage, highlight, and
|
|
59
|
-
equation hits
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
equation hits; notes and conversations are standalone results. Use
|
|
61
|
+
`--passage-ids`, `--highlight-ids`, or `--evidence-ids` to project matching
|
|
62
|
+
evidence flat for piping. `--doc-ids` pivots any result page to deduped
|
|
63
|
+
parent documents, including attached notes and skipping conversations.
|
|
62
64
|
|
|
63
65
|
3. **Delegated reading.** Document hits you cannot tie to any judgement are
|
|
64
66
|
curated-but-unread candidates (`--filter engaged=false` lists the queue).
|
|
@@ -68,6 +70,7 @@ once for the full contract. `PAPIERS_TOKEN` must be configured.
|
|
|
68
70
|
|
|
69
71
|
```bash
|
|
70
72
|
papiers read doc_<id> --max-chars-per-item 4000 --json
|
|
73
|
+
papiers read nte_<id> --max-chars-per-item 4000 --json
|
|
71
74
|
papiers search "<topic>" --doc-ids | papiers read @- --format metadata --json
|
|
72
75
|
papiers search "<subtopic>" --kind passage --document-id doc_<id> --json # search within one document
|
|
73
76
|
```
|
|
@@ -108,7 +111,7 @@ once for the full contract. `PAPIERS_TOKEN` must be configured.
|
|
|
108
111
|
ISO timestamps or `30d`-style shorthand.
|
|
109
112
|
- **Honor the quality signal.** `quality.signal: "empty"` or `"low"` means
|
|
110
113
|
the library has nothing — report that rather than citing weak matches.
|
|
111
|
-
- **Cite IDs.** `hl_/cnv_/doc_/pas_` IDs are stable; include them so the
|
|
114
|
+
- **Cite IDs.** `hl_/cnv_/doc_/pas_/eq_/nte_` IDs are stable; include them so the
|
|
112
115
|
user can jump to sources.
|
|
113
116
|
- **Budgets are policy, not protocol.** Default to ~10–20 queries and 3–8
|
|
114
117
|
document reads per task. The user may override any policy in this skill
|