@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.
Files changed (70) hide show
  1. package/README.md +178 -522
  2. package/dist/agent.repository.js +2 -2
  3. package/dist/agent.schema.d.ts +20 -3
  4. package/dist/agent.schema.js +3 -1
  5. package/dist/ai-config/index.d.ts +24 -0
  6. package/dist/ai-config/index.js +133 -23
  7. package/dist/ai-model.schema.d.ts +13 -3
  8. package/dist/ai-model.schema.js +6 -4
  9. package/dist/ai-provider.schema.d.ts +13 -3
  10. package/dist/ai-provider.schema.js +7 -3
  11. package/dist/ai-runtime.schema.d.ts +84 -0
  12. package/dist/ai-runtime.schema.js +64 -0
  13. package/dist/approval.schema.d.ts +1 -0
  14. package/dist/approval.schema.js +11 -0
  15. package/dist/audit.schema.d.ts +1 -0
  16. package/dist/audit.schema.js +11 -0
  17. package/dist/chat.repository.js +2 -2
  18. package/dist/chat.schema.d.ts +1 -1
  19. package/dist/chat.schema.js +1 -1
  20. package/dist/contact.repository.js +2 -2
  21. package/dist/contact.schema.d.ts +26 -4
  22. package/dist/contact.schema.js +4 -2
  23. package/dist/credential.schema.d.ts +111 -3
  24. package/dist/credential.schema.js +15 -2
  25. package/dist/favorite/favorite.schema.d.ts +18 -4
  26. package/dist/favorite/favorite.schema.js +4 -2
  27. package/dist/favorite/index.d.ts +1 -1
  28. package/dist/favorite/index.js +1 -1
  29. package/dist/favorite/starred-sync.d.ts +2 -2
  30. package/dist/favorite/starred-sync.js +4 -4
  31. package/dist/file/file.schema.d.ts +26 -5
  32. package/dist/file/file.schema.js +5 -3
  33. package/dist/file/index.d.ts +1 -1
  34. package/dist/file/index.js +1 -1
  35. package/dist/grant.schema.d.ts +1 -0
  36. package/dist/grant.schema.js +3 -0
  37. package/dist/inbox-notification.schema.d.ts +10 -3
  38. package/dist/inbox-notification.schema.js +3 -1
  39. package/dist/index.d.ts +17 -17
  40. package/dist/index.js +17 -21
  41. package/dist/message.repository.js +2 -2
  42. package/dist/message.schema.js +8 -8
  43. package/dist/namespaces.d.ts +0 -3
  44. package/dist/namespaces.js +33 -7
  45. package/dist/profile.d.ts +2 -1
  46. package/dist/profile.js +6 -3
  47. package/dist/profile.repository.js +3 -3
  48. package/dist/profile.schema.d.ts +16 -3
  49. package/dist/profile.schema.js +3 -1
  50. package/dist/repository.d.ts +6 -1
  51. package/dist/repository.js +6 -1
  52. package/dist/schema.d.ts +102 -10
  53. package/dist/schema.js +31 -21
  54. package/dist/session/index.d.ts +1 -1
  55. package/dist/session/index.js +1 -1
  56. package/dist/session/session.schema.d.ts +7 -2
  57. package/dist/session/session.schema.js +32 -4
  58. package/dist/session.repository.d.ts +4 -0
  59. package/dist/session.repository.js +2 -2
  60. package/dist/settings/index.d.ts +1 -1
  61. package/dist/settings/index.js +1 -1
  62. package/dist/settings/settings.schema.d.ts +17 -5
  63. package/dist/settings/settings.schema.js +4 -2
  64. package/dist/thread.repository.js +2 -2
  65. package/dist/thread.schema.js +2 -2
  66. package/dist/vocab/message.vocab.js +8 -8
  67. package/dist/vocab/thread.vocab.js +2 -2
  68. package/package.json +15 -8
  69. package/dist/watch/index.d.ts +0 -281
  70. package/dist/watch/index.js +0 -1493
package/README.md CHANGED
@@ -1,593 +1,249 @@
1
- # LinX 数据模型
1
+ # LinX Models
2
2
 
3
- > 基于 Solid Pod 标准的 LinX 核心数据模型定义
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
- ### 2. Contact(联系人)
116
-
117
- **文件路径**: `src/contact/contact.schema.ts`
118
-
119
- **RDF 类**: `vcard:Individual`
120
-
121
- **支持类型**: `person`, `ai`, `organization`, `group`
122
-
123
- **核心字段**:
124
- ```typescript
125
- {
126
- // 姓名
127
- fullName: string; // vcard:fn ⭐ 必需
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
- **文件路径**: `src/chat/chat.schema.ts`
36
+ LinX-owned predicates and classes use the company namespace:
166
37
 
167
- **RDF 类**: `schema:ConversationThread`
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
- **RDF 类**: `schema:Message`
44
+ AI service catalog resources currently use the Xpod AI vocabularies:
193
45
 
194
- **字段**:
195
- ```typescript
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
- **文件路径**: `src/file/file.schema.ts`
53
+ The shared chat/runtime model is:
222
54
 
223
- **RDF 类**: `schema:MediaObject`
224
-
225
- **字段**:
226
- ```typescript
227
- {
228
- name: string; // schema:name 必需
229
- description: string; // schema:description
230
- mimeType: string; // schema:encodingFormat
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
- ### 6. Favorite(收藏)
68
+ - [`docs/agent-runtime-model.md`](docs/agent-runtime-model.md)
249
69
 
250
- **文件路径**: `src/favorite/favorite.schema.ts`
70
+ ## Agent vs AI Config
251
71
 
252
- **RDF 类**: `schema:CreativeWork`
72
+ `agentResource` and `ai-config` intentionally both mention provider/model, but
73
+ they are not the same resource.
253
74
 
254
- **支持收藏类型**: `message`, `file`, `contact`, `link`, `note`
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
- key: string; // linx:settingKey ⭐ 必需(唯一)
291
- value: string; // linx:settingValue (JSON 字符串)
292
- valueType: string; // linx:settingType (string, number, boolean, json)
293
- category: string; // dcterms:type (ui, ai, sync, privacy, notifications)
294
- label: string; // dcterms:title
295
- description: string; // dcterms:description
296
- owner: string; // dcterms:creator
297
- isSensitive: boolean; // linx:status (是否加密)
298
- createdAt: timestamp; // dcterms:created
299
- modifiedAt: timestamp; // dcterms:modified
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
- **预定义设置键** (`SETTING_KEYS`):
304
- ```typescript
305
- // UI 设置
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
- **文件路径**: `src/agent.schema.ts`
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
- **RDF 类**: `foaf:Agent`
103
+ The resources are:
343
104
 
344
- **字段**:
345
- ```typescript
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
- ```bash
401
- yarn workspace @linq/models install
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
- ### 1. 遵循 Solid 标准
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
- - 优先使用标准 RDF 词汇表(VCARD, FOAF, SIOC, DCTerms)
492
- - 仅在必要时使用自定义词汇表(`linx:` 命名空间)
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
- ### 2. 类型安全
145
+ ## Contact / Person / Agent
497
146
 
498
- - 使用 `drizzle-solid` 提供的类型推断
499
- - ✅ 导出 `Row`, `Insert`, `Update` 类型
500
- - ✅ 定义常量枚举(`CONTACT_TYPES`, `SETTING_KEYS` 等)
147
+ Contact, Person, and Agent are distinct:
501
148
 
502
- ### 3. 可扩展性
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
- - 支持软删除(`deletedAt` 字段)
505
- - ✅ 支持 JSON 字段存储复杂数据(标签、数组等)
506
- - ✅ 预留扩展字段(`tags`, `metadata`)
155
+ AI Secretary has both:
507
156
 
508
- ### 4. 互操作性
157
+ ```text
158
+ Contact
159
+ contactType: agent
160
+ entityUri: Agent profile URI
509
161
 
510
- - ✅ 与其他 Solid 应用兼容
511
- - ✅ 使用标准的 RDF 谓词
512
- - ✅ 遵循 SolidOS 的数据规范
162
+ Agent
163
+ home: /.data/agents/secretary/
164
+ profile: /.data/agents/secretary/profile.ttl
165
+ ```
513
166
 
514
- ### 5. 性能优化
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
- - 快照字段避免频繁查询(如 `Favorite.snapshotContent`)
517
- - 冗余字段提升列表显示性能(如 `Message.senderName`)
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
- 1. `src/<entity>/` 创建 `<entity>.schema.ts`
527
- 2. 使用 `podTable` 定义表结构
528
- 3. 选择合适的 RDF 类和谓词
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
- ```bash
546
- # 运行测试(待添加)
547
- yarn workspace @linq/models test
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 (LDP)](https://www.w3.org/TR/ldp/)
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