@undefineds.co/models 0.2.19 → 0.2.22
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 +178 -522
- package/dist/agent.repository.js +2 -2
- package/dist/agent.schema.d.ts +20 -3
- package/dist/agent.schema.js +3 -1
- package/dist/ai-config/index.d.ts +24 -0
- package/dist/ai-config/index.js +133 -23
- package/dist/ai-model.schema.d.ts +13 -3
- package/dist/ai-model.schema.js +6 -4
- package/dist/ai-provider.schema.d.ts +13 -3
- package/dist/ai-provider.schema.js +7 -3
- package/dist/ai-runtime.schema.d.ts +84 -0
- package/dist/ai-runtime.schema.js +64 -0
- package/dist/approval.schema.d.ts +1 -0
- package/dist/approval.schema.js +11 -0
- package/dist/audit.schema.d.ts +1 -0
- package/dist/audit.schema.js +11 -0
- package/dist/chat.repository.js +2 -2
- package/dist/chat.schema.d.ts +1 -1
- package/dist/chat.schema.js +1 -1
- package/dist/contact.repository.js +2 -2
- package/dist/contact.schema.d.ts +26 -4
- package/dist/contact.schema.js +4 -2
- package/dist/credential.schema.d.ts +111 -3
- package/dist/credential.schema.js +15 -2
- package/dist/favorite/favorite.schema.d.ts +18 -4
- package/dist/favorite/favorite.schema.js +4 -2
- package/dist/favorite/index.d.ts +1 -1
- package/dist/favorite/index.js +1 -1
- package/dist/favorite/starred-sync.d.ts +2 -2
- package/dist/favorite/starred-sync.js +4 -4
- package/dist/file/file.schema.d.ts +26 -5
- package/dist/file/file.schema.js +5 -3
- package/dist/file/index.d.ts +1 -1
- package/dist/file/index.js +1 -1
- package/dist/grant.schema.d.ts +1 -0
- package/dist/grant.schema.js +3 -0
- package/dist/inbox-notification.schema.d.ts +10 -3
- package/dist/inbox-notification.schema.js +3 -1
- package/dist/index.d.ts +17 -17
- package/dist/index.js +17 -21
- package/dist/message.repository.js +2 -2
- package/dist/message.schema.js +8 -8
- package/dist/namespaces.d.ts +0 -3
- package/dist/namespaces.js +33 -7
- package/dist/profile.d.ts +2 -1
- package/dist/profile.js +6 -3
- package/dist/profile.repository.js +3 -3
- package/dist/profile.schema.d.ts +16 -3
- package/dist/profile.schema.js +3 -1
- package/dist/repository.d.ts +6 -1
- package/dist/repository.js +6 -1
- package/dist/schema.d.ts +102 -10
- package/dist/schema.js +31 -21
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +1 -1
- package/dist/session/session.schema.d.ts +7 -2
- package/dist/session/session.schema.js +32 -4
- package/dist/session.repository.d.ts +4 -0
- package/dist/session.repository.js +2 -2
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.js +1 -1
- package/dist/settings/settings.schema.d.ts +17 -5
- package/dist/settings/settings.schema.js +4 -2
- package/dist/thread.repository.js +2 -2
- package/dist/thread.schema.js +2 -2
- package/dist/vocab/message.vocab.js +8 -8
- package/dist/vocab/thread.vocab.js +2 -2
- package/package.json +15 -8
- package/dist/watch/index.d.ts +0 -281
- package/dist/watch/index.js +0 -1493
package/README.md
CHANGED
|
@@ -1,593 +1,249 @@
|
|
|
1
|
-
# LinX
|
|
1
|
+
# LinX Models
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> 使用 `drizzle-solid` ORM,兼容标准 RDF 词汇表(VCARD, FOAF, SIOC, DCTerms 等)
|
|
3
|
+
`@undefineds.co/models` is the shared Solid Pod data model contract for LinX
|
|
4
|
+
apps, desktop, CLI, sidecars, and future workers.
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
Application shells should use these schemas, repositories, and helpers directly.
|
|
7
|
+
Do not duplicate shared predicates, subject templates, Turtle serializers,
|
|
8
|
+
resource state machines, or cross-app use-case logic in `apps/*`.
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## Package
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- [使用示例](#使用示例)
|
|
15
|
-
- [设计原则](#设计原则)
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 概述
|
|
20
|
-
|
|
21
|
-
LinX 的所有数据存储在 Solid Pod 中,使用标准的 RDF 格式。本包定义了所有核心业务实体的数据模型,包括:
|
|
22
|
-
|
|
23
|
-
### 核心功能模型
|
|
24
|
-
|
|
25
|
-
1. **Profile** - 用户资料
|
|
26
|
-
2. **Contact** - 联系人管理(支持自然人和 AI)
|
|
27
|
-
3. **Chat & Message** - 聊天会话和消息
|
|
28
|
-
4. **File** - 文件管理
|
|
29
|
-
5. **Favorite** - 收藏夹
|
|
30
|
-
6. **Settings** - 用户设置
|
|
31
|
-
7. **AI Assistant** - AI 助手配置
|
|
32
|
-
|
|
33
|
-
### 其他模型
|
|
34
|
-
|
|
35
|
-
- **Session** - 会话管理
|
|
36
|
-
- **Knowledge Folder** - 知识库文件夹
|
|
37
|
-
- **Extension** - 扩展
|
|
38
|
-
- **Model Credential** - 模型凭证
|
|
39
|
-
- **Import Job** - 导入任务
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Chat / Thread / Message / Session 语义
|
|
44
|
-
|
|
45
|
-
这组语义是 CLI、App、watch/runtime 共享的 models 级业务真相,不应在 UI、CLI 壳层或 skill 文件中重新定义。
|
|
46
|
-
|
|
47
|
-
- **Chat** 表示对话对象/counterpart:用户正在和谁或什么对话,例如默认 AI secretary、某个人、群组、Codex、Claude Code,或后续具体 AI 身份。
|
|
48
|
-
- **Thread** 表示具体场所、时间线和 runtime context:workspace、watch 场景、AI 产品运行时 session、外部 agent session 等上下文都归在 thread 上。
|
|
49
|
-
- **Message** 同时属于一个 `chat` 和一个 `thread`:chat 回答“跟谁聊”,thread 回答“在哪个运行/时间线里聊”。
|
|
50
|
-
- **Session** 表示通用 AI 产品/agent runtime 的运行生命周期投影:它必须指向对应的 `chat` URI 和 `thread` URI,不能作为另一套对话根。
|
|
51
|
-
|
|
52
|
-
存储层规则:
|
|
53
|
-
|
|
54
|
-
- Pod schema 使用 `chat`、`thread` 这类 URI-valued RDF relation 字段。
|
|
55
|
-
- `chatId`、`threadId` 只允许作为 UI 状态、函数参数、runtime protocol 字段或 metadata 中的兼容信息,不允许作为持久 RDF link 字段。
|
|
56
|
-
- 新增 shared model 代码优先使用 `chatResource`、`threadResource`、`messageResource`、`sessionResource` 等 Solid resource 命名;`*Table` 只作为兼容 alias 逐步退出。
|
|
57
|
-
- 如果壳层需要新的查询、upsert、resolve-by-uri、审计或审批状态变更能力,优先在本包新增 repository/helper 和 tests;不要在 CLI/App 中复制 predicate、subject template、Turtle 读写或 shared 状态机。
|
|
58
|
-
- `approval` / `grant` / `audit` / `inboxNotification` / `session` 等跨端控制面也属于本包的 shared resource 语义。CLI/App 只负责把 Pi/Codex/Claude 等运行时事件映射成本包定义的 insert/update DTO,不能另建一套存储路径或审批策略。
|
|
59
|
-
- approval 的倒计时和可选决策也属于 shared resource 语义:使用 `approvalResource.expiresAt` 表示截止时间,使用 `approvalResource.approvalOptions` 存储上游原生协议给出的可选决策(例如 `allow_once` / `allow_always` / `reject_once`)。CLI/App 不得各自用私有 predicate 或本地状态推断这些字段。
|
|
60
|
-
- grant 是可维护的 LLM Wiki 文档资源,不是一次请求的 fingerprint。`grantResource` 使用 `/settings/autonomy/grants/{id}.ttl`,文档 URI 本身就是 RDF subject;通过 `title/summary/body/schema/pageKind/wikiStatus/tags/source/sourceHash/compiledAt/compiledFrom/related/context` 描述页面语义、来源和上下文。
|
|
61
|
-
- `grant.schema` 使用 `dcterms:conformsTo` 指向 Solid schema/shape URI,例如 `/settings/autonomy/schema/grant.ttl#GrantWikiPage`;它不是 `path`/`wikiPath` 字符串,TTL wiki page 也不需要 `.meta` subject。
|
|
62
|
-
- `grant.target`、`grant.action`、`grant.riskCeiling` 只用于候选筛选或排序,不得作为最终自动审批判定。最终是否覆盖必须看 wiki page 的 `body/summary/tags/source/provenance/context` 与当前请求的语义匹配结果。
|
|
63
|
-
- CLI/App 不得为 shared 控制面字段自定义业务 predicate。新增 approval/grant/audit 字段必须先在本包的 namespace、vocab、schema 和 tests 中定义。
|
|
64
|
-
- structured user-input 与 approval 一样属于 watch 共享协议:AI secretary 只能在答案能从请求上下文明确推出时代答,否则必须回到人工输入。
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## 标准词汇表
|
|
69
|
-
|
|
70
|
-
LinX 遵循 Solid 生态的最佳实践,优先使用标准 RDF 词汇表:
|
|
71
|
-
|
|
72
|
-
### 已集成的标准词汇表
|
|
73
|
-
|
|
74
|
-
| 词汇表 | 用途 | 规范 |
|
|
75
|
-
|--------|------|------|
|
|
76
|
-
| **VCARD** | 联系人信息 | [RFC 6350](https://www.w3.org/TR/vcard-rdf/) |
|
|
77
|
-
| **FOAF** | 人和社交关系 | [FOAF Vocabulary](http://xmlns.com/foaf/spec/) |
|
|
78
|
-
| **SIOC** | 社交内容和讨论 | [SIOC Ontology](http://rdfs.org/sioc/spec/) |
|
|
79
|
-
| **DCTerms** | 元数据(创建时间、作者等) | [Dublin Core](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/) |
|
|
80
|
-
| **Schema.org** | 结构化数据 | [Schema.org](https://schema.org/) |
|
|
81
|
-
| **LDP** | Linked Data Platform | [LDP Spec](https://www.w3.org/TR/ldp/) |
|
|
82
|
-
|
|
83
|
-
### LinX 自定义词汇表
|
|
84
|
-
|
|
85
|
-
命名空间:`https://linx.ai/ns#`
|
|
86
|
-
|
|
87
|
-
用于标准词汇表未覆盖的 LinX 特有功能(如 AI 助手配置、同步状态等)。
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## 核心模型
|
|
92
|
-
|
|
93
|
-
### 1. Profile(用户资料)
|
|
94
|
-
|
|
95
|
-
**文件路径**: `src/profile.ts`
|
|
96
|
-
|
|
97
|
-
**RDF 类**: `foaf:Person`
|
|
98
|
-
|
|
99
|
-
**字段**:
|
|
100
|
-
```typescript
|
|
101
|
-
{
|
|
102
|
-
displayName: string; // vcard:fn
|
|
103
|
-
nickname: string; // foaf:nick
|
|
104
|
-
avatarUrl: string; // vcard:hasPhoto
|
|
105
|
-
note: string; // vcard:note
|
|
106
|
-
region: string; // vcard:region
|
|
107
|
-
gender: string; // vcard:gender
|
|
108
|
-
favorite: string; // linx:favorite
|
|
109
|
-
inbox: string; // ldp:inbox
|
|
110
|
-
}
|
|
12
|
+
```bash
|
|
13
|
+
yarn workspace @undefineds.co/models build
|
|
14
|
+
yarn workspace @undefineds.co/models test
|
|
111
15
|
```
|
|
112
16
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
givenName: string; // vcard:givenName
|
|
129
|
-
familyName: string; // vcard:familyName
|
|
130
|
-
nickname: string; // foaf:nick
|
|
131
|
-
|
|
132
|
-
// 联系方式
|
|
133
|
-
email: string; // vcard:hasEmail
|
|
134
|
-
telephone: string; // vcard:hasTelephone
|
|
135
|
-
mobile: string;
|
|
136
|
-
|
|
137
|
-
// 地址
|
|
138
|
-
homeAddress: string; // vcard:hasAddress (JSON)
|
|
139
|
-
workAddress: string;
|
|
140
|
-
|
|
141
|
-
// 组织
|
|
142
|
-
organization: string; // vcard:organizationName
|
|
143
|
-
title: string; // vcard:title
|
|
144
|
-
|
|
145
|
-
// Solid 身份
|
|
146
|
-
webId: string; // foaf:weblog
|
|
147
|
-
|
|
148
|
-
// AI 联系人
|
|
149
|
-
aiAssistantId: string; // linx:aiAssistant
|
|
150
|
-
|
|
151
|
-
// 关系和标签
|
|
152
|
-
relationship: string; // vcard:hasRelated
|
|
153
|
-
tags: string; // dcterms:subject (JSON)
|
|
154
|
-
}
|
|
17
|
+
```ts
|
|
18
|
+
import {
|
|
19
|
+
UDFS,
|
|
20
|
+
XPOD_AI,
|
|
21
|
+
XPOD_CREDENTIAL,
|
|
22
|
+
agentResource,
|
|
23
|
+
aiModelResource,
|
|
24
|
+
aiProviderResource,
|
|
25
|
+
chatResource,
|
|
26
|
+
contactResource,
|
|
27
|
+
credentialResource,
|
|
28
|
+
messageResource,
|
|
29
|
+
selectAIConfigCredential,
|
|
30
|
+
threadResource,
|
|
31
|
+
} from '@undefineds.co/models'
|
|
155
32
|
```
|
|
156
33
|
|
|
157
|
-
|
|
158
|
-
- `CONTACT_TYPES`: `person`, `ai`, `organization`, `group`
|
|
159
|
-
- `RELATIONSHIP_TYPES`: `friend`, `family`, `colleague`, `acquaintance`, `other`
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
### 3. Chat(聊天会话)
|
|
34
|
+
## Namespaces
|
|
164
35
|
|
|
165
|
-
|
|
36
|
+
LinX-owned predicates and classes use the company namespace:
|
|
166
37
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
**字段**:
|
|
170
|
-
```typescript
|
|
171
|
-
{
|
|
172
|
-
title: string; // dcterms:title ⭐ 必需
|
|
173
|
-
description: string; // dcterms:description
|
|
174
|
-
conversationType: string; // linx:conversationType (direct, group, ai)
|
|
175
|
-
status: string; // linx:status (active, archived, deleted)
|
|
176
|
-
participants: array; // linx:participants (WebID 数组)
|
|
177
|
-
creator: string; // dcterms:creator
|
|
178
|
-
createdAt: timestamp; // dcterms:created
|
|
179
|
-
modifiedAt: timestamp; // dcterms:modified
|
|
180
|
-
lastMessage: string; // linx:lastMessage
|
|
181
|
-
lastMessageAt: timestamp; // linx:lastMessageAt
|
|
182
|
-
pinnedAt: timestamp; // linx:pinnedAt
|
|
183
|
-
}
|
|
38
|
+
```text
|
|
39
|
+
https://undefineds.co/ns#
|
|
184
40
|
```
|
|
185
41
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
### 4. Message(聊天消息)
|
|
189
|
-
|
|
190
|
-
**文件路径**: `src/chat/message.schema.ts`
|
|
42
|
+
Use `udfs:` terms in models-level RDF contracts.
|
|
191
43
|
|
|
192
|
-
|
|
44
|
+
AI service catalog resources currently use the Xpod AI vocabularies:
|
|
193
45
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
content: string; // sioc:content ⭐ 必需 (支持 Markdown)
|
|
198
|
-
messageType: string; // linx:messageType (text, image, file, system)
|
|
199
|
-
messageStatus: string; // linx:messageStatus (sending, sent, delivered, read, failed)
|
|
200
|
-
conversationId: string; // linx:conversation
|
|
201
|
-
replyTo: string; // sioc:replyOf
|
|
202
|
-
sender: string; // dcterms:creator (WebID)
|
|
203
|
-
senderName: string; // foaf:name
|
|
204
|
-
createdAt: timestamp; // dcterms:created
|
|
205
|
-
modifiedAt: timestamp; // dcterms:modified (编辑时间)
|
|
206
|
-
deletedAt: timestamp; // linx:deletedAt (软删除)
|
|
207
|
-
readBy: string; // linx:readBy (JSON)
|
|
208
|
-
|
|
209
|
-
// 附件(如果是文件/图片消息)
|
|
210
|
-
attachmentUri: string; // schema:about
|
|
211
|
-
attachmentName: string; // schema:name
|
|
212
|
-
attachmentSize: integer; // schema:fileSize
|
|
213
|
-
attachmentMime: string; // schema:encodingFormat
|
|
214
|
-
}
|
|
46
|
+
```text
|
|
47
|
+
https://vocab.xpod.dev/ai#
|
|
48
|
+
https://vocab.xpod.dev/credential#
|
|
215
49
|
```
|
|
216
50
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
### 5. File(文件管理)
|
|
51
|
+
## Core Runtime Semantics
|
|
220
52
|
|
|
221
|
-
|
|
53
|
+
The shared chat/runtime model is:
|
|
222
54
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
size: integer; // schema:fileSize
|
|
232
|
-
hash: string; // linx:fileHash (SHA-256)
|
|
233
|
-
podUri: string; // dcterms:identifier (Pod 中的 URI)
|
|
234
|
-
localPath: string; // linx:localPath (本地路径)
|
|
235
|
-
syncStatus: string; // linx:syncStatus (synced, pending, conflict, error)
|
|
236
|
-
owner: string; // dcterms:creator
|
|
237
|
-
sharedWith: string; // linx:participants (JSON)
|
|
238
|
-
folder: string; // linx:conversation
|
|
239
|
-
tags: string; // dcterms:subject (JSON)
|
|
240
|
-
starred: boolean; // linx:favorite
|
|
241
|
-
createdAt: timestamp; // dcterms:created
|
|
242
|
-
modifiedAt: timestamp; // dcterms:modified
|
|
243
|
-
}
|
|
55
|
+
```text
|
|
56
|
+
Chat = who or what the user is talking with
|
|
57
|
+
Thread = the concrete timeline/place/runtime context under a Chat
|
|
58
|
+
Message = a message in both a Chat and a Thread
|
|
59
|
+
Session = one Agent runtime execution bound to Agent + Thread + Workspace
|
|
60
|
+
Agent = executable capability root with its own home/config filesystem
|
|
61
|
+
Workspace = concrete working code area/worktree metadata
|
|
62
|
+
Repository = durable source-control metadata, not the working directory
|
|
244
63
|
```
|
|
245
64
|
|
|
246
|
-
|
|
65
|
+
Detailed Agent-centered runtime, Repository/Workspace, branch/ref, Agent home,
|
|
66
|
+
and Session binding rules live in:
|
|
247
67
|
|
|
248
|
-
|
|
68
|
+
- [`docs/agent-runtime-model.md`](docs/agent-runtime-model.md)
|
|
249
69
|
|
|
250
|
-
|
|
70
|
+
## Agent vs AI Config
|
|
251
71
|
|
|
252
|
-
|
|
72
|
+
`agentResource` and `ai-config` intentionally both mention provider/model, but
|
|
73
|
+
they are not the same resource.
|
|
253
74
|
|
|
254
|
-
|
|
75
|
+
`agentResource` answers: which executable actor is this, and what defaults
|
|
76
|
+
should it use at runtime?
|
|
255
77
|
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
{
|
|
259
|
-
title: string; // dcterms:title ⭐ 必需
|
|
260
|
-
description: string; // dcterms:description
|
|
261
|
-
favoriteType: string; // linx:favoriteType
|
|
262
|
-
targetUri: string; // linx:favoriteTarget ⭐ 必需
|
|
263
|
-
|
|
264
|
-
// 快照(避免查询原始资源)
|
|
265
|
-
snapshotContent: string; // schema:text
|
|
266
|
-
snapshotAuthor: string; // schema:author
|
|
267
|
-
snapshotCreatedAt: timestamp; // schema:dateCreated
|
|
268
|
-
|
|
269
|
-
owner: string; // dcterms:creator
|
|
270
|
-
folder: string; // linx:conversation
|
|
271
|
-
tags: string; // dcterms:subject (JSON)
|
|
272
|
-
favoredAt: timestamp; // linx:favoredAt
|
|
273
|
-
createdAt: timestamp; // dcterms:created
|
|
274
|
-
modifiedAt: timestamp; // dcterms:modified
|
|
275
|
-
pinnedAt: timestamp; // linx:pinnedAt
|
|
276
|
-
}
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
### 7. Settings(用户设置)
|
|
282
|
-
|
|
283
|
-
**文件路径**: `src/settings/settings.schema.ts`
|
|
284
|
-
|
|
285
|
-
**RDF 类**: `schema:PropertyValue`
|
|
78
|
+
Current Agent fields include:
|
|
286
79
|
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
80
|
+
```ts
|
|
289
81
|
{
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
82
|
+
name: string
|
|
83
|
+
description?: string
|
|
84
|
+
avatarUrl?: string
|
|
85
|
+
instructions?: string
|
|
86
|
+
provider?: string
|
|
87
|
+
model?: string
|
|
88
|
+
temperature?: number
|
|
89
|
+
tools?: string[]
|
|
90
|
+
contextRound?: number
|
|
91
|
+
ttsModel?: string
|
|
92
|
+
videoModel?: string
|
|
300
93
|
}
|
|
301
94
|
```
|
|
302
95
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
UI_THEME: "ui.theme"
|
|
307
|
-
UI_LANGUAGE: "ui.language"
|
|
308
|
-
UI_SIDEBAR_WIDTH: "ui.sidebar.width"
|
|
309
|
-
UI_LIST_PANEL_WIDTH: "ui.listPanel.width"
|
|
310
|
-
|
|
311
|
-
// AI 设置
|
|
312
|
-
AI_DEFAULT_ASSISTANT: "ai.defaultAssistant"
|
|
313
|
-
AI_AUTO_REPLY: "ai.autoReply"
|
|
314
|
-
AI_STREAMING: "ai.streaming"
|
|
315
|
-
|
|
316
|
-
// 同步设置
|
|
317
|
-
SYNC_AUTO: "sync.auto"
|
|
318
|
-
SYNC_INTERVAL: "sync.interval"
|
|
319
|
-
SYNC_WIFI_ONLY: "sync.wifiOnly"
|
|
320
|
-
|
|
321
|
-
// 隐私设置
|
|
322
|
-
PRIVACY_READ_RECEIPTS: "privacy.readReceipts"
|
|
323
|
-
PRIVACY_ONLINE_STATUS: "privacy.onlineStatus"
|
|
324
|
-
PRIVACY_TYPING_INDICATOR: "privacy.typingIndicator"
|
|
325
|
-
|
|
326
|
-
// 通知设置
|
|
327
|
-
NOTIFICATIONS_ENABLED: "notifications.enabled"
|
|
328
|
-
NOTIFICATIONS_SOUND: "notifications.sound"
|
|
329
|
-
NOTIFICATIONS_DESKTOP: "notifications.desktop"
|
|
330
|
-
|
|
331
|
-
// Pod 设置
|
|
332
|
-
POD_AUTO_CONNECT: "pod.autoConnect"
|
|
333
|
-
POD_CACHE_SIZE: "pod.cacheSize"
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
---
|
|
337
|
-
|
|
338
|
-
### 8. AI Assistant(AI 助手配置)
|
|
96
|
+
Agent owns runtime preference and capability state. It should not own shared
|
|
97
|
+
API keys, endpoint catalogs, provider model lists, or credential rotation
|
|
98
|
+
policy.
|
|
339
99
|
|
|
340
|
-
|
|
100
|
+
`ai-config` answers: which AI services are available, which models belong to a
|
|
101
|
+
provider, and which credential should be used for a provider call?
|
|
341
102
|
|
|
342
|
-
|
|
103
|
+
The resources are:
|
|
343
104
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
{
|
|
347
|
-
|
|
348
|
-
name: string; // foaf:name ⭐ 必需
|
|
349
|
-
nickname: string; // foaf:nick
|
|
350
|
-
description: string; // dcterms:description
|
|
351
|
-
avatarUrl: string; // foaf:depiction
|
|
352
|
-
assistantType: string; // dcterms:type (system, custom, shared)
|
|
353
|
-
|
|
354
|
-
// 模型配置
|
|
355
|
-
provider: string; // linx:aiProvider (openai, anthropic, ollama, custom)
|
|
356
|
-
modelId: string; // linx:aiModel (gpt-4, claude-3, llama2)
|
|
357
|
-
systemPrompt: string; // linx:systemPrompt
|
|
358
|
-
|
|
359
|
-
// 模型参数
|
|
360
|
-
temperature: float; // linx:temperature (0-2)
|
|
361
|
-
maxTokens: integer; // linx:maxTokens
|
|
362
|
-
topP: float;
|
|
363
|
-
frequencyPenalty: float;
|
|
364
|
-
presencePenalty: float;
|
|
365
|
-
|
|
366
|
-
// 功能配置
|
|
367
|
-
enableStreaming: boolean;
|
|
368
|
-
enableFunctionCalling: boolean;
|
|
369
|
-
allowedFunctions: string; // JSON 数组
|
|
370
|
-
|
|
371
|
-
// Pod 访问权限
|
|
372
|
-
podAccessLevel: string; // linx:status (read, write, full)
|
|
373
|
-
allowedContainers: string; // JSON 数组
|
|
374
|
-
|
|
375
|
-
// 共享
|
|
376
|
-
owner: string; // dcterms:creator
|
|
377
|
-
isPublic: boolean;
|
|
378
|
-
sharedWith: string; // JSON
|
|
379
|
-
|
|
380
|
-
// 统计
|
|
381
|
-
messageCount: integer;
|
|
382
|
-
lastUsedAt: timestamp;
|
|
383
|
-
|
|
384
|
-
status: string; // linx:status (active, disabled, archived)
|
|
385
|
-
createdAt: timestamp;
|
|
386
|
-
modifiedAt: timestamp;
|
|
387
|
-
}
|
|
105
|
+
```text
|
|
106
|
+
aiProviderResource /settings/providers/{providerId}.ttl
|
|
107
|
+
aiModelResource /settings/providers/{providerId}.ttl#{modelId}
|
|
108
|
+
credentialResource /settings/credentials.ttl#{credentialId}
|
|
388
109
|
```
|
|
389
110
|
|
|
390
|
-
|
|
391
|
-
- `AI_PROVIDERS`: `openai`, `anthropic`, `google`, `ollama`, `custom`
|
|
392
|
-
- `AI_MODELS`: 包含常见模型 ID(GPT-4, Claude-3, Gemini, Llama2 等)
|
|
111
|
+
The separation is:
|
|
393
112
|
|
|
394
|
-
|
|
113
|
+
```text
|
|
114
|
+
Agent.provider / Agent.model
|
|
115
|
+
runtime default selection for one Agent
|
|
395
116
|
|
|
396
|
-
|
|
117
|
+
AI Provider
|
|
118
|
+
endpoint/catalog/family metadata such as baseUrl, proxyUrl, defaultModel
|
|
397
119
|
|
|
398
|
-
|
|
120
|
+
AI Model
|
|
121
|
+
provider-provided model metadata linked by isProvidedBy
|
|
399
122
|
|
|
400
|
-
|
|
401
|
-
|
|
123
|
+
Credential
|
|
124
|
+
named secret and routing state linked to a provider
|
|
402
125
|
```
|
|
403
126
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
```typescript
|
|
407
|
-
import {
|
|
408
|
-
// 词汇表
|
|
409
|
-
LINQ, SIOC, DCTerms, SCHEMA,
|
|
410
|
-
|
|
411
|
-
// 模型表
|
|
412
|
-
contactTable,
|
|
413
|
-
chatTable,
|
|
414
|
-
messageTable,
|
|
415
|
-
fileTable,
|
|
416
|
-
favoriteTable,
|
|
417
|
-
settingsTable,
|
|
418
|
-
aiAssistantTable,
|
|
419
|
-
|
|
420
|
-
// 类型
|
|
421
|
-
type ContactRow,
|
|
422
|
-
type ChatRow,
|
|
423
|
-
type MessageRow,
|
|
424
|
-
|
|
425
|
-
// 常量
|
|
426
|
-
CONTACT_TYPES,
|
|
427
|
-
SETTING_KEYS,
|
|
428
|
-
AI_PROVIDERS,
|
|
429
|
-
} from "@linq/models";
|
|
430
|
-
```
|
|
127
|
+
Credential selection uses the shared helper:
|
|
431
128
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
```typescript
|
|
435
|
-
// 查询联系人
|
|
436
|
-
const contacts = await db
|
|
437
|
-
.select()
|
|
438
|
-
.from(contactTable)
|
|
439
|
-
.where(eq(contactTable.contactType, CONTACT_TYPES.PERSON));
|
|
440
|
-
|
|
441
|
-
// 创建聊天会话
|
|
442
|
-
const newChat = await db
|
|
443
|
-
.insert(chatTable)
|
|
444
|
-
.values({
|
|
445
|
-
title: "与 Alice 的对话",
|
|
446
|
-
conversationType: "direct",
|
|
447
|
-
participants: ["https://alice.solidcommunity.net/profile/card#me"],
|
|
448
|
-
creator: session.webId,
|
|
449
|
-
status: "active",
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// 发送消息
|
|
453
|
-
const newMessage = await db
|
|
454
|
-
.insert(messageTable)
|
|
455
|
-
.values({
|
|
456
|
-
content: "你好,Alice!",
|
|
457
|
-
messageType: "text",
|
|
458
|
-
conversationId: chatId,
|
|
459
|
-
sender: session.webId,
|
|
460
|
-
senderName: "Bob",
|
|
461
|
-
messageStatus: "sent",
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
// 查询设置
|
|
465
|
-
const theme = await db
|
|
466
|
-
.select()
|
|
467
|
-
.from(settingsTable)
|
|
468
|
-
.where(eq(settingsTable.key, SETTING_KEYS.UI_THEME))
|
|
469
|
-
.limit(1);
|
|
470
|
-
|
|
471
|
-
// 创建 AI 助手
|
|
472
|
-
const assistant = await db
|
|
473
|
-
.insert(aiAssistantTable)
|
|
474
|
-
.values({
|
|
475
|
-
name: "LinX 助手",
|
|
476
|
-
provider: AI_PROVIDERS.OPENAI,
|
|
477
|
-
modelId: AI_MODELS.GPT_4,
|
|
478
|
-
systemPrompt: "你是 LinX 的智能助手...",
|
|
479
|
-
temperature: 0.7,
|
|
480
|
-
maxTokens: 2048,
|
|
481
|
-
owner: session.webId,
|
|
482
|
-
});
|
|
129
|
+
```ts
|
|
130
|
+
const selected = selectAIConfigCredential('openai', credentialRows, providerRows)
|
|
483
131
|
```
|
|
484
132
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
## 设计原则
|
|
133
|
+
Selection semantics:
|
|
488
134
|
|
|
489
|
-
|
|
135
|
+
- Only active `service = "ai"` credentials with an API key are candidates.
|
|
136
|
+
- A credential marked `isDefault` is preferred.
|
|
137
|
+
- If multiple defaults exist, the oldest `lastUsedAt` wins.
|
|
138
|
+
- If no default exists, credentials rotate by oldest `lastUsedAt`.
|
|
139
|
+
- `failCount` and stable id are tie breakers.
|
|
140
|
+
- Callers should update `lastUsedAt` after using the selected credential.
|
|
490
141
|
|
|
491
|
-
-
|
|
492
|
-
|
|
493
|
-
- ✅ 所有数据存储在 Pod 的 LDP 容器中
|
|
494
|
-
- ✅ 使用标准 RDF 类(`vcard:Individual`, `schema:Message` 等)
|
|
142
|
+
This means `ai-config` is a shared service/credential pool. Agent records only
|
|
143
|
+
refer to a provider/model default and runtime parameters.
|
|
495
144
|
|
|
496
|
-
|
|
145
|
+
## Contact / Person / Agent
|
|
497
146
|
|
|
498
|
-
|
|
499
|
-
- ✅ 导出 `Row`, `Insert`, `Update` 类型
|
|
500
|
-
- ✅ 定义常量枚举(`CONTACT_TYPES`, `SETTING_KEYS` 等)
|
|
147
|
+
Contact, Person, and Agent are distinct:
|
|
501
148
|
|
|
502
|
-
|
|
149
|
+
```text
|
|
150
|
+
Contact = address-book/social projection shown in Contacts and Chat
|
|
151
|
+
Person = natural human identity
|
|
152
|
+
Agent = executable runtime/capability root with an Agent home
|
|
153
|
+
```
|
|
503
154
|
|
|
504
|
-
|
|
505
|
-
- ✅ 支持 JSON 字段存储复杂数据(标签、数组等)
|
|
506
|
-
- ✅ 预留扩展字段(`tags`, `metadata`)
|
|
155
|
+
AI Secretary has both:
|
|
507
156
|
|
|
508
|
-
|
|
157
|
+
```text
|
|
158
|
+
Contact
|
|
159
|
+
contactType: agent
|
|
160
|
+
entityUri: Agent profile URI
|
|
509
161
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
162
|
+
Agent
|
|
163
|
+
home: /.data/agents/secretary/
|
|
164
|
+
profile: /.data/agents/secretary/profile.ttl
|
|
165
|
+
```
|
|
513
166
|
|
|
514
|
-
|
|
167
|
+
External people, services, or bots may appear as Contacts without being LinX
|
|
168
|
+
Agents. If something is modeled as an executable LinX Agent, it must have an
|
|
169
|
+
Agent home container.
|
|
170
|
+
|
|
171
|
+
## Resource Ownership
|
|
172
|
+
|
|
173
|
+
Use Resource-first names in shared code:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
contactResource
|
|
177
|
+
chatResource
|
|
178
|
+
threadResource
|
|
179
|
+
messageResource
|
|
180
|
+
agentResource
|
|
181
|
+
aiProviderResource
|
|
182
|
+
aiModelResource
|
|
183
|
+
credentialResource
|
|
184
|
+
sessionResource
|
|
185
|
+
approvalResource
|
|
186
|
+
grantResource
|
|
187
|
+
auditResource
|
|
188
|
+
inboxNotificationResource
|
|
189
|
+
```
|
|
515
190
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
- ✅ 索引常用查询字段
|
|
191
|
+
`*Table` exports are compatibility aliases for existing drizzle-solid call
|
|
192
|
+
sites. New shared model code should prefer `*Resource`.
|
|
519
193
|
|
|
520
|
-
|
|
194
|
+
## Pod Storage Patterns
|
|
521
195
|
|
|
522
|
-
|
|
196
|
+
Representative paths:
|
|
523
197
|
|
|
524
|
-
|
|
198
|
+
```text
|
|
199
|
+
/.data/contacts/{contactId}.ttl
|
|
200
|
+
/.data/chat/{chatId}/index.ttl#this
|
|
201
|
+
/.data/chat/{chatId}/index.ttl#{threadId}
|
|
202
|
+
/.data/chat/{chatId}/{yyyy}/{MM}/{dd}/messages.ttl#{messageId}
|
|
203
|
+
/.data/agents/{agentId}/profile.ttl
|
|
204
|
+
/.data/sessions/{yyyy}/{MM}/{dd}/{sessionId}.ttl
|
|
205
|
+
/settings/providers/{providerId}.ttl
|
|
206
|
+
/settings/providers/{providerId}.ttl#{modelId}
|
|
207
|
+
/settings/credentials.ttl#{credentialId}
|
|
208
|
+
```
|
|
525
209
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
4. 导出类型:`Row`, `Insert`, `Update`
|
|
530
|
-
5. 在 `src/<entity>/index.ts` 导出
|
|
531
|
-
6. 在 `src/index.ts` 添加导出
|
|
532
|
-
7. 更新本 README
|
|
210
|
+
Schema fields that are RDF relations should store resource URIs, not hidden
|
|
211
|
+
`xxxId` foreign keys. Short ids are acceptable at repository/helper boundaries
|
|
212
|
+
when the helper derives the canonical URI internally.
|
|
533
213
|
|
|
534
|
-
|
|
214
|
+
## Design Rules
|
|
535
215
|
|
|
536
|
-
|
|
216
|
+
- Prefer standard RDF vocabularies such as VCARD, FOAF, SIOC, DCTerms,
|
|
217
|
+
Schema.org, LDP, and Solid Chat vocabularies.
|
|
218
|
+
- Use `UDFS` only when a standard predicate does not describe the product
|
|
219
|
+
concept.
|
|
220
|
+
- Keep UI-only state outside the Pod.
|
|
221
|
+
- Put durable shared state in Pod resources owned by this package.
|
|
222
|
+
- Add missing query/mutation helpers here before copying storage logic into
|
|
223
|
+
CLI, web, desktop, or plugins.
|
|
224
|
+
- Do not store API secrets on Agent, Chat, Thread, Session, or Workspace.
|
|
225
|
+
- Do not duplicate repository/Git metadata on Session; keep it on Workspace
|
|
226
|
+
metadata and snapshot it when audit requires reproducibility.
|
|
537
227
|
|
|
538
|
-
|
|
539
|
-
- 删除字段:危险(需要数据迁移)
|
|
540
|
-
- 重命名字段:危险(需要数据迁移)
|
|
541
|
-
- 修改类型:危险(需要数据迁移)
|
|
228
|
+
## Development Checklist
|
|
542
229
|
|
|
543
|
-
|
|
230
|
+
When adding or changing a durable model:
|
|
544
231
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
232
|
+
1. Add or update the schema/resource in `src/`.
|
|
233
|
+
2. Add namespace terms in `src/namespaces.ts` when needed.
|
|
234
|
+
3. Export the resource, row, insert, update, and repository/helper from
|
|
235
|
+
`src/index.ts`.
|
|
236
|
+
4. Add tests for RDF predicates, subject templates, and cross-app helper
|
|
237
|
+
semantics.
|
|
238
|
+
5. Update this README or the focused document under `docs/`.
|
|
548
239
|
|
|
549
|
-
|
|
550
|
-
yarn workspace @linq/models typecheck
|
|
551
|
-
```
|
|
240
|
+
## References
|
|
552
241
|
|
|
553
|
-
---
|
|
554
|
-
|
|
555
|
-
## 参考资料
|
|
556
|
-
|
|
557
|
-
### Solid 规范
|
|
558
242
|
- [Solid Protocol](https://solidproject.org/TR/protocol)
|
|
559
|
-
- [Linked Data Platform
|
|
243
|
+
- [Linked Data Platform](https://www.w3.org/TR/ldp/)
|
|
560
244
|
- [WebID Profile](https://www.w3.org/2005/Incubator/webid/spec/)
|
|
561
|
-
|
|
562
|
-
### RDF 词汇表
|
|
563
|
-
- [VCARD Ontology](https://www.w3.org/TR/vcard-rdf/)
|
|
245
|
+
- [VCARD RDF](https://www.w3.org/TR/vcard-rdf/)
|
|
564
246
|
- [FOAF Vocabulary](http://xmlns.com/foaf/spec/)
|
|
565
247
|
- [SIOC Ontology](http://rdfs.org/sioc/spec/)
|
|
566
248
|
- [Dublin Core Terms](https://www.dublincore.org/specifications/dublin-core/dcmi-terms/)
|
|
567
249
|
- [Schema.org](https://schema.org/)
|
|
568
|
-
|
|
569
|
-
### 工具
|
|
570
|
-
- [Drizzle ORM](https://orm.drizzle.team/)
|
|
571
|
-
- [Inrupt Solid Client](https://docs.inrupt.com/developer-tools/javascript/client-libraries/)
|
|
572
|
-
|
|
573
|
-
---
|
|
574
|
-
|
|
575
|
-
## 更新日志
|
|
576
|
-
|
|
577
|
-
| 日期 | 版本 | 更新内容 |
|
|
578
|
-
|------|------|---------|
|
|
579
|
-
| 2025-11-06 | 1.0.0 | 初始版本 - 创建所有核心模型 |
|
|
580
|
-
| | | - 扩展 namespaces.ts(SIOC, DCTerms, SCHEMA, RDF) |
|
|
581
|
-
| | | - 完善 Contact 模型(完整 VCARD 字段) |
|
|
582
|
-
| | | - 创建 Chat & Message 模型 |
|
|
583
|
-
| | | - 创建 File 模型 |
|
|
584
|
-
| | | - 创建 Favorite 模型 |
|
|
585
|
-
| | | - 创建 Settings 模型 |
|
|
586
|
-
| | | - 创建 AI Assistant 模型 |
|
|
587
|
-
| | | - 重组 index.ts 导出 |
|
|
588
|
-
|
|
589
|
-
---
|
|
590
|
-
|
|
591
|
-
## 许可证
|
|
592
|
-
|
|
593
|
-
MIT License
|