tenbrains 2.1.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/AGENTS.md +112 -0
- package/README.md +218 -0
- package/dist/ai/analyzer.d.ts +28 -0
- package/dist/ai/analyzer.d.ts.map +1 -0
- package/dist/ai/analyzer.js +35 -0
- package/dist/ai/analyzer.js.map +1 -0
- package/dist/ai/client.d.ts +12 -0
- package/dist/ai/client.d.ts.map +1 -0
- package/dist/ai/client.js +152 -0
- package/dist/ai/client.js.map +1 -0
- package/dist/ai/json.d.ts +7 -0
- package/dist/ai/json.d.ts.map +1 -0
- package/dist/ai/json.js +57 -0
- package/dist/ai/json.js.map +1 -0
- package/dist/ai/mock.d.ts +6 -0
- package/dist/ai/mock.d.ts.map +1 -0
- package/dist/ai/mock.js +66 -0
- package/dist/ai/mock.js.map +1 -0
- package/dist/ai/prompts.d.ts +19 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +40 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/providers.d.ts +22 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +56 -0
- package/dist/ai/providers.js.map +1 -0
- package/dist/ai/resolve.d.ts +24 -0
- package/dist/ai/resolve.d.ts.map +1 -0
- package/dist/ai/resolve.js +33 -0
- package/dist/ai/resolve.js.map +1 -0
- package/dist/bin/preflight.d.ts +2 -0
- package/dist/bin/preflight.d.ts.map +1 -0
- package/dist/bin/preflight.js +11 -0
- package/dist/bin/preflight.js.map +1 -0
- package/dist/bin/tenbrains.d.ts +3 -0
- package/dist/bin/tenbrains.d.ts.map +1 -0
- package/dist/bin/tenbrains.js +9 -0
- package/dist/bin/tenbrains.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +554 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/analyze.d.ts +7 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +204 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/bookmark.d.ts +9 -0
- package/dist/commands/bookmark.d.ts.map +1 -0
- package/dist/commands/bookmark.js +120 -0
- package/dist/commands/bookmark.js.map +1 -0
- package/dist/commands/config.d.ts +15 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +142 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/db.d.ts +9 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +64 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/digest.d.ts +19 -0
- package/dist/commands/digest.d.ts.map +1 -0
- package/dist/commands/digest.js +71 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/import.d.ts +11 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +78 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/learn.d.ts +9 -0
- package/dist/commands/learn.d.ts.map +1 -0
- package/dist/commands/learn.js +149 -0
- package/dist/commands/learn.js.map +1 -0
- package/dist/commands/manifest.d.ts +13 -0
- package/dist/commands/manifest.d.ts.map +1 -0
- package/dist/commands/manifest.js +62 -0
- package/dist/commands/manifest.js.map +1 -0
- package/dist/commands/record.d.ts +10 -0
- package/dist/commands/record.d.ts.map +1 -0
- package/dist/commands/record.js +37 -0
- package/dist/commands/record.js.map +1 -0
- package/dist/commands/search.d.ts +5 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +33 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/shared.d.ts +9 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +13 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/suggest.d.ts +9 -0
- package/dist/commands/suggest.d.ts.map +1 -0
- package/dist/commands/suggest.js +102 -0
- package/dist/commands/suggest.js.map +1 -0
- package/dist/commands/takeaway.d.ts +9 -0
- package/dist/commands/takeaway.d.ts.map +1 -0
- package/dist/commands/takeaway.js +167 -0
- package/dist/commands/takeaway.js.map +1 -0
- package/dist/core/config.d.ts +52 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +180 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +28 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +40 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/errors.d.ts +33 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +82 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/input.d.ts +9 -0
- package/dist/core/input.d.ts.map +1 -0
- package/dist/core/input.js +47 -0
- package/dist/core/input.js.map +1 -0
- package/dist/core/opts.d.ts +8 -0
- package/dist/core/opts.d.ts.map +1 -0
- package/dist/core/opts.js +38 -0
- package/dist/core/opts.js.map +1 -0
- package/dist/core/output.d.ts +58 -0
- package/dist/core/output.d.ts.map +1 -0
- package/dist/core/output.js +76 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/paths.d.ts +20 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +31 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/text.d.ts +10 -0
- package/dist/core/text.d.ts.map +1 -0
- package/dist/core/text.js +132 -0
- package/dist/core/text.js.map +1 -0
- package/dist/core/validate.d.ts +5 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +17 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/db/database.d.ts +27 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +90 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/fts.d.ts +12 -0
- package/dist/db/fts.d.ts.map +1 -0
- package/dist/db/fts.js +42 -0
- package/dist/db/fts.js.map +1 -0
- package/dist/db/migrations.d.ts +20 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +243 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/repositories.d.ts +130 -0
- package/dist/db/repositories.d.ts.map +1 -0
- package/dist/db/repositories.js +418 -0
- package/dist/db/repositories.js.map +1 -0
- package/dist/domain/learn.d.ts +25 -0
- package/dist/domain/learn.d.ts.map +1 -0
- package/dist/domain/learn.js +85 -0
- package/dist/domain/learn.js.map +1 -0
- package/dist/domain/schemas.d.ts +169 -0
- package/dist/domain/schemas.d.ts.map +1 -0
- package/dist/domain/schemas.js +54 -0
- package/dist/domain/schemas.js.map +1 -0
- package/dist/domain/search.d.ts +32 -0
- package/dist/domain/search.d.ts.map +1 -0
- package/dist/domain/search.js +77 -0
- package/dist/domain/search.js.map +1 -0
- package/dist/domain/suggest.d.ts +17 -0
- package/dist/domain/suggest.d.ts.map +1 -0
- package/dist/domain/suggest.js +114 -0
- package/dist/domain/suggest.js.map +1 -0
- package/dist/domain/tags.d.ts +9 -0
- package/dist/domain/tags.d.ts.map +1 -0
- package/dist/domain/tags.js +40 -0
- package/dist/domain/tags.js.map +1 -0
- package/dist/domain/types.d.ts +84 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js +2 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/x/archive.d.ts +32 -0
- package/dist/x/archive.d.ts.map +1 -0
- package/dist/x/archive.js +108 -0
- package/dist/x/archive.js.map +1 -0
- package/dist/x/client.d.ts +61 -0
- package/dist/x/client.d.ts.map +1 -0
- package/dist/x/client.js +321 -0
- package/dist/x/client.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** A novel concept extracted from a post (mirrors the original tenbrains shape). */
|
|
3
|
+
export declare const ConceptSchema: z.ZodObject<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
whyItMattersInTweet: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
name: string;
|
|
8
|
+
whyItMattersInTweet: string;
|
|
9
|
+
}, {
|
|
10
|
+
name: string;
|
|
11
|
+
whyItMattersInTweet: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* AI analysis output. The prompt asks for exactly 5 concepts; we accept 1-10 so
|
|
15
|
+
* a slightly off-spec provider response still persists rather than hard-failing.
|
|
16
|
+
*/
|
|
17
|
+
export declare const AnalysisResultSchema: z.ZodObject<{
|
|
18
|
+
topic: z.ZodString;
|
|
19
|
+
summary: z.ZodString;
|
|
20
|
+
intent: z.ZodString;
|
|
21
|
+
novelConcepts: z.ZodArray<z.ZodObject<{
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
whyItMattersInTweet: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
name: string;
|
|
26
|
+
whyItMattersInTweet: string;
|
|
27
|
+
}, {
|
|
28
|
+
name: string;
|
|
29
|
+
whyItMattersInTweet: string;
|
|
30
|
+
}>, "many">;
|
|
31
|
+
}, "strip", z.ZodTypeAny, {
|
|
32
|
+
topic: string;
|
|
33
|
+
summary: string;
|
|
34
|
+
intent: string;
|
|
35
|
+
novelConcepts: {
|
|
36
|
+
name: string;
|
|
37
|
+
whyItMattersInTweet: string;
|
|
38
|
+
}[];
|
|
39
|
+
}, {
|
|
40
|
+
topic: string;
|
|
41
|
+
summary: string;
|
|
42
|
+
intent: string;
|
|
43
|
+
novelConcepts: {
|
|
44
|
+
name: string;
|
|
45
|
+
whyItMattersInTweet: string;
|
|
46
|
+
}[];
|
|
47
|
+
}>;
|
|
48
|
+
/** AI account-takeaway output. */
|
|
49
|
+
export declare const TakeawayResultSchema: z.ZodObject<{
|
|
50
|
+
summary: z.ZodString;
|
|
51
|
+
takeaways: z.ZodArray<z.ZodString, "many">;
|
|
52
|
+
}, "strip", z.ZodTypeAny, {
|
|
53
|
+
summary: string;
|
|
54
|
+
takeaways: string[];
|
|
55
|
+
}, {
|
|
56
|
+
summary: string;
|
|
57
|
+
takeaways: string[];
|
|
58
|
+
}>;
|
|
59
|
+
/** A user/agent rating of one concept, used to prioritize a learning track. */
|
|
60
|
+
export declare const ConceptRatingSchema: z.ZodObject<{
|
|
61
|
+
concept: z.ZodString;
|
|
62
|
+
familiarity: z.ZodNumber;
|
|
63
|
+
interest: z.ZodNumber;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
concept: string;
|
|
66
|
+
familiarity: number;
|
|
67
|
+
interest: number;
|
|
68
|
+
}, {
|
|
69
|
+
concept: string;
|
|
70
|
+
familiarity: number;
|
|
71
|
+
interest: number;
|
|
72
|
+
}>;
|
|
73
|
+
export declare const RatingsInputSchema: z.ZodArray<z.ZodObject<{
|
|
74
|
+
concept: z.ZodString;
|
|
75
|
+
familiarity: z.ZodNumber;
|
|
76
|
+
interest: z.ZodNumber;
|
|
77
|
+
}, "strip", z.ZodTypeAny, {
|
|
78
|
+
concept: string;
|
|
79
|
+
familiarity: number;
|
|
80
|
+
interest: number;
|
|
81
|
+
}, {
|
|
82
|
+
concept: string;
|
|
83
|
+
familiarity: number;
|
|
84
|
+
interest: number;
|
|
85
|
+
}>, "many">;
|
|
86
|
+
/** Input shape for ingesting a single post (`analyze`, `bookmark add`). */
|
|
87
|
+
export declare const PostInputSchema: z.ZodObject<{
|
|
88
|
+
text: z.ZodString;
|
|
89
|
+
url: z.ZodOptional<z.ZodString>;
|
|
90
|
+
externalId: z.ZodOptional<z.ZodString>;
|
|
91
|
+
authorUsername: z.ZodOptional<z.ZodString>;
|
|
92
|
+
authorName: z.ZodOptional<z.ZodString>;
|
|
93
|
+
postedAt: z.ZodOptional<z.ZodString>;
|
|
94
|
+
}, "strip", z.ZodTypeAny, {
|
|
95
|
+
text: string;
|
|
96
|
+
url?: string | undefined;
|
|
97
|
+
externalId?: string | undefined;
|
|
98
|
+
authorUsername?: string | undefined;
|
|
99
|
+
authorName?: string | undefined;
|
|
100
|
+
postedAt?: string | undefined;
|
|
101
|
+
}, {
|
|
102
|
+
text: string;
|
|
103
|
+
url?: string | undefined;
|
|
104
|
+
externalId?: string | undefined;
|
|
105
|
+
authorUsername?: string | undefined;
|
|
106
|
+
authorName?: string | undefined;
|
|
107
|
+
postedAt?: string | undefined;
|
|
108
|
+
}>;
|
|
109
|
+
/** Input shape for one of the recent posts fed into `takeaway refresh`. */
|
|
110
|
+
export declare const TakeawayPostInputSchema: z.ZodObject<{
|
|
111
|
+
text: z.ZodString;
|
|
112
|
+
externalId: z.ZodOptional<z.ZodString>;
|
|
113
|
+
url: z.ZodOptional<z.ZodString>;
|
|
114
|
+
postedAt: z.ZodOptional<z.ZodString>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
text: string;
|
|
117
|
+
url?: string | undefined;
|
|
118
|
+
externalId?: string | undefined;
|
|
119
|
+
postedAt?: string | undefined;
|
|
120
|
+
}, {
|
|
121
|
+
text: string;
|
|
122
|
+
url?: string | undefined;
|
|
123
|
+
externalId?: string | undefined;
|
|
124
|
+
postedAt?: string | undefined;
|
|
125
|
+
}>;
|
|
126
|
+
export declare const TakeawayPostsInputSchema: z.ZodArray<z.ZodObject<{
|
|
127
|
+
text: z.ZodString;
|
|
128
|
+
externalId: z.ZodOptional<z.ZodString>;
|
|
129
|
+
url: z.ZodOptional<z.ZodString>;
|
|
130
|
+
postedAt: z.ZodOptional<z.ZodString>;
|
|
131
|
+
}, "strip", z.ZodTypeAny, {
|
|
132
|
+
text: string;
|
|
133
|
+
url?: string | undefined;
|
|
134
|
+
externalId?: string | undefined;
|
|
135
|
+
postedAt?: string | undefined;
|
|
136
|
+
}, {
|
|
137
|
+
text: string;
|
|
138
|
+
url?: string | undefined;
|
|
139
|
+
externalId?: string | undefined;
|
|
140
|
+
postedAt?: string | undefined;
|
|
141
|
+
}>, "many">;
|
|
142
|
+
/**
|
|
143
|
+
* Input shape for `analyze --thread <json>`: the ordered parts of one thread,
|
|
144
|
+
* each either a bare string or a post object. Analyzed as a single document.
|
|
145
|
+
*/
|
|
146
|
+
export declare const ThreadInputSchema: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
147
|
+
text: z.ZodString;
|
|
148
|
+
externalId: z.ZodOptional<z.ZodString>;
|
|
149
|
+
url: z.ZodOptional<z.ZodString>;
|
|
150
|
+
postedAt: z.ZodOptional<z.ZodString>;
|
|
151
|
+
}, "strip", z.ZodTypeAny, {
|
|
152
|
+
text: string;
|
|
153
|
+
url?: string | undefined;
|
|
154
|
+
externalId?: string | undefined;
|
|
155
|
+
postedAt?: string | undefined;
|
|
156
|
+
}, {
|
|
157
|
+
text: string;
|
|
158
|
+
url?: string | undefined;
|
|
159
|
+
externalId?: string | undefined;
|
|
160
|
+
postedAt?: string | undefined;
|
|
161
|
+
}>]>, "many">;
|
|
162
|
+
export type Concept = z.infer<typeof ConceptSchema>;
|
|
163
|
+
export type AnalysisResult = z.infer<typeof AnalysisResultSchema>;
|
|
164
|
+
export type TakeawayResult = z.infer<typeof TakeawayResultSchema>;
|
|
165
|
+
export type ConceptRating = z.infer<typeof ConceptRatingSchema>;
|
|
166
|
+
export type PostInput = z.infer<typeof PostInputSchema>;
|
|
167
|
+
export type TakeawayPostInput = z.infer<typeof TakeawayPostInputSchema>;
|
|
168
|
+
export type ThreadInput = z.infer<typeof ThreadInputSchema>;
|
|
169
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/domain/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,oFAAoF;AACpF,eAAO,MAAM,aAAa;;;;;;;;;EAGxB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK/B,CAAC;AAEH,kCAAkC;AAClC,eAAO,MAAM,oBAAoB;;;;;;;;;EAG/B,CAAC;AAIH,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;WAA+B,CAAC;AAE/D,2EAA2E;AAC3E,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;EAO1B,CAAC;AAEH,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAKlC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;WAA0C,CAAC;AAEhF;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;aAErB,CAAC;AAEV,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** A novel concept extracted from a post (mirrors the original tenbrains shape). */
|
|
3
|
+
export const ConceptSchema = z.object({
|
|
4
|
+
name: z.string().min(1),
|
|
5
|
+
whyItMattersInTweet: z.string().min(1),
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* AI analysis output. The prompt asks for exactly 5 concepts; we accept 1-10 so
|
|
9
|
+
* a slightly off-spec provider response still persists rather than hard-failing.
|
|
10
|
+
*/
|
|
11
|
+
export const AnalysisResultSchema = z.object({
|
|
12
|
+
topic: z.string().min(1),
|
|
13
|
+
summary: z.string().min(1),
|
|
14
|
+
intent: z.string().min(1),
|
|
15
|
+
novelConcepts: z.array(ConceptSchema).min(1).max(10),
|
|
16
|
+
});
|
|
17
|
+
/** AI account-takeaway output. */
|
|
18
|
+
export const TakeawayResultSchema = z.object({
|
|
19
|
+
summary: z.string().min(1),
|
|
20
|
+
takeaways: z.array(z.string().min(1)).min(1).max(8),
|
|
21
|
+
});
|
|
22
|
+
const RatingValue = z.coerce.number().int().min(1).max(5);
|
|
23
|
+
/** A user/agent rating of one concept, used to prioritize a learning track. */
|
|
24
|
+
export const ConceptRatingSchema = z.object({
|
|
25
|
+
concept: z.string().min(1),
|
|
26
|
+
familiarity: RatingValue,
|
|
27
|
+
interest: RatingValue,
|
|
28
|
+
});
|
|
29
|
+
export const RatingsInputSchema = z.array(ConceptRatingSchema);
|
|
30
|
+
/** Input shape for ingesting a single post (`analyze`, `bookmark add`). */
|
|
31
|
+
export const PostInputSchema = z.object({
|
|
32
|
+
text: z.string().min(1, "post text is required"),
|
|
33
|
+
url: z.string().url().optional(),
|
|
34
|
+
externalId: z.string().min(1).optional(),
|
|
35
|
+
authorUsername: z.string().min(1).optional(),
|
|
36
|
+
authorName: z.string().min(1).optional(),
|
|
37
|
+
postedAt: z.string().min(1).optional(),
|
|
38
|
+
});
|
|
39
|
+
/** Input shape for one of the recent posts fed into `takeaway refresh`. */
|
|
40
|
+
export const TakeawayPostInputSchema = z.object({
|
|
41
|
+
text: z.string().min(1),
|
|
42
|
+
externalId: z.string().min(1).optional(),
|
|
43
|
+
url: z.string().url().optional(),
|
|
44
|
+
postedAt: z.string().min(1).optional(),
|
|
45
|
+
});
|
|
46
|
+
export const TakeawayPostsInputSchema = z.array(TakeawayPostInputSchema).min(1);
|
|
47
|
+
/**
|
|
48
|
+
* Input shape for `analyze --thread <json>`: the ordered parts of one thread,
|
|
49
|
+
* each either a bare string or a post object. Analyzed as a single document.
|
|
50
|
+
*/
|
|
51
|
+
export const ThreadInputSchema = z
|
|
52
|
+
.array(z.union([z.string().min(1), TakeawayPostInputSchema]))
|
|
53
|
+
.min(1);
|
|
54
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/domain/schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Store } from "../db/repositories.js";
|
|
2
|
+
export type SearchType = "analysis" | "takeaway" | "bookmark";
|
|
3
|
+
export interface SearchHit {
|
|
4
|
+
type: SearchType;
|
|
5
|
+
id: string;
|
|
6
|
+
score: number;
|
|
7
|
+
title: string;
|
|
8
|
+
snippet: string;
|
|
9
|
+
refs: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export interface SearchResult {
|
|
12
|
+
query: string;
|
|
13
|
+
total: number;
|
|
14
|
+
groups: Record<SearchType, SearchHit[]>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Turn a free-text query into an FTS5 MATCH expression. Each word is quoted
|
|
18
|
+
* (so FTS operators in user input are inert) and words are OR-ed, letting
|
|
19
|
+
* BM25 rank partial matches instead of dropping them.
|
|
20
|
+
*/
|
|
21
|
+
export declare function toMatchQuery(query: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Full-text search across stored analyses, account takeaways, and bookmarks,
|
|
24
|
+
* backed by the trigger-maintained `search_fts` FTS5 table. Porter stemming
|
|
25
|
+
* matches inflected forms ("embedding" finds "embeddings"); ranking is BM25
|
|
26
|
+
* with the title column weighted double. Fully local and deterministic.
|
|
27
|
+
*/
|
|
28
|
+
export declare function searchCorpus(store: Store, query: string, options?: {
|
|
29
|
+
types?: SearchType[];
|
|
30
|
+
limit?: number;
|
|
31
|
+
}): SearchResult;
|
|
32
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/domain/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;CACzC;AASD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,YAAY,CAsCd"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn a free-text query into an FTS5 MATCH expression. Each word is quoted
|
|
3
|
+
* (so FTS operators in user input are inert) and words are OR-ed, letting
|
|
4
|
+
* BM25 rank partial matches instead of dropping them.
|
|
5
|
+
*/
|
|
6
|
+
export function toMatchQuery(query) {
|
|
7
|
+
const words = query.match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
8
|
+
if (words.length === 0) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return words.map((w) => `"${w}"`).join(" OR ");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Full-text search across stored analyses, account takeaways, and bookmarks,
|
|
15
|
+
* backed by the trigger-maintained `search_fts` FTS5 table. Porter stemming
|
|
16
|
+
* matches inflected forms ("embedding" finds "embeddings"); ranking is BM25
|
|
17
|
+
* with the title column weighted double. Fully local and deterministic.
|
|
18
|
+
*/
|
|
19
|
+
export function searchCorpus(store, query, options = {}) {
|
|
20
|
+
const types = new Set(options.types ?? ["analysis", "takeaway", "bookmark"]);
|
|
21
|
+
const limit = options.limit ?? 10;
|
|
22
|
+
const groups = { analysis: [], takeaway: [], bookmark: [] };
|
|
23
|
+
const match = toMatchQuery(query);
|
|
24
|
+
if (match) {
|
|
25
|
+
const stmt = store.database.handle.prepare(`SELECT ref_id, title, snippet(search_fts, -1, '', '', '…', 24) AS snip,
|
|
26
|
+
bm25(search_fts, 0, 0, 2.0, 1.0) AS rank
|
|
27
|
+
FROM search_fts
|
|
28
|
+
WHERE search_fts MATCH ? AND type = ?
|
|
29
|
+
ORDER BY rank
|
|
30
|
+
LIMIT ?`);
|
|
31
|
+
for (const type of types) {
|
|
32
|
+
const rows = stmt.all(match, type, limit);
|
|
33
|
+
for (const row of rows) {
|
|
34
|
+
const refs = resolveRefs(store, type, row.ref_id);
|
|
35
|
+
if (refs === null) {
|
|
36
|
+
continue; // index row outlived its record; `db reindex` cleans these
|
|
37
|
+
}
|
|
38
|
+
groups[type].push({
|
|
39
|
+
type,
|
|
40
|
+
id: row.ref_id,
|
|
41
|
+
// bm25() returns "lower is better" negatives; flip so higher = better.
|
|
42
|
+
// BM25 magnitudes can be tiny in small corpora, so keep 6 decimals.
|
|
43
|
+
score: Number((-row.rank).toFixed(6)),
|
|
44
|
+
title: row.title,
|
|
45
|
+
snippet: row.snip,
|
|
46
|
+
refs,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const total = groups.analysis.length + groups.takeaway.length + groups.bookmark.length;
|
|
52
|
+
return { query, total, groups };
|
|
53
|
+
}
|
|
54
|
+
function resolveRefs(store, type, id) {
|
|
55
|
+
if (type === "analysis") {
|
|
56
|
+
const analysis = store.analyses.findById(id);
|
|
57
|
+
if (!analysis) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const post = store.posts.findById(analysis.postId);
|
|
61
|
+
return { postId: analysis.postId, author: post?.authorUsername ?? null };
|
|
62
|
+
}
|
|
63
|
+
if (type === "takeaway") {
|
|
64
|
+
const snap = store.snapshots.findById(id);
|
|
65
|
+
if (!snap) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const account = store.accounts.findById(snap.accountId);
|
|
69
|
+
return { accountId: snap.accountId, username: account?.username ?? null };
|
|
70
|
+
}
|
|
71
|
+
const bookmark = store.bookmarks.findById(id);
|
|
72
|
+
if (!bookmark) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return { postId: bookmark.postId, tags: bookmark.tags };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/domain/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Store } from "../db/repositories.js";
|
|
2
|
+
import type { Suggestion } from "./types.js";
|
|
3
|
+
export interface GenerateResult {
|
|
4
|
+
created: number;
|
|
5
|
+
updated: number;
|
|
6
|
+
profileEmpty: boolean;
|
|
7
|
+
suggestions: Suggestion[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Regenerate pending suggestions: rank analyzed-but-unsaved posts against the
|
|
11
|
+
* interest profile. Posts already saved or dismissed are left untouched.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateSuggestions(store: Store, options?: {
|
|
14
|
+
limit?: number;
|
|
15
|
+
now?: Date;
|
|
16
|
+
}): GenerateResult;
|
|
17
|
+
//# sourceMappingURL=suggest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/domain/suggest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA4E7C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CAAO,GAC3C,cAAc,CAsDhB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { tokenSet } from "../core/text.js";
|
|
2
|
+
const TAG_WEIGHT = 3;
|
|
3
|
+
const TAKEAWAY_WEIGHT = 2;
|
|
4
|
+
const BOOKMARK_TEXT_WEIGHT = 1;
|
|
5
|
+
/** Interests drift: signal loses half its weight every ~2 months. */
|
|
6
|
+
const HALF_LIFE_DAYS = 60;
|
|
7
|
+
/** Exponential decay in (0, 1] by age relative to `now`. */
|
|
8
|
+
function decayFactor(createdAt, now) {
|
|
9
|
+
const ageDays = Math.max(0, (now.getTime() - new Date(createdAt).getTime()) / 86_400_000);
|
|
10
|
+
return 0.5 ** (ageDays / HALF_LIFE_DAYS);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build a weighted interest profile from saved signal: bookmark tags (strongest),
|
|
14
|
+
* account-takeaway themes, and the text of bookmarked posts, each discounted by
|
|
15
|
+
* an exponential recency decay so last week's saves outweigh last quarter's.
|
|
16
|
+
* This is the local, deterministic stand-in for the original's semantic
|
|
17
|
+
* affinity ranking.
|
|
18
|
+
*/
|
|
19
|
+
function buildProfile(store, now) {
|
|
20
|
+
const weights = new Map();
|
|
21
|
+
const bump = (token, weight) => {
|
|
22
|
+
weights.set(token, (weights.get(token) ?? 0) + weight);
|
|
23
|
+
};
|
|
24
|
+
const postsById = new Map(store.posts.all().map((p) => [p.id, p]));
|
|
25
|
+
for (const bookmark of store.bookmarks.all()) {
|
|
26
|
+
const decay = decayFactor(bookmark.createdAt, now);
|
|
27
|
+
for (const tag of bookmark.tags) {
|
|
28
|
+
for (const token of tokenSet(tag)) {
|
|
29
|
+
bump(token, TAG_WEIGHT * decay);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const post = postsById.get(bookmark.postId);
|
|
33
|
+
if (post) {
|
|
34
|
+
for (const token of tokenSet(post.text)) {
|
|
35
|
+
bump(token, BOOKMARK_TEXT_WEIGHT * decay);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const snap of store.snapshots.all()) {
|
|
40
|
+
const decay = decayFactor(snap.createdAt, now);
|
|
41
|
+
for (const token of tokenSet(`${snap.summary} ${snap.takeaways.join(" ")}`)) {
|
|
42
|
+
bump(token, TAKEAWAY_WEIGHT * decay);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { weights, empty: weights.size === 0 };
|
|
46
|
+
}
|
|
47
|
+
function scoreCandidate(profile, tokens) {
|
|
48
|
+
const matched = [];
|
|
49
|
+
let score = 0;
|
|
50
|
+
for (const token of tokens) {
|
|
51
|
+
const weight = profile.weights.get(token);
|
|
52
|
+
if (weight) {
|
|
53
|
+
score += weight;
|
|
54
|
+
matched.push({ token, weight });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
matched.sort((a, b) => b.weight - a.weight);
|
|
58
|
+
return { score, matched: matched.slice(0, 3).map((m) => m.token) };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Regenerate pending suggestions: rank analyzed-but-unsaved posts against the
|
|
62
|
+
* interest profile. Posts already saved or dismissed are left untouched.
|
|
63
|
+
*/
|
|
64
|
+
export function generateSuggestions(store, options = {}) {
|
|
65
|
+
const limit = options.limit ?? 10;
|
|
66
|
+
const profile = buildProfile(store, options.now ?? new Date());
|
|
67
|
+
const bookmarkedPostIds = new Set(store.bookmarks.all().map((b) => b.postId));
|
|
68
|
+
let created = 0;
|
|
69
|
+
let updated = 0;
|
|
70
|
+
for (const post of store.posts.all()) {
|
|
71
|
+
if (bookmarkedPostIds.has(post.id)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const existing = store.suggestions.findByPostId(post.id);
|
|
75
|
+
if (existing && existing.status !== "pending") {
|
|
76
|
+
continue; // respect prior save/dismiss feedback
|
|
77
|
+
}
|
|
78
|
+
const analysis = store.analyses.latestForPost(post.id);
|
|
79
|
+
if (!analysis) {
|
|
80
|
+
continue; // only suggest posts we understand
|
|
81
|
+
}
|
|
82
|
+
const conceptText = analysis.concepts.map((c) => c.name).join(" ");
|
|
83
|
+
const tokens = tokenSet(`${post.text} ${analysis.topic} ${conceptText}`);
|
|
84
|
+
let score;
|
|
85
|
+
let reason;
|
|
86
|
+
if (profile.empty) {
|
|
87
|
+
score = 0.1;
|
|
88
|
+
reason = `Analyzed (${analysis.topic}) but not yet bookmarked.`;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const scored = scoreCandidate(profile, tokens);
|
|
92
|
+
if (scored.score <= 0) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
score = Number(scored.score.toFixed(4));
|
|
96
|
+
reason = `Matches your saved interest in ${scored.matched.join(", ")}.`;
|
|
97
|
+
}
|
|
98
|
+
const before = existing !== null;
|
|
99
|
+
store.suggestions.upsert({ postId: post.id, reason, score });
|
|
100
|
+
if (before) {
|
|
101
|
+
updated += 1;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
created += 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
created,
|
|
109
|
+
updated,
|
|
110
|
+
profileEmpty: profile.empty,
|
|
111
|
+
suggestions: store.suggestions.list("pending", limit),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=suggest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.js","sourceRoot":"","sources":["../../src/domain/suggest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Analysis, Post } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministically suggest tags for a post. Prefers, in order: existing tags,
|
|
4
|
+
* any #hashtags in the text, slugified concept names and topic words from the
|
|
5
|
+
* latest analysis, then falls back to the most significant terms in the text.
|
|
6
|
+
* Pure and stable — the same inputs always yield the same tags.
|
|
7
|
+
*/
|
|
8
|
+
export declare function suggestTags(post: Post, analysis: Analysis | null, existing?: string[]): string[];
|
|
9
|
+
//# sourceMappingURL=tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/domain/tags.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,GAAG,IAAI,EACzB,QAAQ,GAAE,MAAM,EAAO,GACtB,MAAM,EAAE,CAgCV"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { hashtags, significantTerms, slugify } from "../core/text.js";
|
|
2
|
+
const MAX_TAGS = 6;
|
|
3
|
+
/**
|
|
4
|
+
* Deterministically suggest tags for a post. Prefers, in order: existing tags,
|
|
5
|
+
* any #hashtags in the text, slugified concept names and topic words from the
|
|
6
|
+
* latest analysis, then falls back to the most significant terms in the text.
|
|
7
|
+
* Pure and stable — the same inputs always yield the same tags.
|
|
8
|
+
*/
|
|
9
|
+
export function suggestTags(post, analysis, existing = []) {
|
|
10
|
+
const ordered = [];
|
|
11
|
+
const seen = new Set();
|
|
12
|
+
const add = (raw) => {
|
|
13
|
+
const tag = slugify(raw);
|
|
14
|
+
if (tag && !seen.has(tag)) {
|
|
15
|
+
seen.add(tag);
|
|
16
|
+
ordered.push(tag);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
for (const tag of existing) {
|
|
20
|
+
add(tag);
|
|
21
|
+
}
|
|
22
|
+
for (const tag of hashtags(post.text)) {
|
|
23
|
+
add(tag);
|
|
24
|
+
}
|
|
25
|
+
if (analysis) {
|
|
26
|
+
for (const concept of analysis.concepts) {
|
|
27
|
+
add(concept.name);
|
|
28
|
+
}
|
|
29
|
+
for (const word of analysis.topic.split(/[^A-Za-z0-9]+/)) {
|
|
30
|
+
if (word.length >= 4) {
|
|
31
|
+
add(word);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const term of significantTerms(post.text, MAX_TAGS)) {
|
|
36
|
+
add(term);
|
|
37
|
+
}
|
|
38
|
+
return ordered.slice(0, MAX_TAGS);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/domain/tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAGtE,MAAM,QAAQ,GAAG,CAAC,CAAC;AAEnB;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,IAAU,EACV,QAAyB,EACzB,WAAqB,EAAE;IAEvB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,CAAC;IACX,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,GAAG,CAAC,GAAG,CAAC,CAAC;IACX,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;YACzD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACrB,GAAG,CAAC,IAAI,CAAC,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC;IAED,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Concept, ConceptRating } from "./schemas.js";
|
|
2
|
+
export type { Concept, ConceptRating };
|
|
3
|
+
export interface Post {
|
|
4
|
+
id: string;
|
|
5
|
+
externalId: string | null;
|
|
6
|
+
url: string | null;
|
|
7
|
+
authorUsername: string | null;
|
|
8
|
+
authorName: string | null;
|
|
9
|
+
text: string;
|
|
10
|
+
postedAt: string | null;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Analysis {
|
|
14
|
+
id: string;
|
|
15
|
+
postId: string;
|
|
16
|
+
provider: string;
|
|
17
|
+
model: string;
|
|
18
|
+
topic: string;
|
|
19
|
+
summary: string;
|
|
20
|
+
intent: string;
|
|
21
|
+
concepts: Concept[];
|
|
22
|
+
mock: boolean;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Account {
|
|
26
|
+
id: string;
|
|
27
|
+
username: string;
|
|
28
|
+
name: string | null;
|
|
29
|
+
followedAt: string;
|
|
30
|
+
lastRefreshedAt: string | null;
|
|
31
|
+
}
|
|
32
|
+
export interface TakeawaySnapshot {
|
|
33
|
+
id: string;
|
|
34
|
+
accountId: string;
|
|
35
|
+
provider: string;
|
|
36
|
+
model: string;
|
|
37
|
+
summary: string;
|
|
38
|
+
takeaways: string[];
|
|
39
|
+
sourcePostIds: string[];
|
|
40
|
+
postCount: number;
|
|
41
|
+
mock: boolean;
|
|
42
|
+
createdAt: string;
|
|
43
|
+
}
|
|
44
|
+
export interface Bookmark {
|
|
45
|
+
id: string;
|
|
46
|
+
postId: string;
|
|
47
|
+
tags: string[];
|
|
48
|
+
note: string | null;
|
|
49
|
+
source: string;
|
|
50
|
+
createdAt: string;
|
|
51
|
+
updatedAt: string;
|
|
52
|
+
}
|
|
53
|
+
export type SuggestionStatus = "pending" | "saved" | "dismissed";
|
|
54
|
+
export interface Suggestion {
|
|
55
|
+
id: string;
|
|
56
|
+
postId: string;
|
|
57
|
+
reason: string;
|
|
58
|
+
score: number;
|
|
59
|
+
status: SuggestionStatus;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
updatedAt: string;
|
|
62
|
+
}
|
|
63
|
+
export interface LearningDay {
|
|
64
|
+
day: number;
|
|
65
|
+
concept: string;
|
|
66
|
+
learn: string;
|
|
67
|
+
explain: string;
|
|
68
|
+
check: string;
|
|
69
|
+
}
|
|
70
|
+
export interface TrackDayProgress {
|
|
71
|
+
day: number;
|
|
72
|
+
notes: string | null;
|
|
73
|
+
completedAt: string;
|
|
74
|
+
}
|
|
75
|
+
export interface LearningTrack {
|
|
76
|
+
id: string;
|
|
77
|
+
analysisId: string;
|
|
78
|
+
minutesPerDay: number;
|
|
79
|
+
ratings: ConceptRating[];
|
|
80
|
+
days: LearningDay[];
|
|
81
|
+
progress: TrackDayProgress[];
|
|
82
|
+
createdAt: string;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/domain/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/domain/types.ts"],"names":[],"mappings":""}
|