@undefineds.co/models 0.2.37 → 0.2.38

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
@@ -163,13 +163,14 @@ Contact
163
163
  entity: Agent context-root URI
164
164
 
165
165
  Agent
166
- root: /agents/__secretary__/
167
- meta: /agents/__secretary__/.meta
166
+ id: /.data/agents/__secretary__/index.ttl#this
167
+ root: /.data/agents/__secretary__/
168
+ meta: /.data/agents/__secretary__/.meta
168
169
  ```
169
170
 
170
171
  External people, services, or bots may appear as Contacts without being LinX
171
172
  Agents. If something is modeled as an executable LinX Agent, the Agent resource
172
- identity is the context-root container itself.
173
+ identity is `index.ttl#this` inside the context-root container.
173
174
 
174
175
  ## Resource Ownership
175
176
 
@@ -203,7 +204,7 @@ Representative paths:
203
204
  /.data/chat/{chatId}/index.ttl#this
204
205
  /.data/chat/{chatId}/index.ttl#{threadId}
205
206
  /.data/chat/{chatId}/{yyyy}/{MM}/{dd}/messages.ttl#{messageId}
206
- /agents/{agentId}/
207
+ /.data/agents/{agentId}/index.ttl#this
207
208
  /.data/sessions/{yyyy}/{MM}/{dd}/{sessionId}.ttl
208
209
  /settings/providers/{providerId}.ttl
209
210
  /settings/providers/{providerId}.ttl#{modelId}
@@ -1,7 +1,8 @@
1
1
  import { boolean, object, podTable, string, integer, timestamp, text, real, uri, id } from "@undefineds.co/drizzle-solid";
2
2
  import { UDFS, DCTerms, FOAF, VCARD } from "./namespaces.js";
3
+ import { agentResourceId } from "./resource-identity.js";
3
4
  export const agentResource = podTable("agent", {
4
- id: id("id").default("{key}/"),
5
+ id: id("id").default((key) => agentResourceId(key)),
5
6
  name: string("name").predicate(FOAF.name).notNull(),
6
7
  description: text("description").predicate(DCTerms.description),
7
8
  avatarUrl: uri("avatarUrl").predicate(VCARD.hasPhoto),
@@ -29,8 +30,8 @@ export const agentResource = podTable("agent", {
29
30
  updatedAt: timestamp("updatedAt").predicate(DCTerms.modified).notNull().defaultNow(),
30
31
  deletedAt: timestamp("deletedAt").predicate(UDFS.deletedAt),
31
32
  }, {
32
- base: '/agents/',
33
- sparqlEndpoint: '/agents/-/sparql',
33
+ base: '/.data/agents/',
34
+ sparqlEndpoint: '/.data/agents/-/sparql',
34
35
  type: FOAF.Agent,
35
36
  namespace: UDFS,
36
37
  });
@@ -12,7 +12,7 @@ export const fixtureContactAgentWorkspace = {
12
12
  name: 'Secretary@linx',
13
13
  rdfType: ContactClass.AGENT,
14
14
  contactType: 'agent',
15
- entity: 'https://pod.example/agents/__secretary__/',
15
+ entity: 'https://pod.example/.data/agents/__secretary__/index.ttl#this',
16
16
  isPublic: false,
17
17
  };
18
18
  export const fixtureChatDirectAI = {
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export { ChatStatus, chatResource, chatTable, type ChatMetadata, type ChatMember
9
9
  export { chatRepository } from './chat.repository';
10
10
  export { buildChatTargetRef, extractChatIdFromChatRef, extractChatTargetRef, extractChatThreadRef, extractThreadIdFromThreadRef, resolveThreadChatId, toTimestamp, type ChatTargetRef, type ChatThreadRef, } from './chat.utils';
11
11
  export { buildModelResourceId, buildModelResourceIri, buildModelResourceIriForDatabase, resolveModelResourceIri, resolveModelResourceIriForDatabase, type ModelResourceTarget, } from './resource-refs';
12
+ export { agentHomeDirFromResourceId, agentHomePathFromResourceId, agentKeyFromResourceRef, agentKeyFromResourceId, agentResourceId, asBaseRelativeResourceId, asResourceIri, requireRowResourceId, type BaseRelativeResourceId, type ResourceIri, } from './resource-identity';
12
13
  export { ThreadStatus, threadResource, threadTable, type ThreadStatusType, type ThreadRow, type ThreadInsert, type ThreadUpdate, } from './thread.schema';
13
14
  export { threadRepository } from './thread.repository';
14
15
  export { MessageRole, MessageStatus, messageResource, messageTable, type MessageRoleType, type MessageStatusType, type MessageRow, type MessageInsert, type MessageUpdate, } from './message.schema';
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ export { ChatStatus, chatResource, chatTable, } from './chat.schema.js';
21
21
  export { chatRepository } from './chat.repository.js';
22
22
  export { buildChatTargetRef, extractChatIdFromChatRef, extractChatTargetRef, extractChatThreadRef, extractThreadIdFromThreadRef, resolveThreadChatId, toTimestamp, } from './chat.utils.js';
23
23
  export { buildModelResourceId, buildModelResourceIri, buildModelResourceIriForDatabase, resolveModelResourceIri, resolveModelResourceIriForDatabase, } from './resource-refs.js';
24
+ export { agentHomeDirFromResourceId, agentHomePathFromResourceId, agentKeyFromResourceRef, agentKeyFromResourceId, agentResourceId, asBaseRelativeResourceId, asResourceIri, requireRowResourceId, } from './resource-identity.js';
24
25
  export { ThreadStatus, threadResource, threadTable, } from './thread.schema.js';
25
26
  export { threadRepository } from './thread.repository.js';
26
27
  export { MessageRole, MessageStatus, messageResource, messageTable, } from './message.schema.js';
@@ -52,7 +52,7 @@ export const messageResource = podTable('chat_message', {
52
52
  thread: uri('thread').predicate(SIOC.has_member).inverse().link(threadResource),
53
53
  // maker is the entity URI of the message author:
54
54
  // - User: their WebID (https://user.pod/profile/card#me)
55
- // - AI: Agent URI (/agents/{id}/)
55
+ // - AI: Agent URI (/.data/agents/{id}/index.ttl#this)
56
56
  // - External: Contact URI (/.data/contacts/{id}.ttl#this)
57
57
  // No reference() constraint - accepts any valid URI.
58
58
  maker: uri('maker').predicate(FOAF.maker),
@@ -0,0 +1,19 @@
1
+ declare const baseRelativeResourceIdBrand: unique symbol;
2
+ declare const resourceIriBrand: unique symbol;
3
+ export type BaseRelativeResourceId = string & {
4
+ readonly [baseRelativeResourceIdBrand]: 'BaseRelativeResourceId';
5
+ };
6
+ export type ResourceIri = string & {
7
+ readonly [resourceIriBrand]: 'ResourceIri';
8
+ };
9
+ export declare function asBaseRelativeResourceId(value: string, label?: string): BaseRelativeResourceId;
10
+ export declare function asResourceIri(value: string, label?: string): ResourceIri;
11
+ export declare function requireRowResourceId(row: {
12
+ id?: string | null;
13
+ } | null | undefined, label?: string): BaseRelativeResourceId;
14
+ export declare function agentResourceId(key?: string | null): BaseRelativeResourceId;
15
+ export declare function agentKeyFromResourceId(resourceId: string): string;
16
+ export declare function agentKeyFromResourceRef(resourceRef: string): string;
17
+ export declare function agentHomeDirFromResourceId(resourceId: string): BaseRelativeResourceId;
18
+ export declare function agentHomePathFromResourceId(resourceId: string): string;
19
+ export {};
@@ -0,0 +1,68 @@
1
+ const ABSOLUTE_IRI = /^[a-zA-Z][a-zA-Z\d+.-]*:/;
2
+ const AGENT_RESOURCE_ID = /^([A-Za-z0-9_.-]+)\/index\.ttl#this$/;
3
+ const AGENT_KEY = /^[A-Za-z0-9_.-]+$/;
4
+ export function asBaseRelativeResourceId(value, label = 'Resource id') {
5
+ if (typeof value !== 'string' || value.trim().length === 0) {
6
+ throw new Error(`${label} must be a non-empty base-relative resource id.`);
7
+ }
8
+ const normalized = value.trim();
9
+ if (ABSOLUTE_IRI.test(normalized) || normalized.startsWith('/') || normalized.startsWith('//')) {
10
+ throw new Error(`${label} must be a base-relative resource id.`);
11
+ }
12
+ return normalized;
13
+ }
14
+ export function asResourceIri(value, label = 'Resource IRI') {
15
+ if (typeof value !== 'string' || value.trim().length === 0) {
16
+ throw new Error(`${label} must be a non-empty resource IRI.`);
17
+ }
18
+ const normalized = value.trim();
19
+ if (!ABSOLUTE_IRI.test(normalized)) {
20
+ throw new Error(`${label} must be a full resource IRI.`);
21
+ }
22
+ return normalized;
23
+ }
24
+ export function requireRowResourceId(row, label = 'Pod row') {
25
+ if (!row || typeof row.id !== 'string' || row.id.trim().length === 0) {
26
+ throw new Error(`${label} row is missing row.id.`);
27
+ }
28
+ return asBaseRelativeResourceId(row.id, `${label} row.id`);
29
+ }
30
+ function defaultAgentKey() {
31
+ return `agent_${Math.random().toString(36).slice(2, 12)}`;
32
+ }
33
+ export function agentResourceId(key) {
34
+ const raw = typeof key === 'string' ? key.trim() : '';
35
+ const value = raw || defaultAgentKey();
36
+ if (AGENT_RESOURCE_ID.test(value)) {
37
+ return asBaseRelativeResourceId(value, 'Agent resource id');
38
+ }
39
+ if (!AGENT_KEY.test(value)) {
40
+ throw new Error('Agent key must be a local key using letters, numbers, dot, underscore, or dash.');
41
+ }
42
+ return asBaseRelativeResourceId(`${value}/index.ttl#this`, 'Agent resource id');
43
+ }
44
+ export function agentKeyFromResourceId(resourceId) {
45
+ const id = asBaseRelativeResourceId(resourceId, 'Agent resource id');
46
+ const match = id.match(AGENT_RESOURCE_ID);
47
+ if (!match?.[1]) {
48
+ throw new Error('Agent resource id must use {agentKey}/index.ttl#this.');
49
+ }
50
+ return match[1];
51
+ }
52
+ export function agentKeyFromResourceRef(resourceRef) {
53
+ if (typeof resourceRef !== 'string' || resourceRef.trim().length === 0) {
54
+ throw new Error('Agent resource ref must be a non-empty Agent id or IRI.');
55
+ }
56
+ const normalized = resourceRef.trim();
57
+ const iriMatch = normalized.match(/\/\.data\/agents\/([A-Za-z0-9_.-]+)\/index\.ttl#this$/);
58
+ if (iriMatch?.[1]) {
59
+ return iriMatch[1];
60
+ }
61
+ return agentKeyFromResourceId(normalized);
62
+ }
63
+ export function agentHomeDirFromResourceId(resourceId) {
64
+ return asBaseRelativeResourceId(`${agentKeyFromResourceId(resourceId)}/`, 'Agent home dir');
65
+ }
66
+ export function agentHomePathFromResourceId(resourceId) {
67
+ return `/.data/agents/${agentKeyFromResourceId(resourceId)}/`;
68
+ }
@@ -1,6 +1,8 @@
1
1
  import { boolean, id, object, podTable, string, timestamp, uri } from '@undefineds.co/drizzle-solid';
2
2
  import { agentResource } from './agent.schema.js';
3
3
  import { DCTerms, UDFS } from './namespaces.js';
4
+ import { resourceKey } from './resource-id-defaults.js';
5
+ import { agentKeyFromResourceRef } from './resource-identity.js';
4
6
  /**
5
7
  * Skill binding resource.
6
8
  *
@@ -8,7 +10,10 @@ import { DCTerms, UDFS } from './namespaces.js';
8
10
  * binding and lightweight load metadata; it does not duplicate full skill text.
9
11
  */
10
12
  export const skillResource = podTable('skill', {
11
- id: id('id').default('{agent.key}/skills/{key}/'),
13
+ id: id('id').default((key, row) => {
14
+ const agentRef = typeof row?.agent === 'string' ? row.agent : '';
15
+ return `${agentKeyFromResourceRef(agentRef)}/skills/${resourceKey(key, 'skill')}/`;
16
+ }),
12
17
  agent: uri('agent').predicate(UDFS.agent).notNull().link(agentResource),
13
18
  root: uri('root').predicate(UDFS.root),
14
19
  name: string('name').predicate(UDFS.name).notNull(),
@@ -22,8 +27,8 @@ export const skillResource = podTable('skill', {
22
27
  createdAt: timestamp('createdAt').predicate(DCTerms.created).notNull().defaultNow(),
23
28
  updatedAt: timestamp('updatedAt').predicate(DCTerms.modified).notNull().defaultNow(),
24
29
  }, {
25
- base: '/agents/',
26
- sparqlEndpoint: '/agents/-/sparql',
30
+ base: '/.data/agents/',
31
+ sparqlEndpoint: '/.data/agents/-/sparql',
27
32
  type: UDFS.Skill,
28
33
  namespace: UDFS,
29
34
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@undefineds.co/models",
3
- "version": "0.2.37",
3
+ "version": "0.2.38",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",