@yss123/cage-ontology 0.0.0-stage → 0.3.1
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/LICENSE +21 -0
- package/README.md +61 -2
- package/dist/catalog.d.ts +112 -0
- package/dist/catalog.js +197 -0
- package/dist/catalog.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shunshunyue and Cage contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,62 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @yss123/cage-ontology
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Cage 的运行时本体与能力发现包。从当前注册表提取聚合、命令、查询和审批的可解释声明,再按调用人的能力过滤并检索。主要用于服务端 AI 工具发现或受控能力目录,不是业务数据查询引擎、向量数据库或前端图谱组件。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
需要 Node.js 24+,与 kernel 等框架包保持同版本:
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
pnpm add @yss123/cage-ontology @yss123/cage-kernel
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
普通应用启用 `@yss123/cage-ai` 时由运行时使用本包,无需再创建另一套本体服务。开发期间查源码、图谱、路径或影响范围,使用 `@yss123/cage-cli` 的 `cage context/graph`。
|
|
14
|
+
|
|
15
|
+
## 服务端检索示例
|
|
16
|
+
|
|
17
|
+
下面是服务端集成函数;`registry` 必须来自当前应用,`ctx` 来自已认证且实时解析授权的身份。不要从浏览器输入构造权限上下文。
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
/** 从当前注册表构建目录;函数只提取声明,不查询业务表或执行命令。 */
|
|
21
|
+
import { type Ctx, type Registry } from '@yss123/cage-kernel';
|
|
22
|
+
import { ontologyCatalog, runtimeOntology } from '@yss123/cage-ontology';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 为受信任服务端调用方检索当前身份可发现的节点。
|
|
26
|
+
* @param registry 当前运行的领域注册表。
|
|
27
|
+
* @param ctx 认证层提供的身份和能力;行级范围由实际读取另行落实。
|
|
28
|
+
* @param query 中文说明、标识或字段关键词。
|
|
29
|
+
* @returns 有界摘要页;nextOffset 非空表示还存在后续结果。
|
|
30
|
+
*/
|
|
31
|
+
export function discover(registry: Registry, ctx: Ctx, query: string) {
|
|
32
|
+
const ontology = runtimeOntology(registry);
|
|
33
|
+
const catalog = ontologyCatalog(ontology);
|
|
34
|
+
return catalog.search(ctx, { query, offset: 0, limit: 10 });
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
高频使用时在注册表确定后构建一次 `RuntimeOntology` 与目录,并在每次请求中传入当前 `ctx`;不要缓存用户授权结果。注册声明变化后重新构建,本体的 `fingerprint` 记录来源注册表。
|
|
39
|
+
|
|
40
|
+
## 主要入口与结果
|
|
41
|
+
|
|
42
|
+
| 入口 | 作用 |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `runtimeOntology(registry)` | 提取公开字段、状态、输入、调用身份、规则名称与审批步骤 |
|
|
45
|
+
| `ontologyCatalog(ontology)`、`OntologyCatalog` | 为稳定本体建立检索与关联索引 |
|
|
46
|
+
| `catalog.search(ctx, input)` | 返回摘要、total、nextOffset、truncated;每页最多 20 项 |
|
|
47
|
+
| `catalog.describe(ctx, key, section)` | 按 overview、fields、input、related 展开详情;字段和关系支持分页 |
|
|
48
|
+
| `catalog.node(ctx, key)` | 读取一个授权可见节点;不存在和无权限均返回 NOT_FOUND |
|
|
49
|
+
| `nodeKey(node)` | 得到 `aggregate:Note`、`command:Note.create` 等稳定键 |
|
|
50
|
+
| `visibleNodes`、`searchOntology` | 直接过滤及简单关键词召回;大目录优先使用分页 catalog |
|
|
51
|
+
|
|
52
|
+
运行本体不包含 handler 函数体、SQL、隐藏字段或密钥。命令可发现性按命令能力判断,其他节点要求其读依赖的 read 能力;可发现不等于可以访问任意业务记录或立即执行命令。状态、版本、数据范围与硬约束仍在实际读写阶段判断。
|
|
53
|
+
|
|
54
|
+
搜索是确定性的关键词匹配,名称命中不是执行证据。规则只有名称时不能推断其阈值;分页未取完必须检查 `nextOffset/truncated`,不能把当前页当成完整业务集合。
|
|
55
|
+
|
|
56
|
+
## 文档
|
|
57
|
+
|
|
58
|
+
- [运行本体与 AI 工具发现](https://github.com/shunshunyue/cage/blob/main/docs/ai/intelligence.md)
|
|
59
|
+
- [开发时的本体查询与源码定位](https://github.com/shunshunyue/cage/blob/main/docs/ai/ontology-context.md)
|
|
60
|
+
- [能力发现与诊断](https://github.com/shunshunyue/cage/blob/main/docs/ai/diagnostics.md)
|
|
61
|
+
|
|
62
|
+
源码与反馈:[GitHub](https://github.com/shunshunyue/cage)。许可证:[MIT](https://github.com/shunshunyue/cage/blob/main/LICENSE)。
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 运行本体的确定性检索索引。构造时建立标题、字段和双向关系索引;查询时按当前权限过滤。
|
|
3
|
+
* 搜索与详情提供分页及原始 key,不使用向量推理;弱引用缓存随本体对象释放,不能缓存用户授权结果。
|
|
4
|
+
*/
|
|
5
|
+
import { type Ctx } from '@yss123/cage-kernel';
|
|
6
|
+
import type { RuntimeNode, RuntimeOntology } from './index.js';
|
|
7
|
+
/**
|
|
8
|
+
* 组合节点类型与稳定 ID,避免命令/查询等同名节点碰撞。
|
|
9
|
+
*/
|
|
10
|
+
export declare const nodeKey: (node: RuntimeNode) => string;
|
|
11
|
+
/**
|
|
12
|
+
* 模型发现阶段的精简节点摘要,完整 schema 按 key 另读。
|
|
13
|
+
*/
|
|
14
|
+
export interface OntologySummary {
|
|
15
|
+
/**
|
|
16
|
+
* 类型与 ID 组成的查询 key。
|
|
17
|
+
*/
|
|
18
|
+
key: string;
|
|
19
|
+
/**
|
|
20
|
+
* 原始声明标识。
|
|
21
|
+
*/
|
|
22
|
+
id: string;
|
|
23
|
+
/**
|
|
24
|
+
* 声明种类。
|
|
25
|
+
*/
|
|
26
|
+
kind: RuntimeNode['kind'];
|
|
27
|
+
/**
|
|
28
|
+
* 有界显示标题。
|
|
29
|
+
*/
|
|
30
|
+
title: string;
|
|
31
|
+
/**
|
|
32
|
+
* 关联聚合名列表。
|
|
33
|
+
*/
|
|
34
|
+
aggregates: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 目录过滤与分页输入,空关键词可浏览全部授权候选。
|
|
38
|
+
*/
|
|
39
|
+
export interface OntologySearch {
|
|
40
|
+
/**
|
|
41
|
+
* 关键词,省略或空值浏览目录。
|
|
42
|
+
*/
|
|
43
|
+
query?: string;
|
|
44
|
+
/**
|
|
45
|
+
* 限定种类,省略不限制。
|
|
46
|
+
*/
|
|
47
|
+
kinds?: RuntimeNode['kind'][];
|
|
48
|
+
/**
|
|
49
|
+
* 限定关联聚合,不隐式授予其读取权。
|
|
50
|
+
*/
|
|
51
|
+
aggregate?: string;
|
|
52
|
+
/**
|
|
53
|
+
* 零基分页偏移,由调用层 schema 校验。
|
|
54
|
+
*/
|
|
55
|
+
offset?: number;
|
|
56
|
+
/**
|
|
57
|
+
* 期望数量,搜索及详情各有内部上限。
|
|
58
|
+
*/
|
|
59
|
+
limit?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 命令按自身能力可见;其他节点需所有依赖聚合可读。可发现创建输入不要求同时授予对象 read,实际执行另行校验。
|
|
63
|
+
*/
|
|
64
|
+
export declare function nodeVisible(node: RuntimeNode, ctx: Ctx): boolean;
|
|
65
|
+
/** 对稳定声明预建索引;完整 schema 留在后端。搜索、详情和关系均可分页,不静默截断目录。 */
|
|
66
|
+
export declare class OntologyCatalog {
|
|
67
|
+
readonly ontology: RuntimeOntology;
|
|
68
|
+
/** 稳定 kind:id 到节点的索引;存声明数据,不缓存任何用户授权判断。 */
|
|
69
|
+
private nodes;
|
|
70
|
+
/** 聚合之间的双向关系发现索引;双向可发现不表示读权限或业务写关系也是双向。 */
|
|
71
|
+
private relations;
|
|
72
|
+
/** 搜索用的规范化文本和标题快照,构造时一次生成,命中后仍按当前 ctx 过滤可见性。 */
|
|
73
|
+
private documents;
|
|
74
|
+
/**
|
|
75
|
+
* 索引稳定本体;重复 key 立即拒绝,关系同时记录两端便于反向发现,但不改变实际读权限。
|
|
76
|
+
*/
|
|
77
|
+
constructor(ontology: RuntimeOntology);
|
|
78
|
+
/**
|
|
79
|
+
* 读取指定 key 并核对当前可见性;不存在与无权均返回 NOT_FOUND。
|
|
80
|
+
*/
|
|
81
|
+
node(ctx: Ctx, key: string): RuntimeNode;
|
|
82
|
+
/**
|
|
83
|
+
* 先按当前权限、调用方筛选器与聚合/种类过滤,再对标题和字段打分;同分按 key 稳定排序。
|
|
84
|
+
*/
|
|
85
|
+
private hits;
|
|
86
|
+
/** 服务端规划工具预算时只需 key,不受面向模型的摘要分页大小限制。 */
|
|
87
|
+
/**
|
|
88
|
+
* 返回全部合格 key 供后端预算规划;只省略摘要分页,不省略授权检查。
|
|
89
|
+
*/
|
|
90
|
+
keys(ctx: Ctx, input?: OntologySearch, eligible?: (node: RuntimeNode) => boolean): string[];
|
|
91
|
+
/**
|
|
92
|
+
* 返回至多 20 条摘要及 total/nextOffset;空查询仍分页,truncated 明确提示未取完。
|
|
93
|
+
*/
|
|
94
|
+
search(ctx: Ctx, input?: OntologySearch, eligible?: (node: RuntimeNode) => boolean): {
|
|
95
|
+
query: string;
|
|
96
|
+
total: number;
|
|
97
|
+
offset: number;
|
|
98
|
+
limit: number;
|
|
99
|
+
nextOffset: number | null;
|
|
100
|
+
truncated: boolean;
|
|
101
|
+
items: OntologySummary[];
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* 按 overview/fields/input/related 展开:输入 schema 保持完整,字段和关联分页。
|
|
105
|
+
* 关系沿双向声明扩展但逐节点检查可见性;返回数量上限不表示其他节点不存在。
|
|
106
|
+
*/
|
|
107
|
+
describe(ctx: Ctx, key: string, section?: 'overview' | 'fields' | 'input' | 'related', offset?: number, limit?: number): unknown;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 按本体对象复用索引,WeakMap 不延长本体生命周期;权限仍在每次方法调用时传入。
|
|
111
|
+
*/
|
|
112
|
+
export declare function ontologyCatalog(ontology: RuntimeOntology): OntologyCatalog;
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 运行本体的确定性检索索引。构造时建立标题、字段和双向关系索引;查询时按当前权限过滤。
|
|
3
|
+
* 搜索与详情提供分页及原始 key,不使用向量推理;弱引用缓存随本体对象释放,不能缓存用户授权结果。
|
|
4
|
+
*/
|
|
5
|
+
import { cageError } from '@yss123/cage-kernel';
|
|
6
|
+
/**
|
|
7
|
+
* 组合节点类型与稳定 ID,避免命令/查询等同名节点碰撞。
|
|
8
|
+
*/
|
|
9
|
+
export const nodeKey = (node) => `${node.kind}:${node.id}`;
|
|
10
|
+
/**
|
|
11
|
+
* 命令按自身能力可见;其他节点需所有依赖聚合可读。可发现创建输入不要求同时授予对象 read,实际执行另行校验。
|
|
12
|
+
*/
|
|
13
|
+
export function nodeVisible(node, ctx) {
|
|
14
|
+
// 获授创建命令不等于能读对象,但用户仍需发现该命令的合法参数。
|
|
15
|
+
return node.kind === 'command'
|
|
16
|
+
? ctx.capabilities.has(node.id)
|
|
17
|
+
: node.reads.every((name) => ctx.capabilities.has(`${name}.read`));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 规范化 Unicode 和大小写,使中英文标识以同一形式参与确定性匹配。
|
|
21
|
+
*/
|
|
22
|
+
const normalize = (value) => value.normalize('NFKC').toLowerCase();
|
|
23
|
+
/**
|
|
24
|
+
* 压缩显示标题并保留来源 key/聚合关联,不复制完整字段与输入 schema。
|
|
25
|
+
*/
|
|
26
|
+
const summary = (node) => ({
|
|
27
|
+
key: nodeKey(node),
|
|
28
|
+
id: node.id,
|
|
29
|
+
kind: node.kind,
|
|
30
|
+
title: node.title.slice(0, 300),
|
|
31
|
+
aggregates: node.reads,
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* 提取英文标识和中文整段及相邻双字词,去重后打分;没有语义向量召回。
|
|
35
|
+
*/
|
|
36
|
+
function terms(query) {
|
|
37
|
+
const normalized = normalize(query), words = [...(normalized.match(/[a-z0-9_.-]+/g) ?? [])];
|
|
38
|
+
for (const run of normalized.match(/[\p{Script=Han}]+/gu) ?? []) {
|
|
39
|
+
words.push(run);
|
|
40
|
+
for (let i = 0; i + 1 < run.length; i++)
|
|
41
|
+
words.push(run.slice(i, i + 2));
|
|
42
|
+
}
|
|
43
|
+
return [...new Set(words)];
|
|
44
|
+
}
|
|
45
|
+
/** 对稳定声明预建索引;完整 schema 留在后端。搜索、详情和关系均可分页,不静默截断目录。 */
|
|
46
|
+
export class OntologyCatalog {
|
|
47
|
+
ontology;
|
|
48
|
+
/** 稳定 kind:id 到节点的索引;存声明数据,不缓存任何用户授权判断。 */
|
|
49
|
+
nodes = new Map();
|
|
50
|
+
/** 聚合之间的双向关系发现索引;双向可发现不表示读权限或业务写关系也是双向。 */
|
|
51
|
+
relations = new Map();
|
|
52
|
+
/** 搜索用的规范化文本和标题快照,构造时一次生成,命中后仍按当前 ctx 过滤可见性。 */
|
|
53
|
+
documents;
|
|
54
|
+
/**
|
|
55
|
+
* 索引稳定本体;重复 key 立即拒绝,关系同时记录两端便于反向发现,但不改变实际读权限。
|
|
56
|
+
*/
|
|
57
|
+
constructor(ontology) {
|
|
58
|
+
this.ontology = ontology;
|
|
59
|
+
this.documents = ontology.nodes.map((node) => {
|
|
60
|
+
const key = nodeKey(node);
|
|
61
|
+
if (this.nodes.has(key))
|
|
62
|
+
throw new Error(`重复本体节点:${key}`);
|
|
63
|
+
this.nodes.set(key, node);
|
|
64
|
+
if (node.kind === 'aggregate')
|
|
65
|
+
for (const field of Object.values((node.data.fields ?? {}))) {
|
|
66
|
+
if (typeof field.relation !== 'string')
|
|
67
|
+
continue;
|
|
68
|
+
// 目录关系可双向发现;从关联对象进入也应找到引用它的业务,不改变实际读取授权。
|
|
69
|
+
for (const [from, to] of [
|
|
70
|
+
[node.id, field.relation],
|
|
71
|
+
[field.relation, node.id],
|
|
72
|
+
]) {
|
|
73
|
+
if (!this.relations.has(from))
|
|
74
|
+
this.relations.set(from, new Set());
|
|
75
|
+
this.relations.get(from).add(to);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const fields = Object.entries((node.data.fields ?? {}))
|
|
79
|
+
.map(([name, f]) => `${name} ${f.description ?? ''}`)
|
|
80
|
+
.join(' ');
|
|
81
|
+
return {
|
|
82
|
+
node,
|
|
83
|
+
title: normalize(`${node.id} ${node.title}`),
|
|
84
|
+
text: normalize(`${key} ${node.title} ${node.reads.join(' ')} ${fields}`),
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 读取指定 key 并核对当前可见性;不存在与无权均返回 NOT_FOUND。
|
|
90
|
+
*/
|
|
91
|
+
node(ctx, key) {
|
|
92
|
+
const node = this.nodes.get(key);
|
|
93
|
+
if (!node || !nodeVisible(node, ctx))
|
|
94
|
+
throw cageError('NOT_FOUND');
|
|
95
|
+
return node;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 先按当前权限、调用方筛选器与聚合/种类过滤,再对标题和字段打分;同分按 key 稳定排序。
|
|
99
|
+
*/
|
|
100
|
+
hits(ctx, input, eligible) {
|
|
101
|
+
const query = normalize(input.query?.trim() ?? ''), words = terms(query);
|
|
102
|
+
return this.documents
|
|
103
|
+
.filter(({ node }) => nodeVisible(node, ctx) &&
|
|
104
|
+
eligible(node) &&
|
|
105
|
+
(!input.kinds?.length || input.kinds.includes(node.kind)) &&
|
|
106
|
+
(!input.aggregate || node.reads.includes(input.aggregate)))
|
|
107
|
+
.map((doc) => ({
|
|
108
|
+
...doc,
|
|
109
|
+
score: !query
|
|
110
|
+
? 1
|
|
111
|
+
: (normalize(nodeKey(doc.node)) === query || normalize(doc.node.id) === query ? 1000 : 0) +
|
|
112
|
+
words.reduce((score, word) => score + (doc.title.includes(word) ? Math.min(20, word.length) * 3 : doc.text.includes(word) ? 1 : 0), 0),
|
|
113
|
+
}))
|
|
114
|
+
.filter((hit) => hit.score > 0)
|
|
115
|
+
.sort((a, b) => b.score - a.score || nodeKey(a.node).localeCompare(nodeKey(b.node)));
|
|
116
|
+
}
|
|
117
|
+
/** 服务端规划工具预算时只需 key,不受面向模型的摘要分页大小限制。 */
|
|
118
|
+
/**
|
|
119
|
+
* 返回全部合格 key 供后端预算规划;只省略摘要分页,不省略授权检查。
|
|
120
|
+
*/
|
|
121
|
+
keys(ctx, input = {}, eligible = () => true) {
|
|
122
|
+
return this.hits(ctx, input, eligible).map((hit) => nodeKey(hit.node));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 返回至多 20 条摘要及 total/nextOffset;空查询仍分页,truncated 明确提示未取完。
|
|
126
|
+
*/
|
|
127
|
+
search(ctx, input = {}, eligible = () => true) {
|
|
128
|
+
const offset = input.offset ?? 0, limit = Math.max(1, Math.min(20, input.limit ?? 10));
|
|
129
|
+
const hits = this.hits(ctx, input, eligible);
|
|
130
|
+
return {
|
|
131
|
+
query: input.query ?? '',
|
|
132
|
+
total: hits.length,
|
|
133
|
+
offset,
|
|
134
|
+
limit,
|
|
135
|
+
nextOffset: offset + limit < hits.length ? offset + limit : null,
|
|
136
|
+
truncated: offset + limit < hits.length,
|
|
137
|
+
items: hits.slice(offset, offset + limit).map((hit) => summary(hit.node)),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 按 overview/fields/input/related 展开:输入 schema 保持完整,字段和关联分页。
|
|
142
|
+
* 关系沿双向声明扩展但逐节点检查可见性;返回数量上限不表示其他节点不存在。
|
|
143
|
+
*/
|
|
144
|
+
describe(ctx, key, section = 'overview', offset = 0, limit = 12) {
|
|
145
|
+
const node = this.node(ctx, key), base = summary(node);
|
|
146
|
+
limit = Math.max(1, Math.min(30, limit));
|
|
147
|
+
if (section === 'input')
|
|
148
|
+
return { ...base, input: node.data.input ?? null };
|
|
149
|
+
if (section === 'fields') {
|
|
150
|
+
const fields = Object.entries((node.data.fields ?? {}));
|
|
151
|
+
return {
|
|
152
|
+
...base,
|
|
153
|
+
total: fields.length,
|
|
154
|
+
offset,
|
|
155
|
+
nextOffset: offset + limit < fields.length ? offset + limit : null,
|
|
156
|
+
fields: Object.fromEntries(fields.slice(offset, offset + limit)),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (section === 'related') {
|
|
160
|
+
const aggregates = new Set(node.reads);
|
|
161
|
+
for (const aggregate of node.reads)
|
|
162
|
+
for (const related of this.relations.get(aggregate) ?? [])
|
|
163
|
+
aggregates.add(related);
|
|
164
|
+
const related = this.ontology.nodes
|
|
165
|
+
.filter((candidate) => candidate !== node && nodeVisible(candidate, ctx) && candidate.reads.some((a) => aggregates.has(a)))
|
|
166
|
+
.sort((a, b) => nodeKey(a).localeCompare(nodeKey(b)));
|
|
167
|
+
return {
|
|
168
|
+
...base,
|
|
169
|
+
total: related.length,
|
|
170
|
+
offset,
|
|
171
|
+
nextOffset: offset + limit < related.length ? offset + limit : null,
|
|
172
|
+
items: related.slice(offset, offset + limit).map(summary),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
...base,
|
|
177
|
+
definition: Object.fromEntries(Object.entries(node.data).filter(([key]) => !['fields', 'input'].includes(key))),
|
|
178
|
+
fieldCount: Object.keys((node.data.fields ?? {})).length,
|
|
179
|
+
hasInput: !!node.data.input,
|
|
180
|
+
sections: ['overview', 'fields', 'input', 'related'],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/** 按不可变本体对象复用检索索引;弱引用随本体释放,不跨对象复用旧注册表内容。 */
|
|
185
|
+
const catalogs = new WeakMap();
|
|
186
|
+
/**
|
|
187
|
+
* 按本体对象复用索引,WeakMap 不延长本体生命周期;权限仍在每次方法调用时传入。
|
|
188
|
+
*/
|
|
189
|
+
export function ontologyCatalog(ontology) {
|
|
190
|
+
let catalog = catalogs.get(ontology);
|
|
191
|
+
if (!catalog) {
|
|
192
|
+
catalog = new OntologyCatalog(ontology);
|
|
193
|
+
catalogs.set(ontology, catalog);
|
|
194
|
+
}
|
|
195
|
+
return catalog;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从运行注册表构建可解释的领域目录,供 AI 发现声明和读取规则摘要。
|
|
3
|
+
* 不导出 handler、SQL、隐藏字段和密钥;本体只描述声明,实际数据读取/写入仍走内核。
|
|
4
|
+
*/
|
|
5
|
+
import { type Registry, type Ctx } from '@yss123/cage-kernel';
|
|
6
|
+
export { OntologyCatalog, ontologyCatalog, nodeKey, type OntologySummary, type OntologySearch } from './catalog.js';
|
|
7
|
+
/**
|
|
8
|
+
* 一个聚合、命令、查询或审批的公开声明节点,data 只保存可解释事实。
|
|
9
|
+
*/
|
|
10
|
+
export interface RuntimeNode {
|
|
11
|
+
id: string; /** 节点种类,和 id 一起形成唯一 key。 */
|
|
12
|
+
kind: 'aggregate' | 'command' | 'query' | 'approval'; /** 声明中文说明,缺失时回退稳定标识。 */
|
|
13
|
+
title: string; /** 可解释的字段、输入、状态和规则摘要,不含函数体。 */
|
|
14
|
+
data: Record<string, unknown>; /** 关联的聚合名,用于发现权限和关系组织。 */
|
|
15
|
+
reads: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 带版本与注册指纹的运行本体,可在启动时验证与当前注册表一致。
|
|
19
|
+
*/
|
|
20
|
+
export interface RuntimeOntology {
|
|
21
|
+
version: 1; /** 来源注册表指纹,防止旧目录与新运行混用。 */
|
|
22
|
+
fingerprint: string; /** 公开声明节点列表,不代表全部业务数据。 */
|
|
23
|
+
nodes: RuntimeNode[];
|
|
24
|
+
}
|
|
25
|
+
/** 只导出可解释的声明事实;handler、SQL、隐藏字段与密钥不会成为模型上下文。 */
|
|
26
|
+
/**
|
|
27
|
+
* 提取公开字段、状态、命令输入与调用身份、查询依赖和审批步骤;不序列化可执行函数。
|
|
28
|
+
* @param registry 当前运行注册表。
|
|
29
|
+
* @returns 与注册指纹绑定的目录;规则只有名称时不能据此推断阈值。
|
|
30
|
+
*/
|
|
31
|
+
export declare function runtimeOntology(registry: Registry): RuntimeOntology;
|
|
32
|
+
/**
|
|
33
|
+
* 按当前能力筛选可发现节点;命令依赖命令能力,其他节点依赖全部 reads 的 read 能力,行范围仍由实际读取处理。
|
|
34
|
+
*/
|
|
35
|
+
export declare function visibleNodes(ontology: RuntimeOntology, ctx: Ctx): RuntimeNode[];
|
|
36
|
+
/** 确定性召回保留来源 ID;模型解释不能把名称匹配当作执行证据。 */
|
|
37
|
+
/**
|
|
38
|
+
* 旧式确定性关键词检索,按匹配数和 ID 排序,最多 40 项;名称匹配不是执行证据,大目录优先用分页 catalog。
|
|
39
|
+
*/
|
|
40
|
+
export declare function searchOntology(ontology: RuntimeOntology, ctx: Ctx, query: string, limit?: number): RuntimeNode[];
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从运行注册表构建可解释的领域目录,供 AI 发现声明和读取规则摘要。
|
|
3
|
+
* 不导出 handler、SQL、隐藏字段和密钥;本体只描述声明,实际数据读取/写入仍走内核。
|
|
4
|
+
*/
|
|
5
|
+
import { registryFingerprint } from '@yss123/cage-kernel';
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { nodeVisible } from './catalog.js';
|
|
8
|
+
export { OntologyCatalog, ontologyCatalog, nodeKey } from './catalog.js';
|
|
9
|
+
/** 只导出可解释的声明事实;handler、SQL、隐藏字段与密钥不会成为模型上下文。 */
|
|
10
|
+
/**
|
|
11
|
+
* 提取公开字段、状态、命令输入与调用身份、查询依赖和审批步骤;不序列化可执行函数。
|
|
12
|
+
* @param registry 当前运行注册表。
|
|
13
|
+
* @returns 与注册指纹绑定的目录;规则只有名称时不能据此推断阈值。
|
|
14
|
+
*/
|
|
15
|
+
export function runtimeOntology(registry) {
|
|
16
|
+
const nodes = [];
|
|
17
|
+
for (const aggregate of registry.aggregates)
|
|
18
|
+
nodes.push({ id: aggregate.name, kind: 'aggregate', title: aggregate.description ?? aggregate.name, reads: [aggregate.name],
|
|
19
|
+
data: { fields: Object.fromEntries(Object.entries(aggregate.fields).filter(([, f]) => !f.isHidden).map(([name, f]) => [name, {
|
|
20
|
+
kind: f.kind, description: f.description, optional: f.isOptional, sensitive: f.sensitiveKind, relation: f.ref, values: f.values,
|
|
21
|
+
}])), states: aggregate.states.values, invariants: Object.keys(aggregate.invariants) } });
|
|
22
|
+
for (const { capability, cmd } of registry.commands)
|
|
23
|
+
nodes.push({ id: capability, kind: 'command', title: cmd.description ?? capability, reads: [cmd.agg.name],
|
|
24
|
+
data: { aggregate: cmd.agg.name, input: z.toJSONSchema(cmd.input, { io: 'input', unrepresentable: 'any' }), from: cmd.from, to: cmd.to,
|
|
25
|
+
invokedBy: cmd.invokedBy, constraints: cmd.constraints.map(c => c.name) } });
|
|
26
|
+
for (const query of registry.queries)
|
|
27
|
+
nodes.push({ id: query.name, kind: 'query', title: query.description ?? query.name, reads: query.reads.map(a => a.name),
|
|
28
|
+
data: { input: z.toJSONSchema(query.input, { io: 'input', unrepresentable: 'any' }), purpose: query.audit?.purpose } });
|
|
29
|
+
for (const { a } of registry.approvals) {
|
|
30
|
+
const route = registry.extensions.find(e => e.kind === 'ROUTE' && e.value.process === a.process);
|
|
31
|
+
const publicStep = (step) => step.kind === 'when' ? { kind: 'when', condition: step.cond, steps: step.steps.map(publicStep) }
|
|
32
|
+
: step.kind === 'parallel' ? { kind: 'parallel', title: step.title, join: 'all',
|
|
33
|
+
branches: step.branches.map((branch) => ({ title: branch.title, steps: branch.nodes.map(publicStep) })) }
|
|
34
|
+
: step.kind === 'ai' ? { kind: 'ai', title: step.title, outcomes: ['pass', 'return', 'manual'] }
|
|
35
|
+
: { kind: 'human', title: step.title, approver: step.approver, mode: step.mode };
|
|
36
|
+
nodes.push({ id: a.process, kind: 'approval', title: a.process, reads: [a.agg.name], data: { aggregate: a.agg.name,
|
|
37
|
+
onApproved: registry.capabilityOf(a.onApproved), onRejected: registry.capabilityOf(a.onRejected),
|
|
38
|
+
onReturned: a.onReturned && registry.capabilityOf(a.onReturned), steps: route?.value.nodes.map(publicStep) ?? [] } });
|
|
39
|
+
}
|
|
40
|
+
return { version: 1, fingerprint: registryFingerprint(registry), nodes };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 按当前能力筛选可发现节点;命令依赖命令能力,其他节点依赖全部 reads 的 read 能力,行范围仍由实际读取处理。
|
|
44
|
+
*/
|
|
45
|
+
export function visibleNodes(ontology, ctx) {
|
|
46
|
+
return ontology.nodes.filter(node => nodeVisible(node, ctx));
|
|
47
|
+
}
|
|
48
|
+
/** 确定性召回保留来源 ID;模型解释不能把名称匹配当作执行证据。 */
|
|
49
|
+
/**
|
|
50
|
+
* 旧式确定性关键词检索,按匹配数和 ID 排序,最多 40 项;名称匹配不是执行证据,大目录优先用分页 catalog。
|
|
51
|
+
*/
|
|
52
|
+
export function searchOntology(ontology, ctx, query, limit = 12) {
|
|
53
|
+
const text = query.normalize('NFKC').toLowerCase();
|
|
54
|
+
const words = text.match(/[a-z0-9_.]+|[\p{Script=Han}]{2}/gu) ?? [text];
|
|
55
|
+
return visibleNodes(ontology, ctx).map(node => ({ node, score: words.reduce((n, word) => n + (JSON.stringify(node).toLowerCase().includes(word) ? 1 : 0), 0) }))
|
|
56
|
+
.filter(entry => !text || entry.score > 0).sort((a, b) => b.score - a.score || a.node.id.localeCompare(b.node.id)).slice(0, Math.min(40, limit)).map(entry => entry.node);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,mBAAmB,EAAwC,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,OAAO,EAA6C,MAAM,cAAc,CAAC;AAWpH,gDAAgD;AAChD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,QAAkB;IAChD,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;YACtK,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,MAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;wBACrI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM;qBAChI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,KAAK,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,QAAQ,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,IAAI,UAAU,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAC5J,IAAI,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE;gBACpI,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACjF,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3J,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1H,KAAK,MAAM,EAAE,CAAC,EAAE,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;QACjG,MAAM,UAAU,GAAG,CAAC,IAAS,EAAW,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;YACzI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK;gBAC7E,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;gBAChH,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;oBAChG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QACnF,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI;gBAChH,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;gBAChG,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,mBAAmB,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAyB,EAAE,GAAQ;IAC9D,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,sCAAsC;AACtC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAyB,EAAE,GAAQ,EAAE,KAAa,EAAE,KAAK,GAAG,EAAE;IAC3F,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxE,OAAO,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7J,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC9K,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yss123/cage-ontology",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Cage 运行时本体与受控能力发现",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"zod": "^4.1.5",
|
|
19
|
+
"@yss123/cage-kernel": "0.3.1"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=24"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/shunshunyue/cage.git",
|
|
28
|
+
"directory": "packages/ontology"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"registry": "https://registry.npmjs.org/"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -p tsconfig.json",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
37
|
+
}
|
|
6
38
|
}
|