@elevasis/core 0.45.0 → 0.47.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/dist/auth/index.d.ts +132 -0
- package/dist/knowledge/index.d.ts +14 -10
- package/dist/knowledge/index.js +23 -1
- package/dist/test-utils/index.d.ts +132 -0
- package/package.json +2 -1
- package/src/__tests__/observability-exports.test.ts +27 -22
- package/src/__tests__/published-artifact.test.ts +99 -0
- package/src/execution/engine/llm/__tests__/model-info.test.ts +82 -9
- package/src/execution/engine/llm/__tests__/model-validation.test.ts +82 -17
- package/src/execution/engine/llm/adapters/__tests__/anthropic-adapter.test.ts +108 -87
- package/src/execution/engine/llm/adapters/server/anthropic.ts +38 -24
- package/src/execution/engine/llm/model-info.ts +113 -43
- package/src/knowledge/__tests__/queries.test.ts +174 -0
- package/src/knowledge/format.ts +39 -0
- package/src/knowledge/index.ts +7 -2
- package/src/knowledge/queries.ts +269 -13
- package/src/operations/index.ts +18 -13
- package/src/operations/public-agent-chat/api-schemas.ts +40 -0
- package/src/operations/public-agent-chat/index.ts +12 -0
- package/src/operations/sessions/api-schemas.ts +31 -11
- package/src/operations/sessions/index.ts +14 -12
- package/src/platform/constants/versions.ts +1 -1
- package/src/supabase/database.types.ts +132 -0
|
@@ -26,10 +26,15 @@ export type OpenRouterModel = 'openrouter/z-ai/glm-5'
|
|
|
26
26
|
*/
|
|
27
27
|
export type GoogleModel = 'gemini-3-flash-preview' | 'gemini-3.1-flash-lite-preview'
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
* Supported Anthropic models (direct SDK access via @anthropic-ai/sdk)
|
|
31
|
-
*/
|
|
32
|
-
export type AnthropicModel =
|
|
29
|
+
/**
|
|
30
|
+
* Supported Anthropic models (direct SDK access via @anthropic-ai/sdk)
|
|
31
|
+
*/
|
|
32
|
+
export type AnthropicModel =
|
|
33
|
+
| 'claude-opus-4-8'
|
|
34
|
+
| 'claude-sonnet-4-6'
|
|
35
|
+
| 'claude-haiku-4-5-20251001'
|
|
36
|
+
| 'claude-haiku-4-5'
|
|
37
|
+
| 'claude-sonnet-4-5'
|
|
33
38
|
|
|
34
39
|
/** Supported LLM models */
|
|
35
40
|
export type LLMModel = OpenAIModel | OpenRouterModel | GoogleModel | AnthropicModel | 'mock'
|
|
@@ -122,26 +127,48 @@ export const GoogleConfigSchema = z.object({
|
|
|
122
127
|
modelOptions: GoogleOptionsSchema.optional()
|
|
123
128
|
})
|
|
124
129
|
|
|
125
|
-
/**
|
|
126
|
-
* Anthropic model options schema
|
|
127
|
-
* Currently empty - future options
|
|
128
|
-
*/
|
|
129
|
-
const AnthropicOptionsSchema = z.object({})
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Anthropic config schema
|
|
133
|
-
* Validates ModelConfig for Anthropic provider (direct SDK access)
|
|
134
|
-
*/
|
|
135
|
-
export const AnthropicConfigSchema = z.object({
|
|
136
|
-
model: z.enum(['claude-sonnet-4-5']),
|
|
137
|
-
provider: z.literal('anthropic'),
|
|
138
|
-
apiKey: z.string(),
|
|
139
|
-
temperature: z.number().min(0).max(1).optional(),
|
|
140
|
-
maxOutputTokens: z.number().min(1000).optional(), // Anthropic requires max_tokens
|
|
141
|
-
topP: z.number().min(0).max(1).optional(),
|
|
142
|
-
modelOptions: AnthropicOptionsSchema.optional()
|
|
143
|
-
})
|
|
130
|
+
/**
|
|
131
|
+
* Anthropic model options schema
|
|
132
|
+
* Currently empty - future options must be added per supported model family
|
|
133
|
+
*/
|
|
134
|
+
const AnthropicOptionsSchema = z.object({}).strict()
|
|
144
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Anthropic config schema
|
|
138
|
+
* Validates ModelConfig for Anthropic provider (direct SDK access)
|
|
139
|
+
*/
|
|
140
|
+
const AnthropicStandardConfigSchema = z.object({
|
|
141
|
+
model: z.enum([
|
|
142
|
+
'claude-sonnet-4-6',
|
|
143
|
+
'claude-haiku-4-5-20251001',
|
|
144
|
+
'claude-haiku-4-5',
|
|
145
|
+
'claude-sonnet-4-5'
|
|
146
|
+
]),
|
|
147
|
+
provider: z.literal('anthropic'),
|
|
148
|
+
apiKey: z.string(),
|
|
149
|
+
temperature: z.number().min(0).max(1).optional(),
|
|
150
|
+
maxOutputTokens: z.number().min(1000).max(64000).optional(), // Anthropic requires max_tokens
|
|
151
|
+
topP: z.number().min(0).max(1).optional(),
|
|
152
|
+
modelOptions: AnthropicOptionsSchema.optional()
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const AnthropicOpus48ConfigSchema = z.object({
|
|
156
|
+
model: z.literal('claude-opus-4-8'),
|
|
157
|
+
provider: z.literal('anthropic'),
|
|
158
|
+
apiKey: z.string(),
|
|
159
|
+
temperature: z.literal(1).optional(),
|
|
160
|
+
maxOutputTokens: z.number().min(1000).max(128000).optional(), // Anthropic requires max_tokens
|
|
161
|
+
topP: z.literal(1).optional(),
|
|
162
|
+
topK: z.undefined().optional(),
|
|
163
|
+
top_k: z.undefined().optional(),
|
|
164
|
+
modelOptions: AnthropicOptionsSchema.optional()
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
export const AnthropicConfigSchema = z.discriminatedUnion('model', [
|
|
168
|
+
AnthropicOpus48ConfigSchema,
|
|
169
|
+
AnthropicStandardConfigSchema
|
|
170
|
+
])
|
|
171
|
+
|
|
145
172
|
/**
|
|
146
173
|
* Infer TypeScript types from schemas
|
|
147
174
|
*/
|
|
@@ -191,16 +218,18 @@ export interface ModelInfo {
|
|
|
191
218
|
minTokens: number
|
|
192
219
|
/** Recommended tokens for production use (typically 2x minimum) */
|
|
193
220
|
recommendedTokens: number
|
|
194
|
-
/** Maximum context window size (total tokens: input + output) */
|
|
195
|
-
maxTokens: number
|
|
196
|
-
/**
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
|
|
200
|
-
|
|
221
|
+
/** Maximum context window size (total tokens: input + output) */
|
|
222
|
+
maxTokens: number
|
|
223
|
+
/** Maximum output tokens supported by the synchronous generation API */
|
|
224
|
+
maxOutputTokens?: number
|
|
225
|
+
/** Model category for grouping and documentation */
|
|
226
|
+
category: 'reasoning' | 'standard' | 'embedding'
|
|
227
|
+
/** Zod schema for validating complete ModelConfig (replaces constraints + optionsSchema) */
|
|
228
|
+
configSchema?: z.ZodType<ModelConfig>
|
|
229
|
+
}
|
|
201
230
|
|
|
202
|
-
// Model configuration as of 2026-
|
|
203
|
-
export const MODEL_INFO: Record<LLMModel, ModelInfo> = {
|
|
231
|
+
// Model configuration as of 2026-06-09
|
|
232
|
+
export const MODEL_INFO: Record<LLMModel, ModelInfo> = {
|
|
204
233
|
// OpenAI GPT-5 (Reasoning Models)
|
|
205
234
|
'gpt-5': {
|
|
206
235
|
inputCostPer1M: 125, // $1.25 per 1M tokens
|
|
@@ -268,17 +297,58 @@ export const MODEL_INFO: Record<LLMModel, ModelInfo> = {
|
|
|
268
297
|
category: 'standard',
|
|
269
298
|
configSchema: GoogleConfigSchema
|
|
270
299
|
},
|
|
271
|
-
// Anthropic Claude Models (direct SDK access via @anthropic-ai/sdk)
|
|
272
|
-
'claude-
|
|
273
|
-
inputCostPer1M:
|
|
274
|
-
outputCostPer1M:
|
|
275
|
-
minTokens: 4000,
|
|
276
|
-
recommendedTokens: 8000,
|
|
277
|
-
maxTokens:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
300
|
+
// Anthropic Claude Models (direct SDK access via @anthropic-ai/sdk)
|
|
301
|
+
'claude-opus-4-8': {
|
|
302
|
+
inputCostPer1M: 500, // $5.00 per 1M tokens
|
|
303
|
+
outputCostPer1M: 2500, // $25.00 per 1M tokens
|
|
304
|
+
minTokens: 4000,
|
|
305
|
+
recommendedTokens: 8000,
|
|
306
|
+
maxTokens: 1000000, // 1M context window
|
|
307
|
+
maxOutputTokens: 128000,
|
|
308
|
+
category: 'reasoning',
|
|
309
|
+
configSchema: AnthropicConfigSchema
|
|
310
|
+
},
|
|
311
|
+
'claude-sonnet-4-6': {
|
|
312
|
+
inputCostPer1M: 300, // $3.00 per 1M tokens
|
|
313
|
+
outputCostPer1M: 1500, // $15.00 per 1M tokens
|
|
314
|
+
minTokens: 4000,
|
|
315
|
+
recommendedTokens: 8000,
|
|
316
|
+
maxTokens: 1000000, // 1M context window
|
|
317
|
+
maxOutputTokens: 64000,
|
|
318
|
+
category: 'standard',
|
|
319
|
+
configSchema: AnthropicConfigSchema
|
|
320
|
+
},
|
|
321
|
+
'claude-haiku-4-5-20251001': {
|
|
322
|
+
inputCostPer1M: 100, // $1.00 per 1M tokens
|
|
323
|
+
outputCostPer1M: 500, // $5.00 per 1M tokens
|
|
324
|
+
minTokens: 4000,
|
|
325
|
+
recommendedTokens: 8000,
|
|
326
|
+
maxTokens: 200000, // 200k context window
|
|
327
|
+
maxOutputTokens: 64000,
|
|
328
|
+
category: 'standard',
|
|
329
|
+
configSchema: AnthropicConfigSchema
|
|
330
|
+
},
|
|
331
|
+
'claude-haiku-4-5': {
|
|
332
|
+
inputCostPer1M: 100, // $1.00 per 1M tokens
|
|
333
|
+
outputCostPer1M: 500, // $5.00 per 1M tokens
|
|
334
|
+
minTokens: 4000,
|
|
335
|
+
recommendedTokens: 8000,
|
|
336
|
+
maxTokens: 200000, // 200k context window
|
|
337
|
+
maxOutputTokens: 64000,
|
|
338
|
+
category: 'standard',
|
|
339
|
+
configSchema: AnthropicConfigSchema
|
|
340
|
+
},
|
|
341
|
+
'claude-sonnet-4-5': {
|
|
342
|
+
inputCostPer1M: 300, // $3.00 per 1M tokens
|
|
343
|
+
outputCostPer1M: 1500, // $15.00 per 1M tokens
|
|
344
|
+
minTokens: 4000,
|
|
345
|
+
recommendedTokens: 8000,
|
|
346
|
+
maxTokens: 200000, // 200k context window
|
|
347
|
+
maxOutputTokens: 64000,
|
|
348
|
+
category: 'standard',
|
|
349
|
+
configSchema: AnthropicConfigSchema
|
|
350
|
+
}
|
|
351
|
+
}
|
|
282
352
|
|
|
283
353
|
/**
|
|
284
354
|
* Get model information (pricing and token requirements)
|
|
@@ -1097,3 +1097,177 @@ describe('formatOmDescribe', () => {
|
|
|
1097
1097
|
expect(output).toContain('System: sales.lead-gen')
|
|
1098
1098
|
})
|
|
1099
1099
|
})
|
|
1100
|
+
|
|
1101
|
+
// ---------------------------------------------------------------------------
|
|
1102
|
+
// Domain-item resolution (item:<domain>:<id> + bare-id back-compat)
|
|
1103
|
+
// ---------------------------------------------------------------------------
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* Fixture exercising all six graph-projected domain-item kinds.
|
|
1107
|
+
* `knowledge.brand-guide` governs the client via a `client:client-1` link.
|
|
1108
|
+
*/
|
|
1109
|
+
const DOMAIN_ITEM_MODEL = {
|
|
1110
|
+
knowledge: {
|
|
1111
|
+
'knowledge.brand-guide': {
|
|
1112
|
+
id: 'knowledge.brand-guide',
|
|
1113
|
+
kind: 'reference',
|
|
1114
|
+
title: 'Brand Guide',
|
|
1115
|
+
summary: 'Branding rules for the client.',
|
|
1116
|
+
body: '## Brand Guide\n\nVoice and palette.',
|
|
1117
|
+
links: [{ nodeId: 'client:client-1' }],
|
|
1118
|
+
ownerIds: [],
|
|
1119
|
+
updatedAt: '2026-01-01'
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
clients: {
|
|
1123
|
+
'client-1': {
|
|
1124
|
+
id: 'client-1',
|
|
1125
|
+
name: 'Byron for Irvine',
|
|
1126
|
+
organizationName: 'Byron for Irvine Campaign',
|
|
1127
|
+
shortName: 'Byron',
|
|
1128
|
+
clientBrief: 'Local city-council campaign.',
|
|
1129
|
+
candidateName: 'Byron'
|
|
1130
|
+
}
|
|
1131
|
+
},
|
|
1132
|
+
roles: {
|
|
1133
|
+
'role.ops-lead': {
|
|
1134
|
+
id: 'role.ops-lead',
|
|
1135
|
+
order: 10,
|
|
1136
|
+
title: 'Ops Lead',
|
|
1137
|
+
responsibilities: ['Run operations.'],
|
|
1138
|
+
responsibleFor: []
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
policies: {
|
|
1142
|
+
'policy.review-spend': {
|
|
1143
|
+
id: 'policy.review-spend',
|
|
1144
|
+
order: 10,
|
|
1145
|
+
label: 'Review Spend',
|
|
1146
|
+
description: 'Review spend over threshold.'
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
customers: {
|
|
1150
|
+
'cust-1': {
|
|
1151
|
+
id: 'cust-1',
|
|
1152
|
+
name: 'SMB Automation Segment',
|
|
1153
|
+
description: 'Small businesses adopting automation.'
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
offerings: {
|
|
1157
|
+
'off-1': {
|
|
1158
|
+
id: 'off-1',
|
|
1159
|
+
name: 'Automation Starter Package',
|
|
1160
|
+
description: 'Entry automation engagement.'
|
|
1161
|
+
}
|
|
1162
|
+
},
|
|
1163
|
+
goals: {
|
|
1164
|
+
'goal-1': {
|
|
1165
|
+
id: 'goal-1',
|
|
1166
|
+
description: 'Double recurring revenue this year.'
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
} as unknown as OrganizationModel
|
|
1170
|
+
|
|
1171
|
+
describe('omDescribe — domain items', () => {
|
|
1172
|
+
it('resolves item:clients:<id> to the full client profile + location + governing knowledge', () => {
|
|
1173
|
+
const result = omDescribe(DOMAIN_ITEM_MODEL, 'item:clients:client-1')
|
|
1174
|
+
expect(result).toBeDefined()
|
|
1175
|
+
if (!result || result.kind !== 'domain-item') throw new Error('expected domain-item result')
|
|
1176
|
+
expect(result.domain).toBe('clients')
|
|
1177
|
+
expect(result.id).toBe('item:clients:client-1')
|
|
1178
|
+
expect(result.name).toBe('Byron for Irvine')
|
|
1179
|
+
// Full ClientProfile payload is carried in `record`.
|
|
1180
|
+
expect(result.record).toMatchObject({
|
|
1181
|
+
organizationName: 'Byron for Irvine Campaign',
|
|
1182
|
+
candidateName: 'Byron'
|
|
1183
|
+
})
|
|
1184
|
+
// Location.
|
|
1185
|
+
expect(result.location.domainLabel).toBe('Clients')
|
|
1186
|
+
expect(result.location.graphNodeId).toBe('client:client-1')
|
|
1187
|
+
expect(result.location.containsParentIds).toContain('organization-model')
|
|
1188
|
+
// Governing knowledge.
|
|
1189
|
+
expect(result.governingKnowledge.map((g) => g.id)).toContain('knowledge.brand-guide')
|
|
1190
|
+
})
|
|
1191
|
+
|
|
1192
|
+
it('resolves bare client:<id> identically to the item: form (back-compat)', () => {
|
|
1193
|
+
const bare = omDescribe(DOMAIN_ITEM_MODEL, 'client:client-1')
|
|
1194
|
+
const canonical = omDescribe(DOMAIN_ITEM_MODEL, 'item:clients:client-1')
|
|
1195
|
+
expect(bare).toEqual(canonical)
|
|
1196
|
+
})
|
|
1197
|
+
|
|
1198
|
+
it('resolves the other five domain kinds via item: and bare ids', () => {
|
|
1199
|
+
const cases: Array<{ item: string; bare: string; domain: string; name: string }> = [
|
|
1200
|
+
{ item: 'item:roles:role.ops-lead', bare: 'role:role.ops-lead', domain: 'roles', name: 'Ops Lead' },
|
|
1201
|
+
{
|
|
1202
|
+
item: 'item:policies:policy.review-spend',
|
|
1203
|
+
bare: 'policy:policy.review-spend',
|
|
1204
|
+
domain: 'policies',
|
|
1205
|
+
name: 'Review Spend'
|
|
1206
|
+
},
|
|
1207
|
+
{ item: 'item:customers:cust-1', bare: 'customer:cust-1', domain: 'customers', name: 'SMB Automation Segment' },
|
|
1208
|
+
{ item: 'item:offerings:off-1', bare: 'offering:off-1', domain: 'offerings', name: 'Automation Starter Package' },
|
|
1209
|
+
{ item: 'item:goals:goal-1', bare: 'goal:goal-1', domain: 'goals', name: 'Double recurring revenue this year.' }
|
|
1210
|
+
]
|
|
1211
|
+
for (const c of cases) {
|
|
1212
|
+
const viaItem = omDescribe(DOMAIN_ITEM_MODEL, c.item)
|
|
1213
|
+
expect(viaItem, `item form ${c.item}`).toBeDefined()
|
|
1214
|
+
if (!viaItem || viaItem.kind !== 'domain-item') throw new Error(`expected domain-item for ${c.item}`)
|
|
1215
|
+
expect(viaItem.domain).toBe(c.domain)
|
|
1216
|
+
expect(viaItem.name).toBe(c.name)
|
|
1217
|
+
// Bare form resolves to the same result.
|
|
1218
|
+
expect(omDescribe(DOMAIN_ITEM_MODEL, c.bare)).toEqual(viaItem)
|
|
1219
|
+
}
|
|
1220
|
+
})
|
|
1221
|
+
|
|
1222
|
+
it('returns undefined for an unknown item id', () => {
|
|
1223
|
+
expect(omDescribe(DOMAIN_ITEM_MODEL, 'item:clients:does-not-exist')).toBeUndefined()
|
|
1224
|
+
expect(omDescribe(DOMAIN_ITEM_MODEL, 'client:does-not-exist')).toBeUndefined()
|
|
1225
|
+
})
|
|
1226
|
+
|
|
1227
|
+
it('returns undefined for an item ref with an unknown domain', () => {
|
|
1228
|
+
expect(omDescribe(DOMAIN_ITEM_MODEL, 'item:widgets:thing-1')).toBeUndefined()
|
|
1229
|
+
})
|
|
1230
|
+
})
|
|
1231
|
+
|
|
1232
|
+
describe('parsePath — domain-item mounts', () => {
|
|
1233
|
+
it('parses /by-domain/<domain> into a by-domain mount', () => {
|
|
1234
|
+
expect(parsePath('/by-domain/clients')).toEqual({ mount: 'by-domain', args: ['clients'] })
|
|
1235
|
+
})
|
|
1236
|
+
|
|
1237
|
+
it('parses /by-item/<domain>/<itemId> into a by-item mount', () => {
|
|
1238
|
+
expect(parsePath('/by-item/clients/client-1')).toEqual({ mount: 'by-item', args: ['clients', 'client-1'] })
|
|
1239
|
+
})
|
|
1240
|
+
|
|
1241
|
+
it('throws on an unknown domain for /by-domain', () => {
|
|
1242
|
+
expect(() => parsePath('/by-domain/widgets')).toThrow(/unknown domain/i)
|
|
1243
|
+
})
|
|
1244
|
+
|
|
1245
|
+
it('throws on an unknown domain for /by-item', () => {
|
|
1246
|
+
expect(() => parsePath('/by-item/widgets/thing-1')).toThrow(/unknown domain/i)
|
|
1247
|
+
})
|
|
1248
|
+
|
|
1249
|
+
it('throws when /by-item is missing the itemId', () => {
|
|
1250
|
+
expect(() => parsePath('/by-item/clients')).toThrow(/by-item/i)
|
|
1251
|
+
})
|
|
1252
|
+
})
|
|
1253
|
+
|
|
1254
|
+
describe('formatOmDescribe — domain items', () => {
|
|
1255
|
+
it('renders a domain-item header, location, record, and governing knowledge', () => {
|
|
1256
|
+
const result = omDescribe(DOMAIN_ITEM_MODEL, 'item:clients:client-1')
|
|
1257
|
+
const output = formatOmDescribe(result)
|
|
1258
|
+
expect(output).toContain('Domain Item: item:clients:client-1')
|
|
1259
|
+
expect(output).toContain('Domain: Clients')
|
|
1260
|
+
expect(output).toContain('Name: Byron for Irvine')
|
|
1261
|
+
expect(output).toContain('Graph node: client:client-1')
|
|
1262
|
+
expect(output).toContain('Governing knowledge:')
|
|
1263
|
+
expect(output).toContain('knowledge.brand-guide')
|
|
1264
|
+
})
|
|
1265
|
+
|
|
1266
|
+
it('serializes the domain-item result directly via JSON.stringify', () => {
|
|
1267
|
+
const result = omDescribe(DOMAIN_ITEM_MODEL, 'item:clients:client-1')
|
|
1268
|
+
const json = JSON.parse(JSON.stringify(result))
|
|
1269
|
+
expect(json.kind).toBe('domain-item')
|
|
1270
|
+
expect(json.domain).toBe('clients')
|
|
1271
|
+
expect(json.id).toBe('item:clients:client-1')
|
|
1272
|
+
})
|
|
1273
|
+
})
|
package/src/knowledge/format.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { OrgKnowledgeNode } from '../organization-model/domains/knowledge'
|
|
2
2
|
import type {
|
|
3
3
|
KnowledgeMount,
|
|
4
|
+
OmDescribeDomainItem,
|
|
4
5
|
OmDescribeKnowledge,
|
|
5
6
|
OmDescribeOntology,
|
|
6
7
|
OmDescribePolicy,
|
|
@@ -170,6 +171,8 @@ export function formatOmDescribe(result: OmDescribeResult | undefined): string {
|
|
|
170
171
|
return formatRoleDescribe(result)
|
|
171
172
|
case 'policy':
|
|
172
173
|
return formatPolicyDescribe(result)
|
|
174
|
+
case 'domain-item':
|
|
175
|
+
return formatDomainItemDescribe(result)
|
|
173
176
|
}
|
|
174
177
|
}
|
|
175
178
|
|
|
@@ -320,3 +323,39 @@ function formatPolicyDescribe(r: OmDescribePolicy): string {
|
|
|
320
323
|
|
|
321
324
|
return join([header, effectSection, appliesSection])
|
|
322
325
|
}
|
|
326
|
+
|
|
327
|
+
function formatDomainItemDescribe(r: OmDescribeDomainItem): string {
|
|
328
|
+
const header = join([
|
|
329
|
+
`Domain Item: ${r.id}`,
|
|
330
|
+
[
|
|
331
|
+
field('Domain', r.location.domainLabel),
|
|
332
|
+
field('Name', r.name),
|
|
333
|
+
field('Graph node', r.location.graphNodeId),
|
|
334
|
+
field('Parent nodes', r.location.containsParentIds.join(', '))
|
|
335
|
+
]
|
|
336
|
+
.filter((s) => s.length > 0)
|
|
337
|
+
.join('\n')
|
|
338
|
+
])
|
|
339
|
+
|
|
340
|
+
// Key record fields — emit a compact subset of the record payload.
|
|
341
|
+
const recordLines: string[] = []
|
|
342
|
+
for (const [k, v] of Object.entries(r.record)) {
|
|
343
|
+
if (v === undefined || v === null) continue
|
|
344
|
+
if (typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length === 0) continue
|
|
345
|
+
const display = Array.isArray(v)
|
|
346
|
+
? v.length === 0
|
|
347
|
+
? null
|
|
348
|
+
: `[${(v as unknown[]).slice(0, 5).join(', ')}${v.length > 5 ? `, ...+${v.length - 5}` : ''}]`
|
|
349
|
+
: typeof v === 'object'
|
|
350
|
+
? JSON.stringify(v).slice(0, 120)
|
|
351
|
+
: String(v)
|
|
352
|
+
if (display === null) continue
|
|
353
|
+
recordLines.push(` ${k}: ${display}`)
|
|
354
|
+
}
|
|
355
|
+
const recordSection = recordLines.length ? `Record:\n${recordLines.join('\n')}` : ''
|
|
356
|
+
|
|
357
|
+
const govLines = r.governingKnowledge.map((g) => ` - ${g.id} [${g.knowledgeKind}] ${g.title}`)
|
|
358
|
+
const govSection = govLines.length ? `Governing knowledge:\n${govLines.join('\n')}` : 'Governing knowledge:\n (none)'
|
|
359
|
+
|
|
360
|
+
return join([header, recordSection, govSection])
|
|
361
|
+
}
|
package/src/knowledge/index.ts
CHANGED
|
@@ -10,7 +10,8 @@ export {
|
|
|
10
10
|
omDescribe,
|
|
11
11
|
listAllSystemsFlat,
|
|
12
12
|
listAllResources,
|
|
13
|
-
listAllRoles
|
|
13
|
+
listAllRoles,
|
|
14
|
+
DOMAIN_ITEM_KINDS
|
|
14
15
|
} from './queries'
|
|
15
16
|
export type {
|
|
16
17
|
KnowledgeMount,
|
|
@@ -24,7 +25,11 @@ export type {
|
|
|
24
25
|
OmDescribeKnowledge,
|
|
25
26
|
OmDescribeOntology,
|
|
26
27
|
OmDescribeRole,
|
|
27
|
-
OmDescribePolicy
|
|
28
|
+
OmDescribePolicy,
|
|
29
|
+
OmDescribeDomainItem,
|
|
30
|
+
OmDescribeDomainItemLocation,
|
|
31
|
+
OmDescribeDomainItemKnowledgeRef,
|
|
32
|
+
DomainItemKind
|
|
28
33
|
} from './queries'
|
|
29
34
|
|
|
30
35
|
export { formatText, formatJson, formatIdsOnly, formatOmSearchHits, formatOmDescribe } from './format'
|