dsh-kingdom 0.8.0 → 2.0.0
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/ASSETS_NOTICE.md +22 -0
- package/LICENSE +661 -29
- package/NOTICE +9 -0
- package/README.md +93 -94
- package/THIRD_PARTY_NOTICES.md +92 -0
- package/cordis.patch.yml +6 -6
- package/docs/V2.0-RELEASE-NOTES.md +30 -0
- package/docs/V2.0-USER-GUIDE.md +74 -0
- package/lib/adapter/dsh-backend.js +327 -24
- package/lib/adapter/dsh-backend.js.map +1 -1
- package/lib/adapter/dsh-cost.js +68 -0
- package/lib/adapter/dsh-cost.js.map +1 -0
- package/lib/adapter/dsh-session-events.js +86 -0
- package/lib/adapter/dsh-session-events.js.map +1 -0
- package/lib/adapter/dsh-usage.js +159 -0
- package/lib/adapter/dsh-usage.js.map +1 -0
- package/lib/capability/admin.js +72 -0
- package/lib/capability/admin.js.map +1 -0
- package/lib/capability/dsh-enforcement.js +143 -34
- package/lib/capability/dsh-enforcement.js.map +1 -1
- package/lib/capability/resolver.js +21 -8
- package/lib/capability/resolver.js.map +1 -1
- package/lib/capability/service.js +169 -26
- package/lib/capability/service.js.map +1 -1
- package/lib/capability/tool-disclosure.js +144 -0
- package/lib/capability/tool-disclosure.js.map +1 -0
- package/lib/core/binding.js +52 -34
- package/lib/core/binding.js.map +1 -1
- package/lib/core/budget.js +304 -0
- package/lib/core/budget.js.map +1 -0
- package/lib/core/collaboration.js +422 -0
- package/lib/core/collaboration.js.map +1 -0
- package/lib/core/cost.js +212 -0
- package/lib/core/cost.js.map +1 -0
- package/lib/core/db.js +197 -4
- package/lib/core/db.js.map +1 -1
- package/lib/core/execution.js +2 -2
- package/lib/core/execution.js.map +1 -1
- package/lib/core/governed-claim.js +46 -0
- package/lib/core/governed-claim.js.map +1 -0
- package/lib/core/governed.js +891 -98
- package/lib/core/governed.js.map +1 -1
- package/lib/core/kingdom.js +78 -70
- package/lib/core/kingdom.js.map +1 -1
- package/lib/core/owner-binding-intent.js +732 -0
- package/lib/core/owner-binding-intent.js.map +1 -0
- package/lib/core/owner-control.js +86 -0
- package/lib/core/owner-control.js.map +1 -0
- package/lib/core/owner-window.js +822 -0
- package/lib/core/owner-window.js.map +1 -0
- package/lib/core/task-service.js +296 -133
- package/lib/core/task-service.js.map +1 -1
- package/lib/core/territory.js +44 -14
- package/lib/core/territory.js.map +1 -1
- package/lib/core/usage.js +39 -0
- package/lib/core/usage.js.map +1 -0
- package/lib/core/workspace-admission.js +225 -0
- package/lib/core/workspace-admission.js.map +1 -0
- package/lib/dispatch/evidence.js +5 -2
- package/lib/dispatch/evidence.js.map +1 -1
- package/lib/dispatch/reconcile.js +3 -9
- package/lib/dispatch/reconcile.js.map +1 -1
- package/lib/dispatch/service.js +464 -64
- package/lib/dispatch/service.js.map +1 -1
- package/lib/gui/assets/characters/chancellor-idle.svg +67 -0
- package/lib/gui/assets/characters/chancellor-sleeping.svg +67 -0
- package/lib/gui/assets/characters/chancellor-thinking.svg +67 -0
- package/lib/gui/assets/characters/chancellor-working.svg +67 -0
- package/lib/gui/assets/characters/knight-redraw-r1-idle.svg +67 -0
- package/lib/gui/assets/characters/knight-redraw-r1-sleeping.svg +67 -0
- package/lib/gui/assets/characters/knight-redraw-r1-thinking.svg +67 -0
- package/lib/gui/assets/characters/knight-redraw-r1-working.svg +67 -0
- package/lib/gui/assets/characters/supervisor-idle.svg +67 -0
- package/lib/gui/assets/characters/supervisor-sleeping.svg +67 -0
- package/lib/gui/assets/characters/supervisor-thinking.svg +67 -0
- package/lib/gui/assets/characters/supervisor-working.svg +67 -0
- package/lib/gui/console-app.js +2330 -0
- package/lib/gui/console-app.js.map +1 -0
- package/lib/gui/contract.js +5 -5
- package/lib/gui/contract.js.map +1 -1
- package/lib/gui/control-contract.js +232 -0
- package/lib/gui/control-contract.js.map +1 -0
- package/lib/gui/local-control.js +423 -0
- package/lib/gui/local-control.js.map +1 -0
- package/lib/gui/owner-control.js +310 -0
- package/lib/gui/owner-control.js.map +1 -0
- package/lib/gui/owner-ui.js +191 -0
- package/lib/gui/owner-ui.js.map +1 -0
- package/lib/gui/server.js +445 -35
- package/lib/gui/server.js.map +1 -1
- package/lib/gui/snapshot.js +1346 -67
- package/lib/gui/snapshot.js.map +1 -1
- package/lib/gui/visual-assets.js +56 -0
- package/lib/gui/visual-assets.js.map +1 -0
- package/lib/gui/visual-system.js +272 -0
- package/lib/gui/visual-system.js.map +1 -0
- package/lib/gui/workbench-ui.js +358 -0
- package/lib/gui/workbench-ui.js.map +1 -0
- package/lib/gui/workbench.js +163 -0
- package/lib/gui/workbench.js.map +1 -0
- package/lib/index.js +1384 -361
- package/lib/index.js.map +1 -1
- package/lib/runner-context-broker.js +1134 -0
- package/lib/runner-context-broker.js.map +1 -0
- package/lib/runtime-cost-observer.js +145 -0
- package/lib/runtime-cost-observer.js.map +1 -0
- package/lib/types/adapter/contract.d.ts +61 -1
- package/lib/types/adapter/dsh-backend.d.ts +32 -13
- package/lib/types/adapter/dsh-cost.d.ts +13 -0
- package/lib/types/adapter/dsh-session-events.d.ts +16 -0
- package/lib/types/adapter/dsh-usage.d.ts +36 -0
- package/lib/types/capability/admin.d.ts +13 -0
- package/lib/types/capability/dsh-enforcement.d.ts +11 -7
- package/lib/types/capability/service.d.ts +10 -3
- package/lib/types/capability/tool-disclosure.d.ts +36 -0
- package/lib/types/core/binding.d.ts +19 -10
- package/lib/types/core/budget.d.ts +81 -0
- package/lib/types/core/collaboration.d.ts +110 -0
- package/lib/types/core/cost.d.ts +99 -0
- package/lib/types/core/db.d.ts +44 -4
- package/lib/types/core/execution.d.ts +1 -1
- package/lib/types/core/governed-claim.d.ts +7 -0
- package/lib/types/core/governed.d.ts +182 -1
- package/lib/types/core/kingdom.d.ts +3 -0
- package/lib/types/core/owner-binding-intent.d.ts +176 -0
- package/lib/types/core/owner-control.d.ts +53 -0
- package/lib/types/core/owner-window.d.ts +226 -0
- package/lib/types/core/task-service.d.ts +60 -13
- package/lib/types/core/territory.d.ts +9 -2
- package/lib/types/core/usage.d.ts +26 -0
- package/lib/types/core/workspace-admission.d.ts +43 -0
- package/lib/types/dispatch/evidence.d.ts +2 -5
- package/lib/types/dispatch/service.d.ts +62 -4
- package/lib/types/gui/console-app.d.ts +137 -0
- package/lib/types/gui/contract.d.ts +396 -16
- package/lib/types/gui/control-contract.d.ts +111 -0
- package/lib/types/gui/local-control.d.ts +120 -0
- package/lib/types/gui/owner-control.d.ts +45 -0
- package/lib/types/gui/owner-ui.d.ts +2 -0
- package/lib/types/gui/server.d.ts +17 -3
- package/lib/types/gui/snapshot.d.ts +33 -11
- package/lib/types/gui/visual-assets.d.ts +27 -0
- package/lib/types/gui/visual-system.d.ts +2 -0
- package/lib/types/gui/workbench-ui.d.ts +5 -0
- package/lib/types/gui/workbench.d.ts +33 -0
- package/lib/types/index.d.ts +157 -6
- package/lib/types/runner-context-broker.d.ts +119 -0
- package/lib/types/runtime-cost-observer.d.ts +22 -0
- package/lib/types/worker/collaboration.d.ts +35 -0
- package/lib/types/worker/dsh-subagent.d.ts +4 -4
- package/lib/types/worker/executor-factory.d.ts +2 -1
- package/lib/types/worker/executor.d.ts +8 -3
- package/lib/types/worker/governed-executor.d.ts +8 -1
- package/lib/worker/collaboration.js +172 -0
- package/lib/worker/collaboration.js.map +1 -0
- package/lib/worker/dsh-subagent.js +4 -4
- package/lib/worker/executor-factory.js.map +1 -1
- package/lib/worker/executor.js +7 -2
- package/lib/worker/executor.js.map +1 -1
- package/lib/worker/governed-executor.js +295 -84
- package/lib/worker/governed-executor.js.map +1 -1
- package/package.json +23 -8
package/lib/core/cost.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
const count = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
|
|
3
|
+
const ref = (value) => typeof value === 'string' && value.length > 0 && value.length <= 768;
|
|
4
|
+
export function validProviderCounts(usage) {
|
|
5
|
+
if (!usage || !count(usage.uncachedInputTokens) || !count(usage.outputTokens) || !count(usage.totalTokens))
|
|
6
|
+
return false;
|
|
7
|
+
for (const key of ['cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens'])
|
|
8
|
+
if (usage[key] !== undefined && !count(usage[key]))
|
|
9
|
+
return false;
|
|
10
|
+
const prompt = usage.uncachedInputTokens + (usage.cacheReadTokens ?? 0) + (usage.cacheWriteTokens ?? 0);
|
|
11
|
+
return count(prompt) && usage.totalTokens >= prompt + usage.outputTokens
|
|
12
|
+
&& (usage.reasoningTokens === undefined || usage.reasoningTokens <= usage.outputTokens)
|
|
13
|
+
&& (usage.cacheReadTokens === undefined || usage.cacheWriteTokens === undefined || usage.totalTokens === prompt + usage.outputTokens)
|
|
14
|
+
&& (usage.routes === undefined || Array.isArray(usage.routes) && usage.routes.length <= 128 && usage.routes.every(route => ref(route.provider) && ref(route.model)));
|
|
15
|
+
}
|
|
16
|
+
function roleRecords(store, kingdomId) {
|
|
17
|
+
const latest = new Map();
|
|
18
|
+
for (const event of store.listRuntimeCostEvents(kingdomId)) {
|
|
19
|
+
if (event.event_type !== 'RUNTIME_ROLE_USAGE_OBSERVED')
|
|
20
|
+
continue;
|
|
21
|
+
try {
|
|
22
|
+
const value = JSON.parse(event.payload_json);
|
|
23
|
+
if (value.type !== 'KingdomRoleUsage/v1' || value.sourceUnitRef !== event.target_id)
|
|
24
|
+
continue;
|
|
25
|
+
const previous = latest.get(value.sourceUnitRef);
|
|
26
|
+
if (previous && (previous.value.observationSequence > value.observationSequence || previous.value.status === 'COMPLETE' && value.status !== 'COMPLETE'))
|
|
27
|
+
continue;
|
|
28
|
+
latest.set(value.sourceUnitRef, { value, firstSeq: previous?.firstSeq ?? event.seq, seq: event.seq });
|
|
29
|
+
}
|
|
30
|
+
catch { /* An invalid historical observation is not free usage. */ }
|
|
31
|
+
}
|
|
32
|
+
return latest;
|
|
33
|
+
}
|
|
34
|
+
function coverageGaps(store, kingdomId, sinceSeq = 0, carriedSourceRefs = []) {
|
|
35
|
+
const units = new Set();
|
|
36
|
+
const carried = new Set(carriedSourceRefs);
|
|
37
|
+
for (const event of store.listRuntimeCostEvents(kingdomId)) {
|
|
38
|
+
if (event.event_type !== 'RUNTIME_ROLE_USAGE_OBSERVED')
|
|
39
|
+
continue;
|
|
40
|
+
try {
|
|
41
|
+
const value = JSON.parse(event.payload_json);
|
|
42
|
+
if (value.type === 'KingdomUsageCoverageGap/v1' && (event.seq > sinceSeq || carried.has(value.sourceUnitRef)))
|
|
43
|
+
units.add(value.sourceUnitRef);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
if (event.seq > sinceSeq || carried.has(event.target_id ?? event.event_id))
|
|
47
|
+
units.add(event.target_id ?? event.event_id);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return units.size;
|
|
51
|
+
}
|
|
52
|
+
export function recordUsageCoverageGap(store, kingdomId, sourceUnitRef, reasonCode) {
|
|
53
|
+
if (!ref(sourceUnitRef) || store.getDefaultKingdom()?.kingdom_id !== kingdomId)
|
|
54
|
+
return;
|
|
55
|
+
const previous = store.getLatestRuntimeRoleUsageEvent(kingdomId, sourceUnitRef);
|
|
56
|
+
if (previous)
|
|
57
|
+
return;
|
|
58
|
+
const value = { type: 'KingdomUsageCoverageGap/v1', sourceUnitRef, reasonCode };
|
|
59
|
+
store.appendEvent({ event_id: randomUUID(), kingdom_id: kingdomId, event_type: 'RUNTIME_ROLE_USAGE_OBSERVED', actor_role: 'SYSTEM',
|
|
60
|
+
actor_id: 'kingdom-cost-observer', target_type: 'runtime-usage', target_id: sourceUnitRef, payload_json: JSON.stringify(value), created_at: new Date().toISOString() });
|
|
61
|
+
}
|
|
62
|
+
/** Arbitrary plugin names are not trusted metadata. Only fixed public categories reach the ledger. */
|
|
63
|
+
export function safePromptPartName(value, index, type) {
|
|
64
|
+
const known = { 'harness:identity': 'harness identity', 'agent:identity': 'agent identity',
|
|
65
|
+
'tools': 'tool guidance', 'skills': 'skill catalog', 'plugins': 'plugin guidance', 'AGENTS.md': 'workspace guidance',
|
|
66
|
+
'runtime': 'runtime context', 'runtime:snapshot': 'runtime snapshot' };
|
|
67
|
+
return known[value] ?? `${type} ${index + 1}`;
|
|
68
|
+
}
|
|
69
|
+
export function recordRoleUsage(store, kingdomId, input) {
|
|
70
|
+
const value = structuredClone(input);
|
|
71
|
+
const binding = store.getBindingById(value.bindingId);
|
|
72
|
+
if (!binding || binding.kingdom_id !== kingdomId || !['CHANCELLOR', 'SUPERVISOR'].includes(binding.role_type)
|
|
73
|
+
|| binding.role_type !== value.roleType || value.type !== 'KingdomRoleUsage/v1' || value.source !== 'provider-reported'
|
|
74
|
+
|| ![value.sourceUnitRef, value.runtimeInstanceRef, value.sessionRef].every(ref)
|
|
75
|
+
|| !count(value.startedLedgerSeq) || !count(value.observationSequence) || !Number.isFinite(Date.parse(value.startedAt))
|
|
76
|
+
|| !count(value.observedRequests) || !count(value.reportedRequests) || value.reportedRequests > value.observedRequests
|
|
77
|
+
|| !['IN_PROGRESS', 'COMPLETE', 'UNAVAILABLE'].includes(value.status)
|
|
78
|
+
|| !['TASK', 'SHARED', 'UNATTRIBUTED'].includes(value.attribution)
|
|
79
|
+
|| !Array.isArray(value.taskIds) || value.taskIds.length > 32 || new Set(value.taskIds).size !== value.taskIds.length
|
|
80
|
+
|| value.taskIds.some(id => { const task = store.getTask(id); return !task || store.getTerritoryById(task.territory_id)?.kingdom_id !== kingdomId; })
|
|
81
|
+
|| (value.attribution === 'TASK' ? value.taskIds.length !== 1 : value.attribution === 'UNATTRIBUTED' ? value.taskIds.length !== 0 : value.taskIds.length < 1)
|
|
82
|
+
|| (value.status === 'COMPLETE' ? !value.usage || !validProviderCounts(value.usage) || value.observedRequests !== value.reportedRequests : value.usage !== null))
|
|
83
|
+
return false;
|
|
84
|
+
return store.withImmediateTransaction(() => {
|
|
85
|
+
const event = store.getLatestRuntimeRoleUsageEvent(kingdomId, value.sourceUnitRef);
|
|
86
|
+
let previous;
|
|
87
|
+
try {
|
|
88
|
+
previous = event ? JSON.parse(event.payload_json) : undefined;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (previous && previous.type !== 'KingdomRoleUsage/v1')
|
|
94
|
+
return false;
|
|
95
|
+
if (previous && (previous.bindingId !== value.bindingId || previous.sessionRef !== value.sessionRef
|
|
96
|
+
|| previous.runtimeInstanceRef !== value.runtimeInstanceRef || previous.startedLedgerSeq !== value.startedLedgerSeq
|
|
97
|
+
|| previous.observationSequence > value.observationSequence || previous.status === 'COMPLETE' && value.status !== 'COMPLETE'))
|
|
98
|
+
return false;
|
|
99
|
+
if (previous && JSON.stringify(previous) === JSON.stringify(value))
|
|
100
|
+
return true;
|
|
101
|
+
// A complete turn is an immutable source unit; rescanning after a budget
|
|
102
|
+
// boundary must not move old usage into the new accounting period.
|
|
103
|
+
if (previous?.status === 'COMPLETE')
|
|
104
|
+
return false;
|
|
105
|
+
store.appendEvent({ event_id: randomUUID(), kingdom_id: kingdomId, event_type: 'RUNTIME_ROLE_USAGE_OBSERVED',
|
|
106
|
+
actor_role: 'SYSTEM', actor_id: 'kingdom-cost-observer', target_type: 'runtime-usage', target_id: value.sourceUnitRef,
|
|
107
|
+
payload_json: JSON.stringify(value), created_at: new Date().toISOString() });
|
|
108
|
+
return true;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/** Lost observer continuity is unknown usage, never proof a Runtime stopped. */
|
|
112
|
+
export function closeInterruptedRoleObservations(store, kingdomId, runtimeInstanceRef) {
|
|
113
|
+
let closed = 0;
|
|
114
|
+
for (const { value } of roleRecords(store, kingdomId).values()) {
|
|
115
|
+
if (value.runtimeInstanceRef !== runtimeInstanceRef || value.status !== 'IN_PROGRESS')
|
|
116
|
+
continue;
|
|
117
|
+
if (recordRoleUsage(store, kingdomId, { ...value, status: 'UNAVAILABLE', reasonCode: 'OBSERVER_RESTARTED', usage: null }))
|
|
118
|
+
closed++;
|
|
119
|
+
}
|
|
120
|
+
return closed;
|
|
121
|
+
}
|
|
122
|
+
export function readAdditionalRoleCost(store, kingdomId, taskId) {
|
|
123
|
+
const all = [...roleRecords(store, kingdomId).values()].map(record => record.value);
|
|
124
|
+
const values = taskId ? all.filter(value => value.attribution === 'TASK' && value.taskIds[0] === taskId) : all;
|
|
125
|
+
const complete = values.filter(value => value.status === 'COMPLETE' && value.usage && validProviderCounts(value.usage));
|
|
126
|
+
const sum = (items) => {
|
|
127
|
+
if (!items.length)
|
|
128
|
+
return null;
|
|
129
|
+
const total = items.reduce((total, item) => total + item.usage.totalTokens, 0);
|
|
130
|
+
return count(total) ? total : null;
|
|
131
|
+
};
|
|
132
|
+
const shared = all.filter(value => value.attribution === 'SHARED' && value.status === 'COMPLETE' && value.usage);
|
|
133
|
+
const unassigned = all.filter(value => value.attribution === 'UNATTRIBUTED' && value.status === 'COMPLETE' && value.usage);
|
|
134
|
+
return { scope: 'OBSERVED_GOVERNANCE_TURNS', units: values.length, completeUnits: complete.length,
|
|
135
|
+
pendingUnits: values.filter(value => value.status === 'IN_PROGRESS').length,
|
|
136
|
+
unknownUnits: values.filter(value => value.status === 'UNAVAILABLE').length + coverageGaps(store, kingdomId),
|
|
137
|
+
attributionGapCount: all.filter(value => value.attribution !== 'TASK').length,
|
|
138
|
+
observedRequests: values.reduce((sum, value) => sum + value.observedRequests, 0),
|
|
139
|
+
reportedRequests: values.reduce((sum, value) => sum + value.reportedRequests, 0), verifiedTokens: sum(complete),
|
|
140
|
+
byRole: ['CHANCELLOR', 'SUPERVISOR'].map(roleType => ({ roleType,
|
|
141
|
+
units: values.filter(value => value.roleType === roleType).length,
|
|
142
|
+
completeUnits: complete.filter(value => value.roleType === roleType).length,
|
|
143
|
+
verifiedTokens: sum(complete.filter(value => value.roleType === roleType)) })),
|
|
144
|
+
sharedTokens: sum(shared), unattributedTokens: sum(unassigned), amount: null, amountStatus: 'PRICE_NOT_CONFIGURED',
|
|
145
|
+
coverageNote: '仅包含本次观测接入后可核对的宰相/主管轮次;共享及未归属不摊入单任务,未接入的外部参与者和旧历史仍是覆盖缺口。' };
|
|
146
|
+
}
|
|
147
|
+
/** Add only non-Worker observations; Worker dispatch reports are already counted by budget.ts. */
|
|
148
|
+
export function readIncompleteRoleUsageSourceRefs(store, kingdomId) {
|
|
149
|
+
const refs = new Set([...roleRecords(store, kingdomId).values()].filter(record => record.value.status !== 'COMPLETE')
|
|
150
|
+
.map(record => record.value.sourceUnitRef));
|
|
151
|
+
for (const event of store.listRuntimeCostEvents(kingdomId)) {
|
|
152
|
+
if (event.event_type !== 'RUNTIME_ROLE_USAGE_OBSERVED')
|
|
153
|
+
continue;
|
|
154
|
+
try {
|
|
155
|
+
const value = JSON.parse(event.payload_json);
|
|
156
|
+
if (value.type === 'KingdomUsageCoverageGap/v1' && ref(value.sourceUnitRef))
|
|
157
|
+
refs.add(value.sourceUnitRef);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
refs.add(event.target_id ?? event.event_id);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return [...refs];
|
|
164
|
+
}
|
|
165
|
+
/** Frozen carry-in sources preserve work already pending when the first policy was created. */
|
|
166
|
+
export function readAdditionalBudgetUsage(store, kingdomId, sinceEventSeq, carriedSourceRefs = []) {
|
|
167
|
+
const carried = new Set(carriedSourceRefs);
|
|
168
|
+
const records = [...roleRecords(store, kingdomId).values()].filter(record => record.seq > sinceEventSeq || carried.has(record.value.sourceUnitRef));
|
|
169
|
+
let verifiedTokens = 0, unknownUnits = 0, pendingUnits = 0, attributionGapCount = 0;
|
|
170
|
+
for (const { value } of records) {
|
|
171
|
+
if (value.status === 'IN_PROGRESS')
|
|
172
|
+
pendingUnits++;
|
|
173
|
+
else if (value.status !== 'COMPLETE' || !value.usage || !validProviderCounts(value.usage))
|
|
174
|
+
unknownUnits++;
|
|
175
|
+
else if (count(verifiedTokens + value.usage.totalTokens))
|
|
176
|
+
verifiedTokens += value.usage.totalTokens;
|
|
177
|
+
else
|
|
178
|
+
unknownUnits++;
|
|
179
|
+
if (value.attribution !== 'TASK')
|
|
180
|
+
attributionGapCount++;
|
|
181
|
+
}
|
|
182
|
+
return { verifiedTokens, unknownUnits: unknownUnits + coverageGaps(store, kingdomId, sinceEventSeq, carriedSourceRefs), pendingUnits, attributionGapCount };
|
|
183
|
+
}
|
|
184
|
+
export function recordPromptCost(store, kingdomId, input) {
|
|
185
|
+
const binding = store.getBindingById(input.bindingId);
|
|
186
|
+
const parts = [...input.sections, ...input.contexts];
|
|
187
|
+
if (!binding || binding.kingdom_id !== kingdomId || !ref(input.sourceUnitRef) || parts.length > 256
|
|
188
|
+
|| parts.some(part => !ref(part.name) || !count(part.bytes))
|
|
189
|
+
|| ![input.toolsBefore, input.toolsAfter, input.toolsBytesBefore, input.toolsBytesAfter].every(count))
|
|
190
|
+
return;
|
|
191
|
+
const value = { ...input,
|
|
192
|
+
sections: input.sections.map((part, index) => ({ name: safePromptPartName(part.name, index, 'section'), bytes: part.bytes })),
|
|
193
|
+
contexts: input.contexts.map((part, index) => ({ name: safePromptPartName(part.name, index, 'context'), bytes: part.bytes })) };
|
|
194
|
+
store.appendEvent({ event_id: randomUUID(), kingdom_id: kingdomId, event_type: 'RUNTIME_PROMPT_COST_OBSERVED', actor_role: 'SYSTEM',
|
|
195
|
+
actor_id: 'kingdom-cost-observer', target_type: 'runtime-prompt', target_id: input.sourceUnitRef,
|
|
196
|
+
payload_json: JSON.stringify(value), created_at: new Date().toISOString() });
|
|
197
|
+
}
|
|
198
|
+
export function readLatestPromptCosts(store, kingdomId) {
|
|
199
|
+
const latest = new Map();
|
|
200
|
+
for (const event of store.listRuntimeCostEvents(kingdomId)) {
|
|
201
|
+
if (event.event_type !== 'RUNTIME_PROMPT_COST_OBSERVED')
|
|
202
|
+
continue;
|
|
203
|
+
try {
|
|
204
|
+
const value = JSON.parse(event.payload_json);
|
|
205
|
+
if (value.type === 'KingdomPromptCost/v1')
|
|
206
|
+
latest.set(value.bindingId, value);
|
|
207
|
+
}
|
|
208
|
+
catch { /* Omit corrupt observations rather than inventing measurements. */ }
|
|
209
|
+
}
|
|
210
|
+
return [...latest.values()];
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=cost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/core/cost.ts"],"names":[],"mappings":"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"}
|
package/lib/core/db.js
CHANGED
|
@@ -372,7 +372,7 @@ export class KingdomStore {
|
|
|
372
372
|
}
|
|
373
373
|
// ── v0.8(M3-S2 Schema v4 Design v6,Owner 三次 Review APPROVED)─────────
|
|
374
374
|
//
|
|
375
|
-
// 忠实实现 v6(
|
|
375
|
+
// 忠实实现 v6(M3-S2 Schema v4 Design v6 + 当时的 49/49 验证脚本):
|
|
376
376
|
// - 四套独立 Core Ledger:session_territory_affinities / execution_leases /
|
|
377
377
|
// capability_decisions / dispatch_records;
|
|
378
378
|
// - executions 重建(v6 §14):建 executions_v4 暂存表(v2 证据列 + 新增
|
|
@@ -945,6 +945,23 @@ BEGIN SELECT RAISE(ABORT, 'DISPATCH_NO_DELETE'); END;
|
|
|
945
945
|
updateTerritorySupervisor(territoryId, supervisorBindingId) {
|
|
946
946
|
this.db.prepare('UPDATE territories SET supervisor_binding_id = ? WHERE territory_id = ?').run(supervisorBindingId, territoryId);
|
|
947
947
|
}
|
|
948
|
+
updateTerritoryMetadata(territoryId, name, summary) {
|
|
949
|
+
this.db.prepare('UPDATE territories SET name = ?, summary = ? WHERE territory_id = ?').run(name, summary, territoryId);
|
|
950
|
+
}
|
|
951
|
+
getEventById(eventId) {
|
|
952
|
+
return this.db.prepare('SELECT * FROM events WHERE event_id = ?').get(eventId) ?? null;
|
|
953
|
+
}
|
|
954
|
+
/** Global append cursor; callers predicting a receipt sequence must hold the write transaction. */
|
|
955
|
+
eventSequence() {
|
|
956
|
+
const row = this.db.prepare('SELECT COALESCE(MAX(seq), 0) AS n FROM events').get();
|
|
957
|
+
return row.n;
|
|
958
|
+
}
|
|
959
|
+
/** Owner topology guards include RECOVERING and unknown future nonterminal states. */
|
|
960
|
+
listUnsettledOwnerExecutions(kingdomId) {
|
|
961
|
+
return this.db.prepare(`SELECT e.* FROM executions e JOIN tasks t ON t.task_id = e.task_id
|
|
962
|
+
JOIN territories te ON te.territory_id = t.territory_id WHERE te.kingdom_id = ?
|
|
963
|
+
AND e.state NOT IN ('COMPLETED', 'FAILED', 'ABORTED') ORDER BY e.started_at`).all(kingdomId);
|
|
964
|
+
}
|
|
948
965
|
// ── task_assignments(v0.7.0 M2-B Assignment Ledger)──────────
|
|
949
966
|
insertTaskAssignment(row) {
|
|
950
967
|
this.db
|
|
@@ -1083,6 +1100,57 @@ BEGIN SELECT RAISE(ABORT, 'DISPATCH_NO_DELETE'); END;
|
|
|
1083
1100
|
.prepare('SELECT * FROM events WHERE kingdom_id = ? AND seq > ? ORDER BY seq ASC LIMIT ?')
|
|
1084
1101
|
.all(kingdomId, afterSeq, limit);
|
|
1085
1102
|
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Exact Dispatch lookup for one Task attempt.
|
|
1105
|
+
*
|
|
1106
|
+
* Integrity decisions must not scan a bounded event projection: the
|
|
1107
|
+
* dispatch/task/attempt relation is authoritative in dispatch_records.
|
|
1108
|
+
*/
|
|
1109
|
+
listDispatchesForTaskAttempt(taskId, attemptNo) {
|
|
1110
|
+
return this.db
|
|
1111
|
+
.prepare(`SELECT * FROM dispatch_records
|
|
1112
|
+
WHERE task_id = ? AND attempt_no = ?
|
|
1113
|
+
ORDER BY created_at ASC`)
|
|
1114
|
+
.all(taskId, attemptNo);
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Exact, replay-safe lookup for an open terminal integrity incident.
|
|
1118
|
+
* The SQL predicate narrows by the exact Dispatch target; the bounded JSON
|
|
1119
|
+
* payload is then checked against the exact Task/attempt correlation.
|
|
1120
|
+
*/
|
|
1121
|
+
getOpenDispatchTerminalIntegrityIncident(kingdomId, dispatchId, taskId, attemptNo) {
|
|
1122
|
+
// The Dispatch row is authoritative for the Task/attempt relation. Do
|
|
1123
|
+
// not accept an event merely because its target_id happens to match a
|
|
1124
|
+
// caller-supplied string.
|
|
1125
|
+
const dispatch = this.getDispatch(dispatchId);
|
|
1126
|
+
if (!dispatch
|
|
1127
|
+
|| dispatch.kingdom_id !== kingdomId
|
|
1128
|
+
|| dispatch.task_id !== taskId
|
|
1129
|
+
|| dispatch.attempt_no !== attemptNo)
|
|
1130
|
+
return null;
|
|
1131
|
+
const rows = this.db
|
|
1132
|
+
.prepare(`SELECT * FROM events
|
|
1133
|
+
WHERE kingdom_id = ?
|
|
1134
|
+
AND event_type = 'DISPATCH_TERMINAL_INTEGRITY_INCIDENT'
|
|
1135
|
+
AND target_type = 'dispatch'
|
|
1136
|
+
AND target_id = ?
|
|
1137
|
+
ORDER BY seq ASC`)
|
|
1138
|
+
.all(kingdomId, dispatchId);
|
|
1139
|
+
for (const row of rows) {
|
|
1140
|
+
try {
|
|
1141
|
+
const payload = JSON.parse(row.payload_json);
|
|
1142
|
+
if (payload.incident_code === 'DISPATCH_TERMINAL_INTEGRITY_INCIDENT'
|
|
1143
|
+
&& payload.state === 'OPEN'
|
|
1144
|
+
&& payload.attempt_no === attemptNo) {
|
|
1145
|
+
return row;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
catch {
|
|
1149
|
+
// A malformed incident payload is not trusted as a matching incident.
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return null;
|
|
1153
|
+
}
|
|
1086
1154
|
/**
|
|
1087
1155
|
* 王国当前 revision = 最大事件序号。
|
|
1088
1156
|
*
|
|
@@ -1095,6 +1163,73 @@ BEGIN SELECT RAISE(ABORT, 'DISPATCH_NO_DELETE'); END;
|
|
|
1095
1163
|
.get(kingdomId);
|
|
1096
1164
|
return row?.n ?? 0;
|
|
1097
1165
|
}
|
|
1166
|
+
/** Observations and future admission/window policy cannot change an in-flight Runner relation. */
|
|
1167
|
+
runnerContextRevision(kingdomId, scope) {
|
|
1168
|
+
const rows = this.db.prepare(`SELECT * FROM events
|
|
1169
|
+
WHERE kingdom_id = ? AND event_type NOT IN (
|
|
1170
|
+
'RUNTIME_ROLE_USAGE_OBSERVED', 'RUNTIME_PROMPT_COST_OBSERVED', 'DISPATCH_USAGE_OBSERVED',
|
|
1171
|
+
'BUDGET_POLICY_UPDATED', 'BUDGET_ADMISSION_RESERVED', 'BUDGET_ADMISSION_BOUND', 'BUDGET_ADMISSION_CANCELLED',
|
|
1172
|
+
'OWNER_DECISION_CREATED', 'OWNER_DECISION_REVOKED', 'OWNER_DECISION_CONSUMED'
|
|
1173
|
+
) AND NOT (event_type = 'OWNER_OPERATION_APPLIED' AND COALESCE(
|
|
1174
|
+
CASE WHEN json_valid(payload_json) THEN json_extract(payload_json, '$.action') = 'budget.policy' ELSE 0 END, 0
|
|
1175
|
+
)) ORDER BY seq DESC`).all(kingdomId);
|
|
1176
|
+
if (!scope)
|
|
1177
|
+
return rows[0]?.seq ?? 0;
|
|
1178
|
+
// Only a known event with a provably independent live Core relation can be
|
|
1179
|
+
// ignored. Missing/corrupt targets and future event kinds remain invalidating.
|
|
1180
|
+
const independentTask = (taskId, worker, session) => {
|
|
1181
|
+
if (!taskId || taskId === scope.taskId || worker === scope.workerBindingId || session === scope.sessionRef)
|
|
1182
|
+
return false;
|
|
1183
|
+
const task = this.getTask(taskId), territory = task ? this.getTerritoryById(task.territory_id) : null;
|
|
1184
|
+
if (!task || territory?.kingdom_id !== kingdomId || task.assigned_binding_id === scope.workerBindingId)
|
|
1185
|
+
return false;
|
|
1186
|
+
return !this.listExecutions(taskId).some(row => row.worker_binding_id === scope.workerBindingId || row.session_id === scope.sessionRef)
|
|
1187
|
+
&& !this.listTaskAssignments(taskId).some(row => row.worker_binding_id === scope.workerBindingId);
|
|
1188
|
+
};
|
|
1189
|
+
for (const event of rows) {
|
|
1190
|
+
let independent = false;
|
|
1191
|
+
const id = event.target_id;
|
|
1192
|
+
if (id) {
|
|
1193
|
+
if (event.target_type === 'task' && ['TASK_PLANNED', 'TASK_ASSIGNED', 'TASK_ACCEPTED', 'TASK_REWORK_REQUESTED', 'TASK_FAILED',
|
|
1194
|
+
'TASK_HANDED_OFF', 'WORKER_RESULT_SUBMITTED', 'WORKER_EXECUTION_STARTED', 'WORKER_EXECUTION_FAILED', 'COLLABORATION_CHILD_CREATED'].includes(event.event_type)) {
|
|
1195
|
+
independent = independentTask(id);
|
|
1196
|
+
}
|
|
1197
|
+
else if (event.target_type === 'execution' && ['EXECUTION_GOVERNED_CREATED', 'EXECUTION_RECOVERING', 'SESSION_STARTED',
|
|
1198
|
+
'SESSION_STOPPED', 'SESSION_FAILED', 'SESSION_PAUSED', 'SESSION_RESUMED'].includes(event.event_type)) {
|
|
1199
|
+
const row = this.getExecution(id);
|
|
1200
|
+
independent = !!row && independentTask(row.task_id, row.worker_binding_id, row.session_id);
|
|
1201
|
+
}
|
|
1202
|
+
else if (event.target_type === 'lease' && ['LEASE_ACQUIRED', 'LEASE_STATE_CHANGED', 'LEASE_RELEASED'].includes(event.event_type)) {
|
|
1203
|
+
const row = this.getLease(id);
|
|
1204
|
+
independent = row?.kingdom_id === kingdomId && independentTask(row.task_id, row.worker_binding_id, row.session_ref);
|
|
1205
|
+
}
|
|
1206
|
+
else if (event.target_type === 'dispatch' && ['DISPATCH_INTENDED', 'DISPATCH_STATE_CHANGED'].includes(event.event_type)) {
|
|
1207
|
+
const row = this.getDispatch(id), lease = row ? this.getLease(row.lease_id) : null;
|
|
1208
|
+
independent = row?.kingdom_id === kingdomId && !!lease && lease.task_id === row.task_id
|
|
1209
|
+
&& independentTask(row.task_id, lease.worker_binding_id, row.session_ref);
|
|
1210
|
+
}
|
|
1211
|
+
else if (event.target_type === 'decision' && event.event_type === 'CAPABILITY_DECISION_RECORDED') {
|
|
1212
|
+
const row = this.getCapabilityDecision(id);
|
|
1213
|
+
independent = row?.kingdom_id === kingdomId && independentTask(row.task_id, row.worker_binding_id);
|
|
1214
|
+
}
|
|
1215
|
+
else if (event.target_type === 'affinity' && ['AFFINITY_ESTABLISHED', 'AFFINITY_RETIRED'].includes(event.event_type)) {
|
|
1216
|
+
const row = this.getAffinity(id);
|
|
1217
|
+
independent = row?.kingdom_id === kingdomId && row.worker_binding_id !== scope.workerBindingId && row.session_ref !== scope.sessionRef;
|
|
1218
|
+
}
|
|
1219
|
+
else if (event.target_type === 'workspace-admission' && ['WORKSPACE_ADMISSION_RESERVED', 'WORKSPACE_ADMISSION_BOUND', 'WORKSPACE_ADMISSION_CANCELLED'].includes(event.event_type)) {
|
|
1220
|
+
try {
|
|
1221
|
+
const row = JSON.parse(event.payload_json);
|
|
1222
|
+
independent = row.type === 'KingdomWorkspaceAdmission/v1' && row.admissionId === id
|
|
1223
|
+
&& row.kingdomId === kingdomId && independentTask(row.taskId, row.workerBindingId);
|
|
1224
|
+
}
|
|
1225
|
+
catch { /* retain invalidation */ }
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
if (!independent)
|
|
1229
|
+
return event.seq;
|
|
1230
|
+
}
|
|
1231
|
+
return 0;
|
|
1232
|
+
}
|
|
1098
1233
|
/**
|
|
1099
1234
|
* v0.7.0(M2):外层事务包装——HANDOFF 等**原子治理操作**(多步写 + 事件)整体提交/回滚。
|
|
1100
1235
|
* appendEvent 的内层 BEGIN 在事务中会抛错,由 appendEvent 的嵌套容忍逻辑接管(见下)。
|
|
@@ -1178,12 +1313,21 @@ BEGIN SELECT RAISE(ABORT, 'DISPATCH_NO_DELETE'); END;
|
|
|
1178
1313
|
.all(...params);
|
|
1179
1314
|
}
|
|
1180
1315
|
insertTask(row) {
|
|
1316
|
+
const hasRequirementColumn = this.db
|
|
1317
|
+
.prepare('PRAGMA table_info(tasks)')
|
|
1318
|
+
.all()
|
|
1319
|
+
.some(column => column.name === 'capability_requirement_json');
|
|
1320
|
+
if (!hasRequirementColumn && row.capability_requirement_json != null) {
|
|
1321
|
+
throw new Error('TASK_CAPABILITY_REQUIREMENT_UNAVAILABLE: Schema v4 未迁移,拒绝丢弃 Task requirement');
|
|
1322
|
+
}
|
|
1323
|
+
const columns = hasRequirementColumn ? ', capability_requirement_json' : '';
|
|
1324
|
+
const values = hasRequirementColumn ? ', ?' : '';
|
|
1181
1325
|
this.db
|
|
1182
1326
|
.prepare(`INSERT INTO tasks
|
|
1183
1327
|
(task_id, territory_id, parent_task_id, title, description, assigned_binding_id,
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
.run(row.task_id, row.territory_id, row.parent_task_id, row.title, row.description, row.assigned_binding_id, row.status, row.acceptance_criteria, row.result_summary, row.created_at, row.updated_at);
|
|
1328
|
+
status, acceptance_criteria, result_summary, created_at, updated_at${columns})
|
|
1329
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?${values})`)
|
|
1330
|
+
.run(row.task_id, row.territory_id, row.parent_task_id, row.title, row.description, row.assigned_binding_id, row.status, row.acceptance_criteria, row.result_summary, row.created_at, row.updated_at, ...(hasRequirementColumn ? [row.capability_requirement_json ?? null] : []));
|
|
1187
1331
|
return row;
|
|
1188
1332
|
}
|
|
1189
1333
|
/**
|
|
@@ -1224,6 +1368,46 @@ BEGIN SELECT RAISE(ABORT, 'DISPATCH_NO_DELETE'); END;
|
|
|
1224
1368
|
.all(taskId);
|
|
1225
1369
|
return rows[0] ?? null;
|
|
1226
1370
|
}
|
|
1371
|
+
/** Exact task/attempt lookup; unrelated kingdom activity cannot hide the reviewed attempt. */
|
|
1372
|
+
latestTaskReworkEvent(kingdomId, taskId, reviewedAttemptNo) {
|
|
1373
|
+
const rows = this.db.prepare("SELECT * FROM events WHERE kingdom_id = ? AND event_type = 'TASK_REWORK_REQUESTED' AND target_type = 'task' AND target_id = ? ORDER BY seq DESC")
|
|
1374
|
+
.all(kingdomId, taskId);
|
|
1375
|
+
for (const row of rows) {
|
|
1376
|
+
try {
|
|
1377
|
+
if (JSON.parse(row.payload_json).reviewed_attempt_no === reviewedAttemptNo)
|
|
1378
|
+
return row;
|
|
1379
|
+
}
|
|
1380
|
+
catch { /* Malformed historical evidence cannot establish a review reference. */ }
|
|
1381
|
+
}
|
|
1382
|
+
return null;
|
|
1383
|
+
}
|
|
1384
|
+
listDispatchUsageEvents(dispatchId) {
|
|
1385
|
+
return this.db.prepare("SELECT * FROM events WHERE event_type = 'DISPATCH_USAGE_OBSERVED' AND target_type = 'dispatch' AND target_id = ? ORDER BY seq")
|
|
1386
|
+
.all(dispatchId);
|
|
1387
|
+
}
|
|
1388
|
+
/** Complete exact budget ledger; display event windows must never be used as accounting history. */
|
|
1389
|
+
listBudgetEvents(kingdomId) {
|
|
1390
|
+
return this.db.prepare(`SELECT * FROM events WHERE kingdom_id = ? AND event_type IN
|
|
1391
|
+
('BUDGET_POLICY_UPDATED', 'BUDGET_ADMISSION_RESERVED', 'BUDGET_ADMISSION_BOUND', 'BUDGET_ADMISSION_CANCELLED', 'DISPATCH_INTENDED')
|
|
1392
|
+
ORDER BY seq ASC`).all(kingdomId);
|
|
1393
|
+
}
|
|
1394
|
+
listWorkspaceAdmissionEvents(kingdomId) {
|
|
1395
|
+
return this.db.prepare(`SELECT * FROM events WHERE kingdom_id = ? AND event_type IN
|
|
1396
|
+
('WORKSPACE_ADMISSION_RESERVED', 'WORKSPACE_ADMISSION_BOUND', 'WORKSPACE_ADMISSION_CANCELLED')
|
|
1397
|
+
ORDER BY seq ASC`).all(kingdomId);
|
|
1398
|
+
}
|
|
1399
|
+
listRuntimeCostEvents(kingdomId) {
|
|
1400
|
+
return this.db.prepare(`SELECT * FROM events WHERE kingdom_id = ? AND event_type IN
|
|
1401
|
+
('RUNTIME_ROLE_USAGE_OBSERVED', 'RUNTIME_PROMPT_COST_OBSERVED') ORDER BY seq ASC`).all(kingdomId);
|
|
1402
|
+
}
|
|
1403
|
+
listActorEventsSince(kingdomId, actorId, afterSeq) {
|
|
1404
|
+
return this.db.prepare('SELECT * FROM events WHERE kingdom_id = ? AND actor_id = ? AND seq > ? ORDER BY seq ASC')
|
|
1405
|
+
.all(kingdomId, actorId, afterSeq);
|
|
1406
|
+
}
|
|
1407
|
+
getLatestRuntimeRoleUsageEvent(kingdomId, sourceUnitRef) {
|
|
1408
|
+
return this.db.prepare("SELECT * FROM events WHERE kingdom_id = ? AND event_type = 'RUNTIME_ROLE_USAGE_OBSERVED' AND target_id = ? ORDER BY seq DESC LIMIT 1")
|
|
1409
|
+
.get(kingdomId, sourceUnitRef) ?? null;
|
|
1410
|
+
}
|
|
1227
1411
|
/** 已落库的最大 attempt_no;无结果时为 0。下一次尝试 = 本值 + 1。 */
|
|
1228
1412
|
maxAttemptNo(taskId) {
|
|
1229
1413
|
const row = this.db
|
|
@@ -1546,12 +1730,21 @@ BEGIN SELECT RAISE(ABORT, 'DISPATCH_NO_DELETE'); END;
|
|
|
1546
1730
|
}
|
|
1547
1731
|
// tasks.capability_requirement_json / kingdoms.capability_ceiling_json(v6 增量)────
|
|
1548
1732
|
getTaskCapabilityRequirement(taskId) {
|
|
1733
|
+
if (!this.getTaskCapabilityRequirementColumn())
|
|
1734
|
+
return null;
|
|
1549
1735
|
const row = this.db.prepare('SELECT capability_requirement_json FROM tasks WHERE task_id = ?').get(taskId);
|
|
1550
1736
|
return row?.capability_requirement_json ?? null;
|
|
1551
1737
|
}
|
|
1552
1738
|
setTaskCapabilityRequirement(taskId, json) {
|
|
1739
|
+
if (!this.getTaskCapabilityRequirementColumn()) {
|
|
1740
|
+
throw new Error('TASK_CAPABILITY_REQUIREMENT_UNAVAILABLE: Schema v4 未迁移');
|
|
1741
|
+
}
|
|
1553
1742
|
this.db.prepare('UPDATE tasks SET capability_requirement_json = ? WHERE task_id = ?').run(json, taskId);
|
|
1554
1743
|
}
|
|
1744
|
+
getTaskCapabilityRequirementColumn() {
|
|
1745
|
+
return this.db.prepare('PRAGMA table_info(tasks)').all()
|
|
1746
|
+
.some(column => column.name === 'capability_requirement_json');
|
|
1747
|
+
}
|
|
1555
1748
|
getKingdomCapabilityCeiling(kingdomId) {
|
|
1556
1749
|
const row = this.db.prepare('SELECT capability_ceiling_json FROM kingdoms WHERE kingdom_id = ?').get(kingdomId);
|
|
1557
1750
|
return row?.capability_ceiling_json ?? null;
|