clearai-dsh 0.2.0 → 0.2.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/CHANGELOG.md +29 -2
- package/README.md +29 -3
- package/README.zh-CN.md +30 -4
- package/lib/client.js +563 -117
- package/lib/domain-language.js +43 -25
- package/lib/fold.js +710 -6
- package/lib/host.js +41 -1
- package/package.json +14 -3
- package/presets/clearai/agent.cordis.yml +7 -0
- package/presets/clearai/plugins/clearai-kernel.js +122 -8
- package/presets/clearai/plugins/prompts.js +18 -3
- package/presets/clearai/preset.yml +3 -3
- package/presets/clearai/skills/clearai-loop/SKILL.md +16 -13
package/lib/domain-language.js
CHANGED
|
@@ -431,20 +431,20 @@ export function graphProjection(state) {
|
|
|
431
431
|
}
|
|
432
432
|
const terms = [...lexicon.terms].sort((a, b) => (a.id < b.id ? -1 : 1))
|
|
433
433
|
const predicates = [...lexicon.predicates].sort((a, b) => (a.id < b.id ? -1 : 1))
|
|
434
|
-
for (const term of terms) nodes.push({ id: `term:${term.id}`, kind: 'concept', ref: term.id, label: term.label ?? term.id, status: term.status ?? 'admitted', parent: text(term.parent) === '' ? null : text(term.parent), uses: uses.get(term.id) ?? 0, depth: depthOf(term) })
|
|
434
|
+
for (const term of terms) nodes.push({ id: `term:${term.id}`, kind: 'concept', layer: 'ontology', ref: term.id, label: term.label ?? term.id, status: term.status ?? 'admitted', parent: text(term.parent) === '' ? null : text(term.parent), uses: uses.get(term.id) ?? 0, depth: depthOf(term) })
|
|
435
435
|
const formsUsed = VALUE_FORMS.filter((form) => predicates.some((item) => text(item.range?.form) === form))
|
|
436
|
-
for (const [index, form] of formsUsed.entries()) nodes.push({ id: `form:${form}`, kind: 'value_type', ref: form, label: form, status: 'admitted', uses: 0, depth: 0, formIndex: index })
|
|
436
|
+
for (const [index, form] of formsUsed.entries()) nodes.push({ id: `form:${form}`, kind: 'value_type', layer: 'ontology', ref: form, label: form, status: 'admitted', uses: 0, depth: 0, formIndex: index })
|
|
437
437
|
for (const term of terms) {
|
|
438
438
|
if (text(term.parent) === '') continue
|
|
439
439
|
if (!termById.has(text(term.parent))) continue
|
|
440
|
-
edges.push({ id: `is_a:${term.id}`, kind: 'is_a', predicate: null, label: 'is_a', from: `term:${term.id}`, to: `term:${term.parent}`, status: term.status ?? 'admitted' })
|
|
440
|
+
edges.push({ id: `is_a:${term.id}`, kind: 'is_a', layer: 'ontology', predicate: null, label: 'is_a', from: `term:${term.id}`, to: `term:${term.parent}`, status: term.status ?? 'admitted' })
|
|
441
441
|
}
|
|
442
442
|
for (const predicate of predicates) {
|
|
443
443
|
const range = isPlainObject(predicate.range) ? predicate.range : {}
|
|
444
444
|
const rangeTerm = text(range.term)
|
|
445
445
|
const form = text(range.form)
|
|
446
446
|
const to = rangeTerm !== '' ? `term:${rangeTerm}` : form !== '' ? `form:${form}` : null
|
|
447
|
-
if (to !== null) edges.push({ id: `predicate:${predicate.id}`, kind: 'predicate', predicate: predicate.id, label: predicate.label ?? predicate.id, from: text(predicate.domain) === '' ? null : `term:${text(predicate.domain)}`, to, status: predicate.status ?? 'admitted', functional: predicate.functional === true })
|
|
447
|
+
if (to !== null) edges.push({ id: `predicate:${predicate.id}`, kind: 'predicate', layer: 'ontology', predicate: predicate.id, label: predicate.label ?? predicate.id, from: text(predicate.domain) === '' ? null : `term:${text(predicate.domain)}`, to, status: predicate.status ?? 'admitted', functional: predicate.functional === true })
|
|
448
448
|
}
|
|
449
449
|
const instances = new Map()
|
|
450
450
|
for (const fact of facts) {
|
|
@@ -454,7 +454,7 @@ export function graphProjection(state) {
|
|
|
454
454
|
const subjectId = text(subject.id)
|
|
455
455
|
if (subjectId === '') continue
|
|
456
456
|
const key = `${text(subject.type)}|${subjectId}`
|
|
457
|
-
if (!instances.has(key)) instances.set(key, { id: key, kind: 'instance', ref: subjectId, label: subjectId, type: text(subject.type) === '' ? null : text(subject.type), facts: [] })
|
|
457
|
+
if (!instances.has(key)) instances.set(key, { id: key, kind: 'instance', layer: 'entity', ref: subjectId, label: subjectId, type: text(subject.type) === '' ? null : text(subject.type), facts: [] })
|
|
458
458
|
instances.get(key).facts.push(fact.id ?? null)
|
|
459
459
|
const predicateId = text(assertion?.predicate)
|
|
460
460
|
const object = isPlainObject(assertion?.object) ? assertion.object : {}
|
|
@@ -465,48 +465,66 @@ export function graphProjection(state) {
|
|
|
465
465
|
const objectType = text(object.type) === '' ? text(predicateById.get(predicateId)?.range?.term) : text(object.type)
|
|
466
466
|
const objectKeyId = `${objectType}|${objectLabel}`
|
|
467
467
|
if (objectLabel !== '') {
|
|
468
|
-
if (!instances.has(objectKeyId)) instances.set(objectKeyId, { id: objectKeyId, kind: 'instance', ref: objectLabel, label: objectLabel, type: objectType === '' ? null : objectType, facts: [] })
|
|
468
|
+
if (!instances.has(objectKeyId)) instances.set(objectKeyId, { id: objectKeyId, kind: 'instance', layer: 'entity', ref: objectLabel, label: objectLabel, type: objectType === '' ? null : objectType, facts: [] })
|
|
469
469
|
instances.get(objectKeyId).facts.push(fact.id ?? null)
|
|
470
470
|
to = objectKeyId
|
|
471
471
|
}
|
|
472
472
|
} else if (predicateId !== '') {
|
|
473
473
|
const literalId = `${predicateId}:${objectKey(assertion.object)}`
|
|
474
|
-
if (!instances.has(literalId)) instances.set(literalId, { id: literalId, kind: 'literal', ref: objectKey(assertion.object), label: formatObject(object), type: null, facts: [] })
|
|
474
|
+
if (!instances.has(literalId)) instances.set(literalId, { id: literalId, kind: 'literal', layer: 'entity', ref: objectKey(assertion.object), label: formatObject(object), type: null, facts: [] })
|
|
475
475
|
instances.get(literalId).facts.push(fact.id ?? null)
|
|
476
476
|
to = literalId
|
|
477
477
|
}
|
|
478
|
-
if (to !== null) edges.push({ id: `assertion:${fact.id ?? ''}:${predicateId}:${subjectKey(assertion)}`, kind: 'assertion', predicate: predicateId, label: text(lexicon.predicates.find((item) => item.id === predicateId)?.label) || predicateId, from: key, to, status, level: fact.level ?? null, fact: fact.id ?? null, scope: fact.scope ?? null })
|
|
478
|
+
if (to !== null) edges.push({ id: `assertion:${fact.id ?? ''}:${predicateId}:${subjectKey(assertion)}`, kind: 'assertion', layer: 'entity', predicate: predicateId, label: text(lexicon.predicates.find((item) => item.id === predicateId)?.label) || predicateId, from: key, to, status, level: fact.level ?? null, fact: fact.id ?? null, scope: fact.scope ?? null, claim: text(fact.hypothesis) === '' ? null : text(fact.hypothesis) })
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
for (const instance of [...instances.values()].sort((a, b) => (a.id < b.id ? -1 : 1))) nodes.push(instance)
|
|
482
|
-
|
|
482
|
+
/**
|
|
483
|
+
* **确定性布局:按层分段,层内折行。**
|
|
484
|
+
*
|
|
485
|
+
* 「层」= `is_a` 深度(概念)、值形态、实例/字面值各成一段,段与段依次向下排。
|
|
486
|
+
* 关键的一步是**折行**:早先每一层只铺一行,于是一堆没有父概念的根被排成一条
|
|
487
|
+
* 极宽极扁的带子(真数据:23 个节点铺出 3800×180),任何视口里都只能缩到看不清。
|
|
488
|
+
* 折行之后同一层在有限宽度内往下堆,整体接近屏幕比例,读得清。
|
|
489
|
+
*
|
|
490
|
+
* 它仍然是**纯函数、确定性**:同一份账本永远算出同一套坐标(层内按 id 排,不靠遍历顺序)。
|
|
491
|
+
*/
|
|
483
492
|
const COLUMN = 220
|
|
484
493
|
const ROW = 132
|
|
494
|
+
const PER_ROW = 6
|
|
495
|
+
let cursorY = 0
|
|
496
|
+
const band = (list) => {
|
|
497
|
+
const top = cursorY
|
|
498
|
+
cursorY += Math.max(1, Math.ceil(list.length / PER_ROW)) * ROW
|
|
499
|
+
return top
|
|
500
|
+
}
|
|
501
|
+
const place = (list, top) => {
|
|
502
|
+
list.forEach((node, index) => {
|
|
503
|
+
node.x = (index % PER_ROW) * COLUMN
|
|
504
|
+
node.y = top + Math.floor(index / PER_ROW) * ROW
|
|
505
|
+
})
|
|
506
|
+
}
|
|
485
507
|
const byDepth = new Map()
|
|
486
508
|
for (const node of nodes.filter((item) => item.kind === 'concept')) {
|
|
487
509
|
const list = byDepth.get(node.depth) ?? []
|
|
488
510
|
list.push(node)
|
|
489
511
|
byDepth.set(node.depth, list)
|
|
490
512
|
}
|
|
491
|
-
|
|
492
|
-
for (const
|
|
493
|
-
list.
|
|
494
|
-
|
|
495
|
-
node.y = depth * ROW
|
|
496
|
-
})
|
|
513
|
+
/** 深度小的在上(父在上、子在下),同深度内按 id——两条都为了确定性。 */
|
|
514
|
+
for (const depth of [...byDepth.keys()].sort((left, right) => left - right)) {
|
|
515
|
+
const list = byDepth.get(depth)
|
|
516
|
+
place(list, band(list))
|
|
497
517
|
}
|
|
498
|
-
nodes.filter((item) => item.kind === 'value_type')
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
const instanceBand = (maxDepth + 2) * ROW
|
|
503
|
-
const perRow = 6
|
|
504
|
-
nodes.filter((item) => item.kind === 'instance' || item.kind === 'literal').forEach((node, index) => {
|
|
505
|
-
node.x = (index % perRow) * COLUMN
|
|
506
|
-
node.y = instanceBand + Math.floor(index / perRow) * ROW
|
|
507
|
-
})
|
|
518
|
+
const forms = nodes.filter((item) => item.kind === 'value_type')
|
|
519
|
+
if (forms.length > 0) place(forms, band(forms))
|
|
520
|
+
const leaves = nodes.filter((item) => item.kind === 'instance' || item.kind === 'literal')
|
|
521
|
+
if (leaves.length > 0) place(leaves, band(leaves))
|
|
508
522
|
const width = Math.max(...nodes.map((node) => (typeof node.x === 'number' ? node.x : 0)), 0) + COLUMN
|
|
509
523
|
const height = Math.max(...nodes.map((node) => (typeof node.y === 'number' ? node.y : 0)), 0) + ROW
|
|
524
|
+
/**
|
|
525
|
+
* 返回的是**纯语义**:节点、边、包围盒。视口该画哪一块、先画谁、怎么缩放,
|
|
526
|
+
* 都是渲染层的事(现在是 React Flow)——投影不再替渲染做决定。
|
|
527
|
+
*/
|
|
510
528
|
return { nodes, edges, bounds: { width, height } }
|
|
511
529
|
}
|
|
512
530
|
|