@yolk-sdk/knowledge 0.0.1-canary.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/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/agent.d.mts +26 -0
- package/dist/agent.d.mts.map +1 -0
- package/dist/agent.mjs +45 -0
- package/dist/agent.mjs.map +1 -0
- package/dist/artifacts.d.mts +37 -0
- package/dist/artifacts.d.mts.map +1 -0
- package/dist/artifacts.mjs +28 -0
- package/dist/artifacts.mjs.map +1 -0
- package/dist/chunking.d.mts +38 -0
- package/dist/chunking.d.mts.map +1 -0
- package/dist/chunking.mjs +93 -0
- package/dist/chunking.mjs.map +1 -0
- package/dist/context.d.mts +16 -0
- package/dist/context.d.mts.map +1 -0
- package/dist/context.mjs +25 -0
- package/dist/context.mjs.map +1 -0
- package/dist/documents.d.mts +105 -0
- package/dist/documents.d.mts.map +1 -0
- package/dist/documents.mjs +93 -0
- package/dist/documents.mjs.map +1 -0
- package/dist/embeddings.d.mts +14 -0
- package/dist/embeddings.d.mts.map +1 -0
- package/dist/embeddings.mjs +8 -0
- package/dist/embeddings.mjs.map +1 -0
- package/dist/errors.d.mts +72 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +26 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/extraction.d.mts +19 -0
- package/dist/extraction.d.mts.map +1 -0
- package/dist/extraction.mjs +7 -0
- package/dist/extraction.mjs.map +1 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +5 -0
- package/dist/ingestion.d.mts +48 -0
- package/dist/ingestion.d.mts.map +1 -0
- package/dist/ingestion.mjs +111 -0
- package/dist/ingestion.mjs.map +1 -0
- package/dist/links.d.mts +17 -0
- package/dist/links.d.mts.map +1 -0
- package/dist/links.mjs +24 -0
- package/dist/links.mjs.map +1 -0
- package/dist/provenance.d.mts +20 -0
- package/dist/provenance.d.mts.map +1 -0
- package/dist/provenance.mjs +26 -0
- package/dist/provenance.mjs.map +1 -0
- package/dist/records.d.mts +59 -0
- package/dist/records.d.mts.map +1 -0
- package/dist/records.mjs +64 -0
- package/dist/records.mjs.map +1 -0
- package/dist/representations.d.mts +36 -0
- package/dist/representations.d.mts.map +1 -0
- package/dist/representations.mjs +44 -0
- package/dist/representations.mjs.map +1 -0
- package/dist/search-store.d.mts +77 -0
- package/dist/search-store.d.mts.map +1 -0
- package/dist/search-store.mjs +7 -0
- package/dist/search-store.mjs.map +1 -0
- package/dist/search.d.mts +49 -0
- package/dist/search.d.mts.map +1 -0
- package/dist/search.mjs +179 -0
- package/dist/search.mjs.map +1 -0
- package/dist/store.d.mts +44 -0
- package/dist/store.d.mts.map +1 -0
- package/dist/store.mjs +7 -0
- package/dist/store.mjs.map +1 -0
- package/dist/summarization.d.mts +23 -0
- package/dist/summarization.d.mts.map +1 -0
- package/dist/summarization.mjs +8 -0
- package/dist/summarization.mjs.map +1 -0
- package/dist/vector-store.d.mts +3 -0
- package/dist/vector-store.mjs +2 -0
- package/package.json +147 -0
- package/src/agent.ts +96 -0
- package/src/artifacts.ts +48 -0
- package/src/chunking.ts +175 -0
- package/src/context.ts +42 -0
- package/src/documents.ts +109 -0
- package/src/embeddings.ts +18 -0
- package/src/errors.ts +63 -0
- package/src/extraction.ts +21 -0
- package/src/index.ts +4 -0
- package/src/ingestion.ts +157 -0
- package/src/links.ts +23 -0
- package/src/provenance.ts +25 -0
- package/src/records.ts +76 -0
- package/src/representations.ts +51 -0
- package/src/search-store.ts +98 -0
- package/src/search.ts +270 -0
- package/src/store.ts +53 -0
- package/src/summarization.ts +28 -0
- package/src/vector-store.ts +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.mts","names":[],"sources":["../src/store.ts"],"mappings":";;;;;;;;;KAcY,uBAAA;EAAA,SACD,KAAA,EAAO,cAAc;EAAA,SACrB,EAAA;AAAA;AAAA,KAGC,yBAAA;EAAA,SACD,KAAA,EAAO,cAAc;EAAA,SACrB,KAAA;AAAA;AAAA,KAGC,0BAAA;EAAA,SACD,OAAA,EAAS,aAAa,CAAC,eAAA;AAAA;AAAA,KAGtB,wBAAA;EAAA,SACD,KAAA,EAAO,cAAc;EAAA,SACrB,KAAA;AAAA;AAAA,KAGC,yBAAA;EAAA,SACD,OAAA,EAAS,aAAA,CAAc,eAAA;EAAA,SACvB,eAAA,EAAiB,aAAA,CAAc,uBAAA;AAAA;AAAA,KAG9B,iBAAA;EAAA,SACD,YAAA,GAAe,KAAA,EAAO,0BAAA,KAA+B,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,mBAAA;EAAA,SACpF,YAAA,GAAe,KAAA,EAAO,0BAAA,KAA+B,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,mBAAA;EAAA,SACpF,SAAA,GAAY,KAAA,EAAO,uBAAA,KAA4B,MAAA,CAAO,MAAA,CAAO,eAAA,EAAiB,mBAAA;EAAA,SAC9E,WAAA,GAAc,KAAA,EAAO,yBAAA,KAA8B,MAAA,CAAO,MAAA,CAAO,0BAAA,EAA4B,mBAAA;EAAA,SAC7F,UAAA,GAAa,KAAA,EAAO,wBAAA,KAA6B,MAAA,CAAO,MAAA,CAAO,yBAAA,EAA2B,mBAAA;EAAA,SAC1F,YAAA,GAAe,KAAA,EAAO,uBAAA,KAA4B,MAAA,CAAO,MAAA,OAAa,mBAAA;EAAA,SACtE,aAAA,GAAgB,KAAA,EAAO,uBAAA,KAA4B,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,iBAAA,GAAoB,mBAAA;EAAA,SACnG,cAAA,GAAiB,KAAA,EAAO,uBAAA,KAA4B,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,mBAAA,GAAsB,mBAAA;EAAA,SACtG,SAAA,GAAY,KAAA,EAAO,uBAAA,KAA4B,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,aAAA,GAAgB,mBAAA;AAAA;AAAA,cACrG,mBAAA;cAEY,cAAA,SAAuB,mBAEnC"}
|
package/dist/store.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.mjs","names":[],"sources":["../src/store.ts"],"sourcesContent":["import { Context } from 'effect'\nimport type { Effect } from 'effect'\nimport type { KnowledgeArtifact } from './artifacts.ts'\nimport type { KnowledgeStoreError } from './errors.ts'\nimport type { KnowledgeLink } from './links.ts'\nimport type {\n CreateKnowledgeRecordInput,\n KnowledgeRecord,\n KnowledgeScope,\n UpdateKnowledgeRecordInput\n} from './records.ts'\nimport type { KnowledgeProvenance } from './provenance.ts'\nimport type { KnowledgeRepresentation } from './representations.ts'\n\nexport type GetKnowledgeRecordInput = {\n readonly scope: KnowledgeScope\n readonly id: string\n}\n\nexport type ListKnowledgeRecordsInput = {\n readonly scope: KnowledgeScope\n readonly limit: number\n}\n\nexport type ListKnowledgeRecordsResult = {\n readonly records: ReadonlyArray<KnowledgeRecord>\n}\n\nexport type ListPinnedKnowledgeInput = {\n readonly scope: KnowledgeScope\n readonly limit: number\n}\n\nexport type ListPinnedKnowledgeResult = {\n readonly records: ReadonlyArray<KnowledgeRecord>\n readonly representations: ReadonlyArray<KnowledgeRepresentation>\n}\n\nexport type KnowledgeStoreApi = {\n readonly createRecord: (input: CreateKnowledgeRecordInput) => Effect.Effect<KnowledgeRecord, KnowledgeStoreError>\n readonly updateRecord: (input: UpdateKnowledgeRecordInput) => Effect.Effect<KnowledgeRecord, KnowledgeStoreError>\n readonly getRecord: (input: GetKnowledgeRecordInput) => Effect.Effect<KnowledgeRecord, KnowledgeStoreError>\n readonly listRecords: (input: ListKnowledgeRecordsInput) => Effect.Effect<ListKnowledgeRecordsResult, KnowledgeStoreError>\n readonly listPinned: (input: ListPinnedKnowledgeInput) => Effect.Effect<ListPinnedKnowledgeResult, KnowledgeStoreError>\n readonly deleteRecord: (input: GetKnowledgeRecordInput) => Effect.Effect<void, KnowledgeStoreError>\n readonly listArtifacts: (input: GetKnowledgeRecordInput) => Effect.Effect<ReadonlyArray<KnowledgeArtifact>, KnowledgeStoreError>\n readonly listProvenance: (input: GetKnowledgeRecordInput) => Effect.Effect<ReadonlyArray<KnowledgeProvenance>, KnowledgeStoreError>\n readonly listLinks: (input: GetKnowledgeRecordInput) => Effect.Effect<ReadonlyArray<KnowledgeLink>, KnowledgeStoreError>\n}\n\nexport class KnowledgeStore extends Context.Service<KnowledgeStore, KnowledgeStoreApi>()(\n '@yolk-sdk/knowledge/KnowledgeStore'\n) {}\n"],"mappings":";;AAkDA,IAAa,iBAAb,cAAoC,QAAQ,QAA2C,EACrF,oCACF,EAAE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { KnowledgeMetadata } from "./documents.mjs";
|
|
2
|
+
import { KnowledgeSummarizationError } from "./errors.mjs";
|
|
3
|
+
import { Context, Effect, Layer } from "effect";
|
|
4
|
+
|
|
5
|
+
//#region src/summarization.d.ts
|
|
6
|
+
type KnowledgeDocumentSummary = {
|
|
7
|
+
readonly title?: string;
|
|
8
|
+
readonly summary?: string;
|
|
9
|
+
};
|
|
10
|
+
type SummarizeKnowledgeDocumentInput = {
|
|
11
|
+
readonly content: string;
|
|
12
|
+
readonly sourceTitle?: string;
|
|
13
|
+
readonly metadata?: KnowledgeMetadata;
|
|
14
|
+
};
|
|
15
|
+
type KnowledgeSummarizerApi = {
|
|
16
|
+
readonly summarize: (input: SummarizeKnowledgeDocumentInput) => Effect.Effect<KnowledgeDocumentSummary, KnowledgeSummarizationError>;
|
|
17
|
+
};
|
|
18
|
+
declare const KnowledgeSummarizer_base: Context.ServiceClass<KnowledgeSummarizer, "@yolk-sdk/knowledge/KnowledgeSummarizer", KnowledgeSummarizerApi>;
|
|
19
|
+
declare class KnowledgeSummarizer extends KnowledgeSummarizer_base {}
|
|
20
|
+
declare const NoopKnowledgeSummarizerLive: Layer.Layer<KnowledgeSummarizer, never, never>;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { KnowledgeDocumentSummary, KnowledgeSummarizer, KnowledgeSummarizerApi, NoopKnowledgeSummarizerLive, SummarizeKnowledgeDocumentInput };
|
|
23
|
+
//# sourceMappingURL=summarization.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarization.d.mts","names":[],"sources":["../src/summarization.ts"],"mappings":";;;;;KAIY,wBAAA;EAAA,SACD,KAAA;EAAA,SACA,OAAO;AAAA;AAAA,KAGN,+BAAA;EAAA,SACD,OAAA;EAAA,SACA,WAAA;EAAA,SACA,QAAA,GAAW,iBAAiB;AAAA;AAAA,KAG3B,sBAAA;EAAA,SACD,SAAA,GACP,KAAA,EAAO,+BAAA,KACJ,MAAA,CAAO,MAAA,CAAO,wBAAA,EAA0B,2BAAA;AAAA;AAAA,cAC9C,wBAAA;cAEY,mBAAA,SAA4B,wBAExC;AAAA,cAEY,2BAAA,EAA2B,KAAA,CAAA,KAAA,CAAA,mBAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
//#region src/summarization.ts
|
|
3
|
+
var KnowledgeSummarizer = class extends Context.Service()("@yolk-sdk/knowledge/KnowledgeSummarizer") {};
|
|
4
|
+
const NoopKnowledgeSummarizerLive = Layer.succeed(KnowledgeSummarizer, { summarize: (input) => Effect.succeed({ title: input.sourceTitle }) });
|
|
5
|
+
//#endregion
|
|
6
|
+
export { KnowledgeSummarizer, NoopKnowledgeSummarizerLive };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=summarization.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarization.mjs","names":[],"sources":["../src/summarization.ts"],"sourcesContent":["import { Context, Effect, Layer } from 'effect'\nimport type { KnowledgeMetadata } from './documents.ts'\nimport type { KnowledgeSummarizationError } from './errors.ts'\n\nexport type KnowledgeDocumentSummary = {\n readonly title?: string\n readonly summary?: string\n}\n\nexport type SummarizeKnowledgeDocumentInput = {\n readonly content: string\n readonly sourceTitle?: string\n readonly metadata?: KnowledgeMetadata\n}\n\nexport type KnowledgeSummarizerApi = {\n readonly summarize: (\n input: SummarizeKnowledgeDocumentInput\n ) => Effect.Effect<KnowledgeDocumentSummary, KnowledgeSummarizationError>\n}\n\nexport class KnowledgeSummarizer extends Context.Service<KnowledgeSummarizer, KnowledgeSummarizerApi>()(\n '@yolk-sdk/knowledge/KnowledgeSummarizer'\n) {}\n\nexport const NoopKnowledgeSummarizerLive = Layer.succeed(KnowledgeSummarizer, {\n summarize: input => Effect.succeed({ title: input.sourceTitle })\n})\n"],"mappings":";;AAqBA,IAAa,sBAAb,cAAyC,QAAQ,QAAqD,EACpG,yCACF,EAAE,CAAC;AAEH,MAAa,8BAA8B,MAAM,QAAQ,qBAAqB,EAC5E,YAAW,UAAS,OAAO,QAAQ,EAAE,OAAO,MAAM,YAAY,CAAC,EACjE,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { SearchIndexStoreError } from "./errors.mjs";
|
|
2
|
+
import { KnowledgeChunkSearchInput, KnowledgeChunkSearchResult, ReplaceKnowledgeDocumentChunksInput } from "./search-store.mjs";
|
|
3
|
+
export { type ReplaceKnowledgeDocumentChunksInput as VectorRecord, type KnowledgeChunkSearchInput as VectorSearchQuery, type KnowledgeChunkSearchResult as VectorSearchResult, SearchIndexStoreError as VectorStoreError };
|
package/package.json
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yolk-sdk/knowledge",
|
|
3
|
+
"version": "0.0.1-canary.0",
|
|
4
|
+
"description": "Domain-free knowledge record, artifact, provenance, and context contracts for Yolk agents.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/magoz/yolk-sdk.git",
|
|
11
|
+
"directory": "packages/knowledge"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/magoz/yolk-sdk/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/magoz/yolk-sdk#readme",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"knowledge",
|
|
19
|
+
"agents",
|
|
20
|
+
"context",
|
|
21
|
+
"provenance",
|
|
22
|
+
"effect"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22"
|
|
26
|
+
},
|
|
27
|
+
"exports": {
|
|
28
|
+
"./package.json": "./package.json",
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.mts",
|
|
31
|
+
"import": "./dist/index.mjs",
|
|
32
|
+
"default": "./dist/index.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./agent": {
|
|
35
|
+
"types": "./dist/agent.d.mts",
|
|
36
|
+
"import": "./dist/agent.mjs",
|
|
37
|
+
"default": "./dist/agent.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./artifacts": {
|
|
40
|
+
"types": "./dist/artifacts.d.mts",
|
|
41
|
+
"import": "./dist/artifacts.mjs",
|
|
42
|
+
"default": "./dist/artifacts.mjs"
|
|
43
|
+
},
|
|
44
|
+
"./context": {
|
|
45
|
+
"types": "./dist/context.d.mts",
|
|
46
|
+
"import": "./dist/context.mjs",
|
|
47
|
+
"default": "./dist/context.mjs"
|
|
48
|
+
},
|
|
49
|
+
"./chunking": {
|
|
50
|
+
"types": "./dist/chunking.d.mts",
|
|
51
|
+
"import": "./dist/chunking.mjs",
|
|
52
|
+
"default": "./dist/chunking.mjs"
|
|
53
|
+
},
|
|
54
|
+
"./embeddings": {
|
|
55
|
+
"types": "./dist/embeddings.d.mts",
|
|
56
|
+
"import": "./dist/embeddings.mjs",
|
|
57
|
+
"default": "./dist/embeddings.mjs"
|
|
58
|
+
},
|
|
59
|
+
"./errors": {
|
|
60
|
+
"types": "./dist/errors.d.mts",
|
|
61
|
+
"import": "./dist/errors.mjs",
|
|
62
|
+
"default": "./dist/errors.mjs"
|
|
63
|
+
},
|
|
64
|
+
"./extraction": {
|
|
65
|
+
"types": "./dist/extraction.d.mts",
|
|
66
|
+
"import": "./dist/extraction.mjs",
|
|
67
|
+
"default": "./dist/extraction.mjs"
|
|
68
|
+
},
|
|
69
|
+
"./ingestion": {
|
|
70
|
+
"types": "./dist/ingestion.d.mts",
|
|
71
|
+
"import": "./dist/ingestion.mjs",
|
|
72
|
+
"default": "./dist/ingestion.mjs"
|
|
73
|
+
},
|
|
74
|
+
"./documents": {
|
|
75
|
+
"types": "./dist/documents.d.mts",
|
|
76
|
+
"import": "./dist/documents.mjs",
|
|
77
|
+
"default": "./dist/documents.mjs"
|
|
78
|
+
},
|
|
79
|
+
"./search-store": {
|
|
80
|
+
"types": "./dist/search-store.d.mts",
|
|
81
|
+
"import": "./dist/search-store.mjs",
|
|
82
|
+
"default": "./dist/search-store.mjs"
|
|
83
|
+
},
|
|
84
|
+
"./links": {
|
|
85
|
+
"types": "./dist/links.d.mts",
|
|
86
|
+
"import": "./dist/links.mjs",
|
|
87
|
+
"default": "./dist/links.mjs"
|
|
88
|
+
},
|
|
89
|
+
"./records": {
|
|
90
|
+
"types": "./dist/records.d.mts",
|
|
91
|
+
"import": "./dist/records.mjs",
|
|
92
|
+
"default": "./dist/records.mjs"
|
|
93
|
+
},
|
|
94
|
+
"./provenance": {
|
|
95
|
+
"types": "./dist/provenance.d.mts",
|
|
96
|
+
"import": "./dist/provenance.mjs",
|
|
97
|
+
"default": "./dist/provenance.mjs"
|
|
98
|
+
},
|
|
99
|
+
"./representations": {
|
|
100
|
+
"types": "./dist/representations.d.mts",
|
|
101
|
+
"import": "./dist/representations.mjs",
|
|
102
|
+
"default": "./dist/representations.mjs"
|
|
103
|
+
},
|
|
104
|
+
"./search": {
|
|
105
|
+
"types": "./dist/search.d.mts",
|
|
106
|
+
"import": "./dist/search.mjs",
|
|
107
|
+
"default": "./dist/search.mjs"
|
|
108
|
+
},
|
|
109
|
+
"./store": {
|
|
110
|
+
"types": "./dist/store.d.mts",
|
|
111
|
+
"import": "./dist/store.mjs",
|
|
112
|
+
"default": "./dist/store.mjs"
|
|
113
|
+
},
|
|
114
|
+
"./summarization": {
|
|
115
|
+
"types": "./dist/summarization.d.mts",
|
|
116
|
+
"import": "./dist/summarization.mjs",
|
|
117
|
+
"default": "./dist/summarization.mjs"
|
|
118
|
+
},
|
|
119
|
+
"./vector-store": {
|
|
120
|
+
"types": "./dist/vector-store.d.mts",
|
|
121
|
+
"import": "./dist/vector-store.mjs",
|
|
122
|
+
"default": "./dist/vector-store.mjs"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"files": [
|
|
126
|
+
"src/**/*.ts",
|
|
127
|
+
"!src/**/*.test.ts",
|
|
128
|
+
"!src/**/*.test.tsx",
|
|
129
|
+
"dist/**/*",
|
|
130
|
+
"README.md"
|
|
131
|
+
],
|
|
132
|
+
"publishConfig": {
|
|
133
|
+
"access": "public",
|
|
134
|
+
"provenance": true
|
|
135
|
+
},
|
|
136
|
+
"dependencies": {
|
|
137
|
+
"effect": "4.0.0-beta.65",
|
|
138
|
+
"gpt-tokenizer": "^3.4.0",
|
|
139
|
+
"@yolk-sdk/agent": "^0.0.1-canary.0"
|
|
140
|
+
},
|
|
141
|
+
"scripts": {
|
|
142
|
+
"build": "tsdown",
|
|
143
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
144
|
+
"test": "vitest run --passWithNoTests",
|
|
145
|
+
"test:run": "vitest run --passWithNoTests"
|
|
146
|
+
}
|
|
147
|
+
}
|
package/src/agent.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Effect } from 'effect'
|
|
2
|
+
import * as Schema from 'effect/Schema'
|
|
3
|
+
import { ToolError } from '@yolk-sdk/agent/loop'
|
|
4
|
+
import { ToolResult } from '@yolk-sdk/agent/protocol'
|
|
5
|
+
import { makeTool, type ToolRegistration } from '@yolk-sdk/agent/tools'
|
|
6
|
+
import type { KnowledgeScope } from './records.ts'
|
|
7
|
+
import type { KnowledgeSearchScope } from './documents.ts'
|
|
8
|
+
import type { KnowledgeSearcher } from './search.ts'
|
|
9
|
+
import { packKnowledgeSearchContext } from './search.ts'
|
|
10
|
+
|
|
11
|
+
export type ResolveKnowledgeScope<Context> = (context: Context) => KnowledgeScope
|
|
12
|
+
|
|
13
|
+
export type KnowledgeAgentContextOptions = {
|
|
14
|
+
readonly maxPinnedContextCharacters: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const defaultKnowledgeAgentContextOptions: KnowledgeAgentContextOptions = {
|
|
18
|
+
maxPinnedContextCharacters: 6000
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const KnowledgeSearchToolParams = Schema.Struct({
|
|
22
|
+
query: Schema.Trimmed.pipe(
|
|
23
|
+
Schema.check(Schema.isNonEmpty()),
|
|
24
|
+
Schema.annotate({ description: 'Search query for the configured knowledge search.' })
|
|
25
|
+
)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const isToolError = Schema.is(ToolError)
|
|
29
|
+
|
|
30
|
+
export type KnowledgeSearchToolScopeResolver<Context> =
|
|
31
|
+
| KnowledgeSearchScope
|
|
32
|
+
| ((context: Context) => Effect.Effect<KnowledgeSearchScope, ToolError>)
|
|
33
|
+
|
|
34
|
+
export type MakeKnowledgeSearchToolOptions<Context> = {
|
|
35
|
+
readonly scope: KnowledgeSearchToolScopeResolver<Context>
|
|
36
|
+
readonly name?: string
|
|
37
|
+
readonly description?: string
|
|
38
|
+
readonly limit?: number
|
|
39
|
+
readonly minScore?: number
|
|
40
|
+
readonly contextChunks?: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const resolveScope = <Context>(resolver: KnowledgeSearchToolScopeResolver<Context>, context: Context) => {
|
|
44
|
+
if (typeof resolver === 'function') {
|
|
45
|
+
return resolver(context)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return Effect.succeed(resolver)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const makeKnowledgeSearchTool = <Context>(
|
|
52
|
+
searcher: KnowledgeSearcher,
|
|
53
|
+
options: MakeKnowledgeSearchToolOptions<Context>
|
|
54
|
+
): ToolRegistration<Context> => {
|
|
55
|
+
const name = options.name ?? 'search_knowledge'
|
|
56
|
+
|
|
57
|
+
return makeTool({
|
|
58
|
+
name,
|
|
59
|
+
description: options.description ?? 'Search the configured knowledge search.',
|
|
60
|
+
parameters: KnowledgeSearchToolParams,
|
|
61
|
+
access: 'read',
|
|
62
|
+
invalidParamsMessage: error => error instanceof Error ? error.message : String(error),
|
|
63
|
+
execute: input =>
|
|
64
|
+
resolveScope(options.scope, input.context).pipe(
|
|
65
|
+
Effect.flatMap(scope =>
|
|
66
|
+
searcher.search({
|
|
67
|
+
scope,
|
|
68
|
+
query: input.params.query,
|
|
69
|
+
limit: options.limit,
|
|
70
|
+
minScore: options.minScore,
|
|
71
|
+
contextChunks: options.contextChunks
|
|
72
|
+
})
|
|
73
|
+
),
|
|
74
|
+
Effect.map(results => packKnowledgeSearchContext(input.params.query, results)),
|
|
75
|
+
Effect.map(
|
|
76
|
+
context =>
|
|
77
|
+
ToolResult.make({
|
|
78
|
+
toolCallId: input.call.id,
|
|
79
|
+
content: context.text,
|
|
80
|
+
structuredContent: context
|
|
81
|
+
})
|
|
82
|
+
),
|
|
83
|
+
Effect.mapError(error => {
|
|
84
|
+
if (isToolError(error)) {
|
|
85
|
+
return error
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return new ToolError({
|
|
89
|
+
tool: input.call.name,
|
|
90
|
+
message: error.message,
|
|
91
|
+
cause: 'execution'
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
)
|
|
95
|
+
})
|
|
96
|
+
}
|
package/src/artifacts.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Context } from 'effect'
|
|
2
|
+
import type { Effect } from 'effect'
|
|
3
|
+
import * as Schema from 'effect/Schema'
|
|
4
|
+
import type { KnowledgeArtifactError } from './errors.ts'
|
|
5
|
+
import { KnowledgeMetadataSchema, NonEmptyTrimmedString, NonNegativeInteger } from './records.ts'
|
|
6
|
+
|
|
7
|
+
export const KnowledgeArtifactKindSchema = Schema.Literals([
|
|
8
|
+
'original',
|
|
9
|
+
'extracted_text',
|
|
10
|
+
'thumbnail',
|
|
11
|
+
'transcript',
|
|
12
|
+
'caption',
|
|
13
|
+
'structured'
|
|
14
|
+
])
|
|
15
|
+
export type KnowledgeArtifactKind = Schema.Schema.Type<typeof KnowledgeArtifactKindSchema>
|
|
16
|
+
|
|
17
|
+
export const KnowledgeArtifactSchema = Schema.Struct({
|
|
18
|
+
id: NonEmptyTrimmedString,
|
|
19
|
+
recordId: NonEmptyTrimmedString,
|
|
20
|
+
kind: KnowledgeArtifactKindSchema,
|
|
21
|
+
storageKey: NonEmptyTrimmedString,
|
|
22
|
+
mediaType: Schema.optional(NonEmptyTrimmedString),
|
|
23
|
+
byteSize: Schema.optional(NonNegativeInteger),
|
|
24
|
+
checksum: Schema.optional(NonEmptyTrimmedString),
|
|
25
|
+
metadata: Schema.optional(KnowledgeMetadataSchema),
|
|
26
|
+
createdAt: Schema.DateTimeUtc
|
|
27
|
+
})
|
|
28
|
+
export type KnowledgeArtifact = Schema.Schema.Type<typeof KnowledgeArtifactSchema>
|
|
29
|
+
|
|
30
|
+
export type PutKnowledgeArtifactInput = {
|
|
31
|
+
readonly storageKey: string
|
|
32
|
+
readonly mediaType?: string
|
|
33
|
+
readonly bytes: Uint8Array
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type GetKnowledgeArtifactInput = {
|
|
37
|
+
readonly storageKey: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type KnowledgeArtifactStoreApi = {
|
|
41
|
+
readonly putArtifact: (input: PutKnowledgeArtifactInput) => Effect.Effect<void, KnowledgeArtifactError>
|
|
42
|
+
readonly getArtifact: (input: GetKnowledgeArtifactInput) => Effect.Effect<Uint8Array, KnowledgeArtifactError>
|
|
43
|
+
readonly deleteArtifact: (input: GetKnowledgeArtifactInput) => Effect.Effect<void, KnowledgeArtifactError>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class KnowledgeArtifactStore extends Context.Service<KnowledgeArtifactStore, KnowledgeArtifactStoreApi>()(
|
|
47
|
+
'@yolk-sdk/knowledge/KnowledgeArtifactStore'
|
|
48
|
+
) {}
|
package/src/chunking.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from 'effect'
|
|
2
|
+
import { countTokens, decode, encode } from 'gpt-tokenizer/encoding/o200k_base'
|
|
3
|
+
import type { KnowledgeChunk, KnowledgeMetadata } from './documents.ts'
|
|
4
|
+
import { KnowledgeChunkingError } from './errors.ts'
|
|
5
|
+
|
|
6
|
+
const SENTENCE_PATTERN = /[^.!?]+[.!?]+(?:["')\]]+)?\s*|[^.!?]+$/g
|
|
7
|
+
const PARAGRAPH_BREAK_PATTERN = /(\n{2,})/
|
|
8
|
+
const WORD_PATTERN = /\S+\s*/g
|
|
9
|
+
|
|
10
|
+
export type ChunkKnowledgeDocumentInput = {
|
|
11
|
+
readonly collectionId: string
|
|
12
|
+
readonly documentId: string
|
|
13
|
+
readonly content: string
|
|
14
|
+
readonly maxTokens?: number
|
|
15
|
+
readonly metadata?: KnowledgeMetadata
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type KnowledgeChunkerApi = {
|
|
19
|
+
readonly chunk: (
|
|
20
|
+
input: ChunkKnowledgeDocumentInput
|
|
21
|
+
) => Effect.Effect<ReadonlyArray<KnowledgeChunk>, KnowledgeChunkingError>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class KnowledgeChunker extends Context.Service<KnowledgeChunker, KnowledgeChunkerApi>()(
|
|
25
|
+
'@yolk-sdk/knowledge/KnowledgeChunker'
|
|
26
|
+
) {}
|
|
27
|
+
|
|
28
|
+
export const countKnowledgeChunkTokens = (text: string) => countTokens(text)
|
|
29
|
+
|
|
30
|
+
const sanitizeText = (text: string) =>
|
|
31
|
+
text
|
|
32
|
+
.replace(/\r\n/g, '\n')
|
|
33
|
+
.replace(/[\t ]+/g, ' ')
|
|
34
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
35
|
+
.trim()
|
|
36
|
+
|
|
37
|
+
const splitSentences = (text: string) =>
|
|
38
|
+
text
|
|
39
|
+
.split(PARAGRAPH_BREAK_PATTERN)
|
|
40
|
+
.flatMap(part => {
|
|
41
|
+
if (part.length === 0) {
|
|
42
|
+
return []
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (/^\n{2,}$/.test(part)) {
|
|
46
|
+
return ['\n\n']
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return part.match(SENTENCE_PATTERN) ?? [part]
|
|
50
|
+
})
|
|
51
|
+
.filter(unit => unit.length > 0)
|
|
52
|
+
|
|
53
|
+
const splitEncodedTokens = (text: string, maxTokens: number) => {
|
|
54
|
+
const tokens = encode(text)
|
|
55
|
+
return Array.from({ length: Math.ceil(tokens.length / maxTokens) }, (_, index) =>
|
|
56
|
+
decode(tokens.slice(index * maxTokens, index * maxTokens + maxTokens)).trim()
|
|
57
|
+
).filter(chunk => chunk.length > 0)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const splitOversizedUnit = (text: string, maxTokens: number) => {
|
|
61
|
+
const words = text.match(WORD_PATTERN) ?? []
|
|
62
|
+
const chunks: string[] = []
|
|
63
|
+
let current = ''
|
|
64
|
+
let currentTokenCount = 0
|
|
65
|
+
|
|
66
|
+
for (const word of words) {
|
|
67
|
+
const wordTokenCount = countTokens(word)
|
|
68
|
+
|
|
69
|
+
if (wordTokenCount > maxTokens) {
|
|
70
|
+
const currentChunk = current.trim()
|
|
71
|
+
if (currentChunk.length > 0) {
|
|
72
|
+
chunks.push(currentChunk)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
chunks.push(...splitEncodedTokens(word, maxTokens))
|
|
76
|
+
current = ''
|
|
77
|
+
currentTokenCount = 0
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (currentTokenCount > 0 && currentTokenCount + wordTokenCount > maxTokens) {
|
|
82
|
+
const currentChunk = current.trim()
|
|
83
|
+
if (currentChunk.length > 0) {
|
|
84
|
+
chunks.push(currentChunk)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
current = word
|
|
88
|
+
currentTokenCount = wordTokenCount
|
|
89
|
+
continue
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
current = `${current}${word}`
|
|
93
|
+
currentTokenCount += wordTokenCount
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const finalChunk = current.trim()
|
|
97
|
+
if (finalChunk.length > 0) {
|
|
98
|
+
chunks.push(finalChunk)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return chunks
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const splitUnitsBySize = (units: ReadonlyArray<string>, maxTokens: number) =>
|
|
105
|
+
units.flatMap(unit =>
|
|
106
|
+
countTokens(unit) <= maxTokens ? [unit] : splitOversizedUnit(unit, maxTokens)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
const buildChunkContents = (units: ReadonlyArray<string>, maxTokens: number) => {
|
|
110
|
+
const chunks: string[] = []
|
|
111
|
+
let current = ''
|
|
112
|
+
let currentTokenCount = 0
|
|
113
|
+
|
|
114
|
+
const pushCurrent = () => {
|
|
115
|
+
const content = current.trim()
|
|
116
|
+
if (content.length > 0) {
|
|
117
|
+
chunks.push(content)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const unit of units) {
|
|
122
|
+
const unitTokenCount = countTokens(unit)
|
|
123
|
+
|
|
124
|
+
if (currentTokenCount > 0 && currentTokenCount + unitTokenCount > maxTokens) {
|
|
125
|
+
pushCurrent()
|
|
126
|
+
current = unit
|
|
127
|
+
currentTokenCount = unitTokenCount
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
current = `${current}${unit}`
|
|
132
|
+
currentTokenCount += unitTokenCount
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
pushCurrent()
|
|
136
|
+
return chunks
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const chunkKnowledgeText = (input: ChunkKnowledgeDocumentInput, maxTokens: number) =>
|
|
140
|
+
Effect.gen(function* () {
|
|
141
|
+
if (!Number.isInteger(maxTokens) || maxTokens < 1) {
|
|
142
|
+
return yield* Effect.fail(
|
|
143
|
+
new KnowledgeChunkingError({ message: 'Chunk maxTokens must be a positive integer' })
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const sanitized = sanitizeText(input.content)
|
|
148
|
+
if (sanitized.length === 0) {
|
|
149
|
+
return yield* Effect.fail(new KnowledgeChunkingError({ message: 'Cannot chunk empty content' }))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const units = splitUnitsBySize(splitSentences(sanitized), maxTokens)
|
|
153
|
+
const contents = buildChunkContents(units, maxTokens)
|
|
154
|
+
|
|
155
|
+
if (contents.length === 0) {
|
|
156
|
+
return yield* Effect.fail(new KnowledgeChunkingError({ message: 'No chunks produced' }))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return contents.map((content, position) => ({
|
|
160
|
+
id: `${input.documentId}:chunk:${position}`,
|
|
161
|
+
collectionId: input.collectionId,
|
|
162
|
+
documentId: input.documentId,
|
|
163
|
+
content,
|
|
164
|
+
position,
|
|
165
|
+
tokenCount: countTokens(content),
|
|
166
|
+
metadata: input.metadata
|
|
167
|
+
})) satisfies ReadonlyArray<KnowledgeChunk>
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
export const makeDefaultKnowledgeChunker = (input: { readonly maxTokens: number }): KnowledgeChunkerApi => ({
|
|
171
|
+
chunk: document => chunkKnowledgeText(document, document.maxTokens ?? input.maxTokens)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
export const DefaultKnowledgeChunkerLive = (input: { readonly maxTokens: number } = { maxTokens: 512 }) =>
|
|
175
|
+
Layer.succeed(KnowledgeChunker, makeDefaultKnowledgeChunker(input))
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Array as Arr } from 'effect'
|
|
2
|
+
import type { KnowledgeRecord } from './records.ts'
|
|
3
|
+
import type { KnowledgeRepresentation } from './representations.ts'
|
|
4
|
+
|
|
5
|
+
export type KnowledgeContextItem = {
|
|
6
|
+
readonly record: KnowledgeRecord
|
|
7
|
+
readonly representation?: KnowledgeRepresentation
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type BuildKnowledgeContextInput = {
|
|
11
|
+
readonly items: ReadonlyArray<KnowledgeContextItem>
|
|
12
|
+
readonly maxCharacters: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const truncationMarker = '\n\n[truncated: pinned knowledge exceeded context budget]'
|
|
16
|
+
|
|
17
|
+
const recordHeader = (record: KnowledgeRecord) =>
|
|
18
|
+
`## ${record.title}\nrole: ${record.role}\nstatus: ${record.status}\ncontext: ${record.contextPolicy}`
|
|
19
|
+
|
|
20
|
+
const itemBody = (item: KnowledgeContextItem) => {
|
|
21
|
+
const representationText = item.representation?.summary ?? item.representation?.contentText
|
|
22
|
+
return [recordHeader(item.record), item.record.summary, representationText]
|
|
23
|
+
.filter(section => section !== undefined && section.trim().length > 0)
|
|
24
|
+
.join('\n')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const buildKnowledgeContext = (input: BuildKnowledgeContextInput) => {
|
|
28
|
+
const sections = Arr.map(input.items, itemBody).filter(section => section.trim().length > 0)
|
|
29
|
+
const header = '# Pinned knowledge\nUse this durable user knowledge as high-priority context. Cite knowledge records when relevant.'
|
|
30
|
+
const body = sections.join('\n\n')
|
|
31
|
+
const context = body.length === 0 ? '' : `${header}\n\n${body}`
|
|
32
|
+
|
|
33
|
+
if (context.length <= input.maxCharacters) {
|
|
34
|
+
return context
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (input.maxCharacters <= truncationMarker.length) {
|
|
38
|
+
return context.slice(0, input.maxCharacters).trimEnd()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return `${context.slice(0, input.maxCharacters - truncationMarker.length).trimEnd()}${truncationMarker}`
|
|
42
|
+
}
|