@cynodia/axiom-agent-api 0.3.1-alpha.1 → 0.4.1-alpha.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/dist/queries.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ActionDef, AnyNode, ApplicationGraph, ConstraintDef, EdgeKind, Expression, FieldId, FormNode, GraphEdge, Location, NodeId, StateDef, UINode, ViewNode } from '@cynodia/axiom-core';
1
+ import type { ActionDef, AnyNode, ApplicationGraph, ConstraintDef, EdgeKind, Expression, FieldId, FormNode, GraphEdge, Location, NodeId, StateDef, TransitionConstraintDef, UINode, ViewNode } from '@cynodia/axiom-core';
2
2
  export interface SubgraphRequest {
3
3
  root: NodeId;
4
4
  depth?: number;
@@ -16,7 +16,17 @@ export interface MutationImpact {
16
16
  directWriters: AnyNode[];
17
17
  dependentDerivedStates: StateDef[];
18
18
  affectedConstraints: ConstraintDef[];
19
+ /** Rules that govern how this state may change, whatever writes it. */
20
+ affectedTransitionConstraints: TransitionConstraintDef[];
19
21
  affectedViews: ViewNode[];
22
+ /**
23
+ * False when something in the graph cannot be analyzed — a native operation that does
24
+ * not declare its effects, for instance. An incomplete answer says so rather than
25
+ * presenting itself as exhaustive.
26
+ */
27
+ analysisComplete: boolean;
28
+ /** Why the analysis is incomplete, when it is. */
29
+ analysisGaps: string[];
20
30
  }
21
31
  export declare class GraphQueries {
22
32
  protected graph: ApplicationGraph;
@@ -33,6 +43,15 @@ export declare class GraphQueries {
33
43
  /** States whose value type mentions the entity. */
34
44
  getStatesForEntity(entityId: NodeId): StateDef[];
35
45
  getConstraintsForEntity(entityId: NodeId): ConstraintDef[];
46
+ /** Rules governing how instances of this entity may change. */
47
+ getTransitionConstraintsForEntity(entityId: NodeId): TransitionConstraintDef[];
48
+ /** Every rule that protects a location, whichever path attempts the write. */
49
+ getRulesProtecting(location: Location): {
50
+ constraints: ConstraintDef[];
51
+ transitionConstraints: TransitionConstraintDef[];
52
+ };
53
+ /** Parts of the graph whose reads and writes cannot be derived. */
54
+ private analysisGaps;
36
55
  /** Actions that write a state holding the entity, or that construct instances of it. */
37
56
  getActionsForEntity(entityId: NodeId): ActionDef[];
38
57
  /** Every UI node that binds or displays one of the entity's fields. */
package/dist/queries.js CHANGED
@@ -45,6 +45,32 @@ export class GraphQueries {
45
45
  getConstraintsForEntity(entityId) {
46
46
  return this.graph.getNodesByKind('constraint').filter((constraint) => constraint.entityId === entityId);
47
47
  }
48
+ /** Rules governing how instances of this entity may change. */
49
+ getTransitionConstraintsForEntity(entityId) {
50
+ return this.graph
51
+ .getNodesByKind('transition-constraint')
52
+ .filter((constraint) => constraint.entityId === entityId);
53
+ }
54
+ /** Every rule that protects a location, whichever path attempts the write. */
55
+ getRulesProtecting(location) {
56
+ const impact = this.getMutationImpact(location);
57
+ return {
58
+ constraints: impact.affectedConstraints,
59
+ transitionConstraints: impact.affectedTransitionConstraints,
60
+ };
61
+ }
62
+ /** Parts of the graph whose reads and writes cannot be derived. */
63
+ analysisGaps() {
64
+ const gaps = [];
65
+ for (const action of this.graph.getNodesByKind('action')) {
66
+ for (const operation of action.operations ?? []) {
67
+ if (operation.kind === 'native' && (operation.declaredEffects ?? []).length === 0) {
68
+ gaps.push(`${action.name ?? action.id} runs the native operation "${operation.implementationId}" without declaring its effects`);
69
+ }
70
+ }
71
+ }
72
+ return gaps;
73
+ }
48
74
  /** Actions that write a state holding the entity, or that construct instances of it. */
49
75
  getActionsForEntity(entityId) {
50
76
  const stateIds = new Set(this.getStatesForEntity(entityId).map((state) => state.id));
@@ -203,6 +229,10 @@ export class GraphQueries {
203
229
  views.set(view.id, view);
204
230
  }
205
231
  }
232
+ const affectedTransitionConstraints = this.graph
233
+ .getNodesByKind('transition-constraint')
234
+ .filter((constraint) => entityIds.has(constraint.entityId));
235
+ const gaps = this.analysisGaps();
206
236
  return {
207
237
  location,
208
238
  rootStateId,
@@ -210,7 +240,10 @@ export class GraphQueries {
210
240
  directWriters,
211
241
  dependentDerivedStates,
212
242
  affectedConstraints,
243
+ affectedTransitionConstraints,
213
244
  affectedViews: [...views.values()],
245
+ analysisComplete: gaps.length === 0,
246
+ analysisGaps: gaps,
214
247
  };
215
248
  }
216
249
  constraintTouches(constraint, fieldIds) {
@@ -245,7 +278,8 @@ export class GraphQueries {
245
278
  }
246
279
  nodesWithFieldEdge(fieldId, kinds) {
247
280
  const found = new Map();
248
- for (const edge of this.graph.listEdges()) {
281
+ // Derived relationships, so an answer never depends on edges having been written.
282
+ for (const edge of this.graph.semanticEdges()) {
249
283
  if (!kinds.includes(edge.kind) || !edgeFieldIds(edge).includes(fieldId)) {
250
284
  continue;
251
285
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cynodia/axiom-agent-api",
3
- "version": "0.3.1-alpha.1",
3
+ "version": "0.4.1-alpha.1",
4
4
  "description": "Semantic queries and transactional graph transformations for AI agents.",
5
5
  "license": "MIT",
6
6
  "author": "AskTech AS",
@@ -31,7 +31,7 @@
31
31
  }
32
32
  },
33
33
  "dependencies": {
34
- "@cynodia/axiom-core": "0.3.1-alpha.1"
34
+ "@cynodia/axiom-core": "0.4.1-alpha.1"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "tsc -b tsconfig.json tsconfig.test.json",