@tiagojct/subsub 0.16.0 → 0.17.0
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/CHANGELOG.md +14 -0
- package/README.md +8 -12
- package/dist/bench.js +1 -1
- package/dist/cli.js +2 -2
- package/dist/config.js +0 -6
- package/dist/doctor.js +1 -2
- package/dist/init.js +7 -20
- package/dist/look.js +2 -2
- package/dist/prompt.js +4 -6
- package/dist/read.js +88 -0
- package/dist/roles.js +4 -10
- package/dist/subsub.js +81 -47
- package/dist/web.js +122 -9
- package/package.json +1 -1
- package/prompts/lit.md +2 -2
- package/roles/researcher.md +3 -1
- package/src/bench.ts +1 -1
- package/src/cli.ts +2 -2
- package/src/config.ts +1 -11
- package/src/doctor.ts +1 -2
- package/src/init.ts +6 -31
- package/src/look.ts +2 -4
- package/src/prompt.ts +6 -8
- package/src/read.ts +107 -0
- package/src/roles.ts +5 -12
- package/src/subsub.ts +71 -48
- package/src/usage.ts +1 -1
- package/src/web.ts +114 -9
- package/templates/Zotero agent.md +1 -1
- package/web/app.css +61 -2
- package/web/app.js +215 -18
- package/web/i18n.js +56 -25
- package/web/index.html +17 -16
- package/dist/profiles.js +0 -96
- package/src/profiles.ts +0 -118
package/dist/profiles.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Profiles: how much Sub-Sub does for the user. Named after the work, not the
|
|
3
|
-
* person: a professor new to a field can choose Reader, a student can choose
|
|
4
|
-
* Scholar. A profile is the user's own choice (/profile changes it), not a lock.
|
|
5
|
-
*
|
|
6
|
-
* - reader: explains each step; reading notes are quotes with page numbers and
|
|
7
|
-
* questions; no summaries or syntheses; /lit gives a reading list;
|
|
8
|
-
* no bulk library changes.
|
|
9
|
-
* - scholar: literature notes, syntheses, searches, alerts; all library changes.
|
|
10
|
-
* - author: scholar plus manuscript work: citation check, bibliography, comments
|
|
11
|
-
* on the argument. Does not write the manuscript's paragraphs.
|
|
12
|
-
* - editor: everything, including drafting text for a manuscript on request.
|
|
13
|
-
*/
|
|
14
|
-
const BULK_LIBRARY = ["rename_tags", "remove_tags", "remove_automatic_tags", "trash_items", "update_fields", "repair_metadata"].map((n) => `zotero_${n}`);
|
|
15
|
-
const MANUSCRIPT = ["scholar_check_manuscript", "scholar_export_bibliography"];
|
|
16
|
-
export const PROFILE_SPECS = {
|
|
17
|
-
reader: {
|
|
18
|
-
name: "reader",
|
|
19
|
-
label: "Reader",
|
|
20
|
-
summary: "explains each step; reading notes are quotes and questions; /lit gives a reading list; no summaries; no bulk library changes",
|
|
21
|
-
without: [...BULK_LIBRARY, ...MANUSCRIPT],
|
|
22
|
-
withoutPrompts: ["compare", "review", "digest"],
|
|
23
|
-
batch: 10,
|
|
24
|
-
rules: [
|
|
25
|
-
"Profile: Reader. {{User}} is learning to work with the literature and wants to do the reading and the writing.",
|
|
26
|
-
"- Before each step, say in one or two lines what you will do and why.",
|
|
27
|
-
"- A literature note is a reading note: the full reference, then direct quotes with page numbers (or section names), and under each quote one question for {{user}} to answer. Do not write summaries, syntheses, conclusions or paragraphs that {{user}} could hand in as their own text. When a prompt or the shared rules ask for a literature note or a synthesis, make a reading note instead and say so.",
|
|
28
|
-
"- For searches, list works with one line each on what they study, not on what they conclude.",
|
|
29
|
-
"- /lit gives a reading list, not a review: plan, search, screen and read as the prompt says, then write the note in the Reader form that the prompt gives (no answer, no agreement or disagreement, no conclusions).",
|
|
30
|
-
"- If {{user}} asks for a summary, a synthesis or text for an assignment, say that the Reader profile does not write these, and offer quotes and questions. {{User}} can change the profile with /profile.",
|
|
31
|
-
"- Tag review notes: at most 10 items. Explain each proposed tag in the Reason column.",
|
|
32
|
-
].join("\n"),
|
|
33
|
-
},
|
|
34
|
-
scholar: {
|
|
35
|
-
name: "scholar",
|
|
36
|
-
label: "Scholar",
|
|
37
|
-
summary: "literature notes, syntheses, searches and alerts; all library changes",
|
|
38
|
-
without: MANUSCRIPT,
|
|
39
|
-
withoutPrompts: ["review"],
|
|
40
|
-
batch: 25,
|
|
41
|
-
rules: [
|
|
42
|
-
"Profile: Scholar.",
|
|
43
|
-
"- Write literature notes and syntheses from what you read, with a source for every claim.",
|
|
44
|
-
"- Do not draft text for {{user}}'s manuscripts, theses or assignments. If asked, say that the Author and Editor profiles help with manuscripts (/profile).",
|
|
45
|
-
"- Tag review notes: 25 items.",
|
|
46
|
-
].join("\n"),
|
|
47
|
-
},
|
|
48
|
-
author: {
|
|
49
|
-
name: "author",
|
|
50
|
-
label: "Author",
|
|
51
|
-
summary: "Scholar plus manuscripts: citation check, bibliography, comments on the argument",
|
|
52
|
-
without: [],
|
|
53
|
-
withoutPrompts: [],
|
|
54
|
-
batch: 25,
|
|
55
|
-
rules: [
|
|
56
|
-
"Profile: Author.",
|
|
57
|
-
"- Write literature notes and syntheses from what you read, with a source for every claim.",
|
|
58
|
-
"- Help with {{user}}'s manuscripts: check citations against the library, export the bibliography, and comment on the argument, the structure and the evidence that is missing, with the sources that could support each point.",
|
|
59
|
-
"- Do not write the manuscript's paragraphs. Say what is missing and where the support is; {{user}} writes the text. The Editor profile drafts text (/profile).",
|
|
60
|
-
"- Tag review notes: 25 items.",
|
|
61
|
-
].join("\n"),
|
|
62
|
-
},
|
|
63
|
-
editor: {
|
|
64
|
-
name: "editor",
|
|
65
|
-
label: "Editor",
|
|
66
|
-
summary: "everything, including drafting manuscript text on request",
|
|
67
|
-
without: [],
|
|
68
|
-
withoutPrompts: [],
|
|
69
|
-
batch: 25,
|
|
70
|
-
rules: [
|
|
71
|
-
"Profile: Editor. All tools.",
|
|
72
|
-
"- Write literature notes and syntheses from what you read, with a source for every claim.",
|
|
73
|
-
"- When {{user}} asks, draft text for a manuscript: cite library items as [@citekey], use only claims from sources you read, and mark drafted text clearly so that {{user}} can check it.",
|
|
74
|
-
"- Tag review notes: 25 items unless {{user}} asks for more.",
|
|
75
|
-
].join("\n"),
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
export function profileSpec(p) {
|
|
79
|
-
return PROFILE_SPECS[p];
|
|
80
|
-
}
|
|
81
|
-
/** Why a prompt command does not run in this profile, or undefined when it does. */
|
|
82
|
-
export function promptBlocked(text, profile) {
|
|
83
|
-
const m = /^\/([\w-]+)(?:\s|$)/.exec(text.trim());
|
|
84
|
-
if (!m || !PROFILE_SPECS[profile].withoutPrompts.includes(m[1]))
|
|
85
|
-
return undefined;
|
|
86
|
-
const allowed = Object.values(PROFILE_SPECS)
|
|
87
|
-
.filter((s) => !s.withoutPrompts.includes(m[1]))
|
|
88
|
-
.map((s) => s.label)
|
|
89
|
-
.join(", ");
|
|
90
|
-
return `/${m[1]} is not part of the ${PROFILE_SPECS[profile].label} profile (it is in: ${allowed}). Change the profile with /profile.`;
|
|
91
|
-
}
|
|
92
|
-
export function profileList(current) {
|
|
93
|
-
return Object.values(PROFILE_SPECS)
|
|
94
|
-
.map((s) => `${s.name === current ? "*" : " "} ${s.label.padEnd(8)} ${s.summary}`)
|
|
95
|
-
.join("\n");
|
|
96
|
-
}
|
package/src/profiles.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Profiles: how much Sub-Sub does for the user. Named after the work, not the
|
|
3
|
-
* person: a professor new to a field can choose Reader, a student can choose
|
|
4
|
-
* Scholar. A profile is the user's own choice (/profile changes it), not a lock.
|
|
5
|
-
*
|
|
6
|
-
* - reader: explains each step; reading notes are quotes with page numbers and
|
|
7
|
-
* questions; no summaries or syntheses; /lit gives a reading list;
|
|
8
|
-
* no bulk library changes.
|
|
9
|
-
* - scholar: literature notes, syntheses, searches, alerts; all library changes.
|
|
10
|
-
* - author: scholar plus manuscript work: citation check, bibliography, comments
|
|
11
|
-
* on the argument. Does not write the manuscript's paragraphs.
|
|
12
|
-
* - editor: everything, including drafting text for a manuscript on request.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import type { Profile } from "./config.ts";
|
|
16
|
-
|
|
17
|
-
export interface ProfileSpec {
|
|
18
|
-
name: Profile;
|
|
19
|
-
label: string;
|
|
20
|
-
summary: string;
|
|
21
|
-
/** Tools this profile does not offer (full names). */
|
|
22
|
-
without: string[];
|
|
23
|
-
/** Prompt commands this profile does not run (names without the slash). */
|
|
24
|
-
withoutPrompts: string[];
|
|
25
|
-
/** Items per review note and per batch. */
|
|
26
|
-
batch: number;
|
|
27
|
-
/** Added to the system prompt. {{user}} is the user's name or "the user". */
|
|
28
|
-
rules: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const BULK_LIBRARY = ["rename_tags", "remove_tags", "remove_automatic_tags", "trash_items", "update_fields", "repair_metadata"].map(
|
|
32
|
-
(n) => `zotero_${n}`,
|
|
33
|
-
);
|
|
34
|
-
const MANUSCRIPT = ["scholar_check_manuscript", "scholar_export_bibliography"];
|
|
35
|
-
|
|
36
|
-
export const PROFILE_SPECS: Record<Profile, ProfileSpec> = {
|
|
37
|
-
reader: {
|
|
38
|
-
name: "reader",
|
|
39
|
-
label: "Reader",
|
|
40
|
-
summary: "explains each step; reading notes are quotes and questions; /lit gives a reading list; no summaries; no bulk library changes",
|
|
41
|
-
without: [...BULK_LIBRARY, ...MANUSCRIPT],
|
|
42
|
-
withoutPrompts: ["compare", "review", "digest"],
|
|
43
|
-
batch: 10,
|
|
44
|
-
rules: [
|
|
45
|
-
"Profile: Reader. {{User}} is learning to work with the literature and wants to do the reading and the writing.",
|
|
46
|
-
"- Before each step, say in one or two lines what you will do and why.",
|
|
47
|
-
"- A literature note is a reading note: the full reference, then direct quotes with page numbers (or section names), and under each quote one question for {{user}} to answer. Do not write summaries, syntheses, conclusions or paragraphs that {{user}} could hand in as their own text. When a prompt or the shared rules ask for a literature note or a synthesis, make a reading note instead and say so.",
|
|
48
|
-
"- For searches, list works with one line each on what they study, not on what they conclude.",
|
|
49
|
-
"- /lit gives a reading list, not a review: plan, search, screen and read as the prompt says, then write the note in the Reader form that the prompt gives (no answer, no agreement or disagreement, no conclusions).",
|
|
50
|
-
"- If {{user}} asks for a summary, a synthesis or text for an assignment, say that the Reader profile does not write these, and offer quotes and questions. {{User}} can change the profile with /profile.",
|
|
51
|
-
"- Tag review notes: at most 10 items. Explain each proposed tag in the Reason column.",
|
|
52
|
-
].join("\n"),
|
|
53
|
-
},
|
|
54
|
-
scholar: {
|
|
55
|
-
name: "scholar",
|
|
56
|
-
label: "Scholar",
|
|
57
|
-
summary: "literature notes, syntheses, searches and alerts; all library changes",
|
|
58
|
-
without: MANUSCRIPT,
|
|
59
|
-
withoutPrompts: ["review"],
|
|
60
|
-
batch: 25,
|
|
61
|
-
rules: [
|
|
62
|
-
"Profile: Scholar.",
|
|
63
|
-
"- Write literature notes and syntheses from what you read, with a source for every claim.",
|
|
64
|
-
"- Do not draft text for {{user}}'s manuscripts, theses or assignments. If asked, say that the Author and Editor profiles help with manuscripts (/profile).",
|
|
65
|
-
"- Tag review notes: 25 items.",
|
|
66
|
-
].join("\n"),
|
|
67
|
-
},
|
|
68
|
-
author: {
|
|
69
|
-
name: "author",
|
|
70
|
-
label: "Author",
|
|
71
|
-
summary: "Scholar plus manuscripts: citation check, bibliography, comments on the argument",
|
|
72
|
-
without: [],
|
|
73
|
-
withoutPrompts: [],
|
|
74
|
-
batch: 25,
|
|
75
|
-
rules: [
|
|
76
|
-
"Profile: Author.",
|
|
77
|
-
"- Write literature notes and syntheses from what you read, with a source for every claim.",
|
|
78
|
-
"- Help with {{user}}'s manuscripts: check citations against the library, export the bibliography, and comment on the argument, the structure and the evidence that is missing, with the sources that could support each point.",
|
|
79
|
-
"- Do not write the manuscript's paragraphs. Say what is missing and where the support is; {{user}} writes the text. The Editor profile drafts text (/profile).",
|
|
80
|
-
"- Tag review notes: 25 items.",
|
|
81
|
-
].join("\n"),
|
|
82
|
-
},
|
|
83
|
-
editor: {
|
|
84
|
-
name: "editor",
|
|
85
|
-
label: "Editor",
|
|
86
|
-
summary: "everything, including drafting manuscript text on request",
|
|
87
|
-
without: [],
|
|
88
|
-
withoutPrompts: [],
|
|
89
|
-
batch: 25,
|
|
90
|
-
rules: [
|
|
91
|
-
"Profile: Editor. All tools.",
|
|
92
|
-
"- Write literature notes and syntheses from what you read, with a source for every claim.",
|
|
93
|
-
"- When {{user}} asks, draft text for a manuscript: cite library items as [@citekey], use only claims from sources you read, and mark drafted text clearly so that {{user}} can check it.",
|
|
94
|
-
"- Tag review notes: 25 items unless {{user}} asks for more.",
|
|
95
|
-
].join("\n"),
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export function profileSpec(p: Profile): ProfileSpec {
|
|
100
|
-
return PROFILE_SPECS[p];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/** Why a prompt command does not run in this profile, or undefined when it does. */
|
|
104
|
-
export function promptBlocked(text: string, profile: Profile): string | undefined {
|
|
105
|
-
const m = /^\/([\w-]+)(?:\s|$)/.exec(text.trim());
|
|
106
|
-
if (!m || !PROFILE_SPECS[profile].withoutPrompts.includes(m[1])) return undefined;
|
|
107
|
-
const allowed = Object.values(PROFILE_SPECS)
|
|
108
|
-
.filter((s) => !s.withoutPrompts.includes(m[1]))
|
|
109
|
-
.map((s) => s.label)
|
|
110
|
-
.join(", ");
|
|
111
|
-
return `/${m[1]} is not part of the ${PROFILE_SPECS[profile].label} profile (it is in: ${allowed}). Change the profile with /profile.`;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function profileList(current?: Profile): string {
|
|
115
|
-
return Object.values(PROFILE_SPECS)
|
|
116
|
-
.map((s) => `${s.name === current ? "*" : " "} ${s.label.padEnd(8)} ${s.summary}`)
|
|
117
|
-
.join("\n");
|
|
118
|
-
}
|