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