@alfe.ai/openclaw-knowledge 0.0.18 → 0.0.20

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 ADDED
@@ -0,0 +1,47 @@
1
+ # `@alfe.ai/openclaw-knowledge`
2
+
3
+ OpenClaw tools for shared, scoped knowledge about an organization, team, or
4
+ project. Shared knowledge consists of curated documents and a structured scope
5
+ profile. Quick or uncertain capture belongs in private per-agent memory; there
6
+ is no shared free-floating facts primitive.
7
+
8
+ The plugin exposes seven tools:
9
+
10
+ - `resource_search` searches the RAG projection and returns document paths.
11
+ - `resource_read_doc` reads a bounded document by explicit scope and path.
12
+ - `resource_write_doc` writes a document while retaining revision history.
13
+ - `resource_get_profile` reads one scope profile.
14
+ - `resource_list_scopes` discovers exact member scope IDs.
15
+ - `resource_propose_change` opens an inert review request for a non-member scope.
16
+ - `resource_list_change_requests` pages through the agent's own proposals.
17
+
18
+ ## Boundary and authorization model
19
+
20
+ Every resource operation takes an explicit `scopeType` and `scopeId`. The org
21
+ service remains the system of record and enforces membership for reads/direct
22
+ writes; the knowledge service is only the searchable projection. A proposal
23
+ does not grant read access and changes nothing until an authorized reviewer
24
+ approves it.
25
+
26
+ Runtime validation mirrors the service limits for queries, identifiers, paths,
27
+ documents, profiles, and proposal pages. Direct document downloads stop at the
28
+ 2 MiB index boundary, while the model-facing read tool uses a 256 KiB cap and
29
+ directs larger reads to the synced `shared/` workspace. Session-start context
30
+ is escaped, line-bounded, and capped at 16 KiB because profile and scope names
31
+ are shared data, not trusted prompt instructions.
32
+
33
+ ## Development
34
+
35
+ ```bash
36
+ pnpm --filter @alfe.ai/openclaw-knowledge lint
37
+ pnpm --filter @alfe.ai/openclaw-knowledge typecheck
38
+ pnpm --filter @alfe.ai/openclaw-knowledge test
39
+ pnpm --filter @alfe.ai/openclaw-knowledge build
40
+ ```
41
+
42
+ The package publishes ESM and CJS entrypoints. Its default-only plugin entry
43
+ and complete static tool catalog must stay aligned with
44
+ `openclaw.plugin.json`.
45
+
46
+ Part of [Alfe](https://alfe.ai). See the [documentation](https://docs.alfe.ai)
47
+ for platform setup.
package/dist/index.d.cts CHANGED
@@ -1,101 +1,2 @@
1
- import plugin from "./plugin.cjs";
2
-
3
- //#region ../agent-api-client/dist/index.d.ts
4
-
5
- type KnowledgeScopeType = "org" | "team" | "project";
6
- interface KnowledgeScope {
7
- scopeType: KnowledgeScopeType;
8
- scopeId: string;
9
- name: string;
10
- }
11
- interface KnowledgeSearchHit {
12
- id: string;
13
- text: string;
14
- /** Normalized relevance in (0,1]; higher = closer. */
15
- score: number;
16
- scopeType: KnowledgeScopeType;
17
- scopeId: string;
18
- /**
19
- * Provenance of the hit. All live results are `"doc"`; `"fact"` only ever
20
- * appears for legacy vectors indexed before the facts primitive was removed
21
- * (the search index stays tolerant of them). Treat every hit as a doc.
22
- */
23
- source: "doc" | "fact";
24
- /** The canonical file under shared/<scope>/ (present on doc hits). */
25
- filePath?: string;
26
- /** Legacy-only: the id of a pre-removal fact vector. */
27
- factId?: string;
28
- }
29
- interface KnowledgeSearchResult {
30
- results: KnowledgeSearchHit[];
31
- /** True when fan-out breadth was capped (more member scopes than the cap). */
32
- truncatedScopes: boolean;
33
- }
34
- interface KnowledgeProfileLink {
35
- label: string;
36
- url: string;
37
- }
38
- interface KnowledgeProfile {
39
- scopeType: KnowledgeScopeType;
40
- scopeId: string;
41
- about: string | null;
42
- description: string | null;
43
- links: KnowledgeProfileLink[];
44
- updatedAt: string | null;
45
- updatedBy: string | null;
46
- }
47
- interface KnowledgeDoc {
48
- filePath: string;
49
- fileName: string;
50
- contentType?: string;
51
- size: number;
52
- uploadedBy?: string;
53
- createdAt: string;
54
- updatedAt: string;
55
- }
56
- //#endregion
57
- //#region src/types.d.ts
58
- interface KnowledgeConfig {
59
- /** Inject org profile + name-only scope list at session start. */
60
- injectContext: boolean;
61
- /** Cap on scopes listed in the session-start context block. */
62
- maxScopes: number;
63
- }
64
- /**
65
- * The subset of `AgentApiClient` the plugin needs. Declaring it as an
66
- * interface (rather than importing the concrete class everywhere) keeps the
67
- * injection/formatting code decoupled and unit-testable — the real
68
- * `AgentApiClient` structurally satisfies it.
69
- */
70
- interface KnowledgeApi {
71
- knowledgeSearch(query: string, opts?: {
72
- limit?: number;
73
- scopeType?: KnowledgeScopeType;
74
- scopeId?: string;
75
- }): Promise<KnowledgeSearchResult>;
76
- listScopes(): Promise<{
77
- scopes: KnowledgeScope[];
78
- }>;
79
- getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
80
- listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
81
- limit?: number;
82
- cursor?: string;
83
- }): Promise<{
84
- files: KnowledgeDoc[];
85
- nextCursor: string | null;
86
- }>;
87
- readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string): Promise<{
88
- filePath: string;
89
- text: string;
90
- }>;
91
- writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
92
- contentType?: string;
93
- message?: string;
94
- }): Promise<{
95
- filePath: string;
96
- }>;
97
- }
98
- //# sourceMappingURL=types.d.ts.map
99
- //#endregion
100
- export { type KnowledgeApi, type KnowledgeConfig, type KnowledgeDoc, type KnowledgeProfile, type KnowledgeScope, type KnowledgeScopeType, type KnowledgeSearchResult, plugin as default };
101
- //# sourceMappingURL=index.d.cts.map
1
+ import { a as KnowledgeChangeRequest, c as KnowledgeScope, d as ProposeScopeChangeInput, i as ChangeRequestStatus, l as KnowledgeScopeType, n as KnowledgeApi, o as KnowledgeDoc, r as KnowledgeConfig, s as KnowledgeProfile, t as plugin, u as KnowledgeSearchResult } from "./plugin.cjs";
2
+ export { type ChangeRequestStatus, type KnowledgeApi, type KnowledgeChangeRequest, type KnowledgeConfig, type KnowledgeDoc, type KnowledgeProfile, type KnowledgeScope, type KnowledgeScopeType, type KnowledgeSearchResult, type ProposeScopeChangeInput, plugin as default };
package/dist/index.d.ts CHANGED
@@ -1,101 +1,2 @@
1
- import plugin from "./plugin.js";
2
-
3
- //#region ../agent-api-client/dist/index.d.ts
4
-
5
- type KnowledgeScopeType = "org" | "team" | "project";
6
- interface KnowledgeScope {
7
- scopeType: KnowledgeScopeType;
8
- scopeId: string;
9
- name: string;
10
- }
11
- interface KnowledgeSearchHit {
12
- id: string;
13
- text: string;
14
- /** Normalized relevance in (0,1]; higher = closer. */
15
- score: number;
16
- scopeType: KnowledgeScopeType;
17
- scopeId: string;
18
- /**
19
- * Provenance of the hit. All live results are `"doc"`; `"fact"` only ever
20
- * appears for legacy vectors indexed before the facts primitive was removed
21
- * (the search index stays tolerant of them). Treat every hit as a doc.
22
- */
23
- source: "doc" | "fact";
24
- /** The canonical file under shared/<scope>/ (present on doc hits). */
25
- filePath?: string;
26
- /** Legacy-only: the id of a pre-removal fact vector. */
27
- factId?: string;
28
- }
29
- interface KnowledgeSearchResult {
30
- results: KnowledgeSearchHit[];
31
- /** True when fan-out breadth was capped (more member scopes than the cap). */
32
- truncatedScopes: boolean;
33
- }
34
- interface KnowledgeProfileLink {
35
- label: string;
36
- url: string;
37
- }
38
- interface KnowledgeProfile {
39
- scopeType: KnowledgeScopeType;
40
- scopeId: string;
41
- about: string | null;
42
- description: string | null;
43
- links: KnowledgeProfileLink[];
44
- updatedAt: string | null;
45
- updatedBy: string | null;
46
- }
47
- interface KnowledgeDoc {
48
- filePath: string;
49
- fileName: string;
50
- contentType?: string;
51
- size: number;
52
- uploadedBy?: string;
53
- createdAt: string;
54
- updatedAt: string;
55
- }
56
- //#endregion
57
- //#region src/types.d.ts
58
- interface KnowledgeConfig {
59
- /** Inject org profile + name-only scope list at session start. */
60
- injectContext: boolean;
61
- /** Cap on scopes listed in the session-start context block. */
62
- maxScopes: number;
63
- }
64
- /**
65
- * The subset of `AgentApiClient` the plugin needs. Declaring it as an
66
- * interface (rather than importing the concrete class everywhere) keeps the
67
- * injection/formatting code decoupled and unit-testable — the real
68
- * `AgentApiClient` structurally satisfies it.
69
- */
70
- interface KnowledgeApi {
71
- knowledgeSearch(query: string, opts?: {
72
- limit?: number;
73
- scopeType?: KnowledgeScopeType;
74
- scopeId?: string;
75
- }): Promise<KnowledgeSearchResult>;
76
- listScopes(): Promise<{
77
- scopes: KnowledgeScope[];
78
- }>;
79
- getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
80
- listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
81
- limit?: number;
82
- cursor?: string;
83
- }): Promise<{
84
- files: KnowledgeDoc[];
85
- nextCursor: string | null;
86
- }>;
87
- readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string): Promise<{
88
- filePath: string;
89
- text: string;
90
- }>;
91
- writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
92
- contentType?: string;
93
- message?: string;
94
- }): Promise<{
95
- filePath: string;
96
- }>;
97
- }
98
- //# sourceMappingURL=types.d.ts.map
99
- //#endregion
100
- export { type KnowledgeApi, type KnowledgeConfig, type KnowledgeDoc, type KnowledgeProfile, type KnowledgeScope, type KnowledgeScopeType, type KnowledgeSearchResult, plugin as default };
101
- //# sourceMappingURL=index.d.ts.map
1
+ import { a as KnowledgeChangeRequest, c as KnowledgeScope, d as ProposeScopeChangeInput, i as ChangeRequestStatus, l as KnowledgeScopeType, n as KnowledgeApi, o as KnowledgeDoc, r as KnowledgeConfig, s as KnowledgeProfile, t as plugin, u as KnowledgeSearchResult } from "./plugin.js";
2
+ export { type ChangeRequestStatus, type KnowledgeApi, type KnowledgeChangeRequest, type KnowledgeConfig, type KnowledgeDoc, type KnowledgeProfile, type KnowledgeScope, type KnowledgeScopeType, type KnowledgeSearchResult, type ProposeScopeChangeInput, plugin as default };
package/dist/plugin.d.cts CHANGED
@@ -1,70 +1,207 @@
1
- //#region src/plugin.d.ts
1
+ import { TSchema } from "@sinclair/typebox";
2
+
3
+ //#region ../agent-api-client/dist/index.d.ts
4
+
5
+ //# sourceMappingURL=sync.d.ts.map
6
+ //#endregion
7
+ //#region src/domains/knowledge.d.ts
8
+ type KnowledgeScopeType = "org" | "team" | "project";
9
+ interface KnowledgeScope {
10
+ scopeType: KnowledgeScopeType;
11
+ scopeId: string;
12
+ name: string;
13
+ }
14
+ interface KnowledgeSearchHit {
15
+ id: string;
16
+ text: string;
17
+ /** Normalized relevance in (0,1]; higher = closer. */
18
+ score: number;
19
+ scopeType: KnowledgeScopeType;
20
+ scopeId: string;
21
+ /**
22
+ * Provenance of the hit. All live results are `"doc"`; `"fact"` only ever
23
+ * appears for legacy vectors indexed before the facts primitive was removed
24
+ * (the search index stays tolerant of them). Treat every hit as a doc.
25
+ */
26
+ source: "doc" | "fact";
27
+ /** The canonical file under shared/<scope>/ (present on doc hits). */
28
+ filePath?: string;
29
+ /** Legacy-only: the id of a pre-removal fact vector. */
30
+ factId?: string;
31
+ }
32
+ interface KnowledgeSearchResult {
33
+ results: KnowledgeSearchHit[];
34
+ /** True when fan-out breadth was capped (more member scopes than the cap). */
35
+ truncatedScopes: boolean;
36
+ }
37
+ interface KnowledgeProfileLink {
38
+ label: string;
39
+ url: string;
40
+ }
41
+ interface KnowledgeProfile {
42
+ scopeType: KnowledgeScopeType;
43
+ scopeId: string;
44
+ about: string | null;
45
+ description: string | null;
46
+ links: KnowledgeProfileLink[];
47
+ updatedAt: string | null;
48
+ updatedBy: string | null;
49
+ }
50
+ type ChangeRequestResourceType = "doc" | "profile";
51
+ type ChangeRequestOperation = "create" | "update" | "delete";
52
+ type ChangeRequestStatus = "open" | "approved" | "rejected" | "withdrawn" | "superseded";
53
+ type ChangeRequestActorKind = "human" | "agent";
54
+ /** Public projection of a change request (mirrors `PublicChangeRequest` in services/org). */
55
+ interface KnowledgeChangeRequest {
56
+ changeRequestId: string;
57
+ scopeType: KnowledgeScopeType;
58
+ scopeId: string;
59
+ resourceType: ChangeRequestResourceType;
60
+ operation: ChangeRequestOperation;
61
+ targetPath: string | null;
62
+ baseVersionId: string | null;
63
+ proposedContentType: string | null;
64
+ status: ChangeRequestStatus;
65
+ proposerId: string;
66
+ proposerKind: ChangeRequestActorKind;
67
+ rationale: string;
68
+ reviewerId: string | null;
69
+ reviewerKind: ChangeRequestActorKind | null;
70
+ reviewedAt: string | null;
71
+ reviewNote: string | null;
72
+ appliedRef: string | null;
73
+ createdAt: string;
74
+ updatedAt: string;
75
+ }
76
+ /** Per-type proposal payload for `proposeScopeChange`. */
77
+ interface ProposeScopeChangeInput {
78
+ resourceType: ChangeRequestResourceType;
79
+ operation: ChangeRequestOperation;
80
+ /** Why the change is proposed — shown to the reviewer. */
81
+ rationale: string;
82
+ /** doc: the path the proposal applies to (e.g. designs/data-center.md). */
83
+ targetPath?: string;
84
+ /** doc create/update: the staged body to upload (markdown or other text). */
85
+ content?: string;
86
+ /** doc create/update: content type of the staged body (default text/markdown). */
87
+ contentType?: string;
88
+ /** profile: the proposed value ({ about, description, links }). */
89
+ proposedValue?: unknown;
90
+ }
91
+ interface KnowledgeDoc {
92
+ filePath: string;
93
+ fileName: string;
94
+ contentType?: string;
95
+ size: number;
96
+ uploadedBy?: string;
97
+ createdAt: string;
98
+ updatedAt: string;
99
+ }
100
+ //#endregion
101
+ //#region ../openclaw-plugin-kit/dist/index.d.ts
102
+ //# sourceMappingURL=types.d.ts.map
103
+ //#endregion
104
+ //#region src/tools.d.ts
105
+ /** Shape returned to OpenClaw from a tool `execute`. */
106
+ interface ToolResult {
107
+ content: {
108
+ type: "text";
109
+ text: string;
110
+ }[];
111
+ details: unknown;
112
+ isError?: boolean;
113
+ }
114
+ interface ToolDef<TParameters = unknown> {
115
+ name: string;
116
+ description: string;
117
+ label: string;
118
+ parameters: TParameters;
119
+ execute: (toolCallId: string, params: Record<string, unknown>) => Promise<ToolResult>;
120
+ }
121
+ /** Deliberately model-safe validation/usage failure. Other exceptions stay private. */
122
+ //#endregion
123
+ //#region src/types.d.ts
124
+ interface KnowledgeConfig {
125
+ /** Inject org profile + name-only scope list at session start. */
126
+ injectContext: boolean;
127
+ /** Cap on scopes listed in the session-start context block. */
128
+ maxScopes: number;
129
+ }
2
130
  /**
3
- * knowledge OpenClaw knowledge-resources extension.
4
- *
5
- * Scoped, searchable knowledge ABOUT a thing being worked on (org / team /
6
- * project). Distinct from private per-agent memory: this is SHARED,
7
- * attributable, deliberate-publish knowledge that humans and other agents
8
- * read and contribute to.
9
- *
10
- * Shared knowledge is curated DOCUMENTS (+ scope profiles). There is no
11
- * free-floating "fact" primitive: an agent that learns something durable
12
- * finds the right document and edits it in (search → read_doc → write_doc /
13
- * propose_change). Quick or uncertain capture belongs in the agent's private
14
- * per-agent memory, not shared knowledge.
15
- *
16
- * Backed by:
17
- * - services/knowledge — RAG search (vector index over docs)
18
- * - services/org — system of record + per-agent membership gate
19
- * (docs, profile)
20
- *
21
- * Registers:
22
- * - Tools: resource_search, resource_read_doc, resource_write_doc,
23
- * resource_get_profile, resource_list_scopes,
24
- * resource_propose_change, resource_list_change_requests
25
- * - Lifecycle hook: before_agent_start (bounded org-profile + scope-list inject)
26
- *
27
- * NOTE: every tool name here MUST also appear in `openclaw.plugin.json`'s
28
- * `contracts.tools` allowlist — OpenClaw (2026.5+) gates the model's tool
29
- * payload on that strict-literal list, so a registered-but-unlisted tool is
30
- * invisible to the LLM.
131
+ * The subset of `AgentApiClient` the plugin needs. Declaring it as an
132
+ * interface (rather than importing the concrete class everywhere) keeps the
133
+ * injection/formatting code decoupled and unit-testable the real
134
+ * `AgentApiClient` structurally satisfies it.
31
135
  */
136
+ interface KnowledgeApi {
137
+ knowledgeSearch(query: string, opts?: {
138
+ limit?: number;
139
+ scopeType?: KnowledgeScopeType;
140
+ scopeId?: string;
141
+ }): Promise<KnowledgeSearchResult>;
142
+ listScopes(): Promise<{
143
+ scopes: KnowledgeScope[];
144
+ }>;
145
+ getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
146
+ listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
147
+ limit?: number;
148
+ cursor?: string;
149
+ }): Promise<{
150
+ files: KnowledgeDoc[];
151
+ nextCursor: string | null;
152
+ }>;
153
+ readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, opts?: {
154
+ maxBytes?: number;
155
+ }): Promise<{
156
+ filePath: string;
157
+ text: string;
158
+ }>;
159
+ writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
160
+ contentType?: string;
161
+ message?: string;
162
+ }): Promise<{
163
+ filePath: string;
164
+ }>;
165
+ proposeScopeChange(scopeType: KnowledgeScopeType, scopeId: string, input: ProposeScopeChangeInput): Promise<KnowledgeChangeRequest>;
166
+ listScopeChangeRequests(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
167
+ status?: ChangeRequestStatus;
168
+ limit?: number;
169
+ cursor?: string;
170
+ }): Promise<{
171
+ changeRequests: KnowledgeChangeRequest[];
172
+ nextCursor: string | null;
173
+ }>;
174
+ }
175
+ //# sourceMappingURL=types.d.ts.map
176
+ //#endregion
177
+ //#region src/runtime.d.ts
178
+ interface PluginLogger {
179
+ info(message: string, ...args: unknown[]): void;
180
+ warn(message: string, ...args: unknown[]): void;
181
+ error(message: string, ...args: unknown[]): void;
182
+ debug(message: string, ...args: unknown[]): void;
183
+ }
32
184
  interface PluginApi {
33
- pluginConfig?: Record<string, unknown>;
34
- config: Record<string, unknown>;
35
- logger: {
36
- info: (msg: string, ctx?: Record<string, unknown>) => void;
37
- debug: (msg: string, ctx?: Record<string, unknown>) => void;
38
- warn: (msg: string, ctx?: Record<string, unknown>) => void;
39
- error: (msg: string, ctx?: Record<string, unknown>) => void;
40
- };
41
- registerTool: (factory: (ctx: ToolContext) => Tool, opts?: {
185
+ pluginConfig?: unknown;
186
+ logger: PluginLogger;
187
+ registerTool(tool: ToolDef<TSchema>, options?: {
42
188
  names?: string[];
43
- }) => void;
44
- on: (hookName: string, handler: (...args: unknown[]) => unknown, opts?: {
189
+ }): void;
190
+ on(hookName: string, handler: (...args: unknown[]) => unknown, options?: {
45
191
  priority?: number;
46
- }) => void;
192
+ }): void;
47
193
  }
48
- interface ToolContext {
49
- agentId?: string;
50
- sessionKey?: string;
51
- sessionId?: string;
52
- messageChannel?: string;
53
- }
54
- interface Tool {
55
- name: string;
56
- label: string;
57
- description: string;
58
- parameters: Record<string, unknown>;
59
- execute: (toolCallId: string, params: Record<string, unknown>) => Promise<unknown>;
60
- }
61
- declare const plugin: {
194
+ interface KnowledgePlugin {
62
195
  id: string;
63
196
  name: string;
64
197
  description: string;
65
198
  version: string;
66
- register(api: PluginApi): void;
67
- };
199
+ activate(api: PluginApi): void;
200
+ deactivate(api: PluginApi): void;
201
+ }
202
+ //#endregion
203
+ //#region src/plugin.d.ts
204
+ declare const plugin: KnowledgePlugin;
68
205
  //#endregion
69
- export { plugin as default };
206
+ export { KnowledgeChangeRequest as a, KnowledgeScope as c, ProposeScopeChangeInput as d, ChangeRequestStatus as i, KnowledgeScopeType as l, KnowledgeApi as n, KnowledgeDoc as o, KnowledgeConfig as r, KnowledgeProfile as s, plugin as t, KnowledgeSearchResult as u };
70
207
  //# sourceMappingURL=plugin.d.cts.map