@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 CHANGED
@@ -1,594 +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
- - `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
- ### 2. Contact(联系人)
117
-
118
- **文件路径**: `src/contact/contact.schema.ts`
119
-
120
- **RDF 类**: `vcard:Individual`
121
-
122
- **支持类型**: `person`, `ai`, `organization`, `group`
123
-
124
- **核心字段**:
125
- ```typescript
126
- {
127
- // 姓名
128
- fullName: string; // vcard:fn ⭐ 必需
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
- ### 3. Chat(聊天会话)
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
- **文件路径**: `src/chat/message.schema.ts`
44
+ AI service catalog resources currently use the Xpod AI vocabularies:
192
45
 
193
- **RDF 类**: `schema:Message`
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
- ### 5. File(文件管理)
53
+ The shared chat/runtime model is:
221
54
 
222
- **文件路径**: `src/file/file.schema.ts`
223
-
224
- **RDF 类**: `schema:MediaObject`
225
-
226
- **字段**:
227
- ```typescript
228
- {
229
- name: string; // schema:name 必需
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
- **RDF 类**: `schema:CreativeWork`
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
- ### 7. Settings(用户设置)
72
+ `agentResource` and `ai-config` intentionally both mention provider/model, but
73
+ they are not the same resource.
283
74
 
284
- **文件路径**: `src/settings/settings.schema.ts`
75
+ `agentResource` answers: which executable actor is this, and what defaults
76
+ should it use at runtime?
285
77
 
286
- **RDF 类**: `schema:PropertyValue`
78
+ Current Agent fields include:
287
79
 
288
- **字段**:
289
- ```typescript
80
+ ```ts
290
81
  {
291
- key: string; // linx:settingKey ⭐ 必需(唯一)
292
- value: string; // linx:settingValue (JSON 字符串)
293
- valueType: string; // linx:settingType (string, number, boolean, json)
294
- category: string; // dcterms:type (ui, ai, sync, privacy, notifications)
295
- label: string; // dcterms:title
296
- description: string; // dcterms:description
297
- owner: string; // dcterms:creator
298
- isSensitive: boolean; // linx:status (是否加密)
299
- createdAt: timestamp; // dcterms:created
300
- 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
301
93
  }
302
94
  ```
303
95
 
304
- **预定义设置键** (`SETTING_KEYS`):
305
- ```typescript
306
- // UI 设置
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
- **文件路径**: `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?
342
102
 
343
- **RDF 类**: `foaf:Agent`
103
+ The resources are:
344
104
 
345
- **字段**:
346
- ```typescript
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
- ```bash
402
- yarn workspace @linq/models install
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
- // Solid resources
413
- contactResource,
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
- ### 1. 遵循 Solid 标准
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
- - 优先使用标准 RDF 词汇表(VCARD, FOAF, SIOC, DCTerms)
493
- - ✅ 仅在必要时使用自定义词汇表(`linx:` 命名空间)
494
- - ✅ 所有数据存储在 Pod 的 LDP 容器中
495
- - ✅ 使用标准 RDF 类(`vcard:Individual`, `schema:Message` 等)
145
+ ## Contact / Person / Agent
496
146
 
497
- ### 2. 类型安全
147
+ Contact, Person, and Agent are distinct:
498
148
 
499
- - ✅ 使用 `drizzle-solid` 提供的类型推断
500
- - 导出 `Row`, `Insert`, `Update` 类型
501
- - 定义常量枚举(`CONTACT_TYPES`, `SETTING_KEYS` 等)
502
-
503
- ### 3. 可扩展性
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
- - 与其他 Solid 应用兼容
512
- - ✅ 使用标准的 RDF 谓词
513
- - ✅ 遵循 SolidOS 的数据规范
155
+ AI Secretary has both:
514
156
 
515
- ### 5. 性能优化
157
+ ```text
158
+ Contact
159
+ contactType: agent
160
+ entityUri: Agent profile URI
516
161
 
517
- - ✅ 快照字段避免频繁查询(如 `Favorite.snapshotContent`)
518
- - ✅ 冗余字段提升列表显示性能(如 `Message.senderName`)
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
- 1. 在 `src/<entity>/` 创建 `<entity>.schema.ts`
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
- ```bash
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 (LDP)](https://www.w3.org/TR/ldp/)
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