@telorun/analyzer 0.17.0 → 0.18.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.
@@ -1,6 +1,23 @@
1
1
  import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
2
2
  import { type ManifestVisitor } from "./manifest-visitor.js";
3
3
  import type { AnalysisContext } from "./types.js";
4
+ /** One reference field declared by a resource's definition, derived purely from
5
+ * the schema field map (independent of whether the manifest fills it). Editor
6
+ * hosts render these as ports / adapters on a node. */
7
+ export interface RefFieldInfo {
8
+ /** Field-map path with `[]` / `{}` markers (e.g. `targets[]`,
9
+ * `routes[].handler`, `encoder`). */
10
+ path: string;
11
+ /** True when the path traverses at least one array. */
12
+ isArray: boolean;
13
+ /** Accepted `x-telo-ref` constraint strings (e.g. `telo#Runnable`). */
14
+ refs: string[];
15
+ /** Distinct capabilities the slot may target (`Telo.Runnable`,
16
+ * `Telo.Service`, `Telo.Provider`, …) — one per resolvable constraint. The
17
+ * first classifies the port (node-capability → edge, ambient → picker); the
18
+ * full set validates drag-to-wire endpoints. Empty when none resolve. */
19
+ capabilities: string[];
20
+ }
4
21
  /**
5
22
  * Accumulates type and alias knowledge for a running kernel or analysis session.
6
23
  * Wraps AliasResolver and DefinitionRegistry into a single domain-level interface
@@ -23,6 +40,31 @@ export declare class AnalysisRegistry {
23
40
  * sub-schema (e.g. Server.notFoundHandler.returns[].content[mime].encoder).
24
41
  */
25
42
  iterateFieldEntries(resource: ResourceManifest, onRef: (fieldPath: string) => void, onScope: (fieldPath: string) => void): void;
43
+ /**
44
+ * Returns every reference field a resource's definition declares, with arity
45
+ * and the capability each slot targets — derived purely from the schema field
46
+ * map, so it lists slots even when the manifest leaves them empty. Editor
47
+ * hosts render these as node ports (drag-to-wire for node-capability targets,
48
+ * inline picker for ambient targets).
49
+ */
50
+ refFieldsForResource(resource: ResourceManifest): RefFieldInfo[];
51
+ /** Base capability an `x-telo-ref` constraint targets. A definition's declared
52
+ * `capability` is always one of the base capabilities, so it wins — this
53
+ * resolves user-defined abstracts (e.g. `std/ai#Model`, declared
54
+ * `capability: Telo.Invocable`) to the capability instances satisfy, not the
55
+ * abstract kind. Builtin abstracts (`telo#Runnable`) carry no `capability`
56
+ * field — there the kind itself *is* the capability. Undefined when
57
+ * unresolvable. */
58
+ capabilityForRef(xTeloRef: string): string | undefined;
59
+ /** Resolves the JSON Schema for a kind's `invoke()` inputs, for editor hosts
60
+ * that render a typed inputs form. Two-layer fallback mirroring the analyzer's
61
+ * template inputs typing: the definition's own `inputType`, then the
62
+ * `extends`-declared abstract's `inputType`. Resolves the inline
63
+ * (`{ kind: Type.JsonSchema, schema }`) and raw-schema forms; a bare named
64
+ * type reference is left unresolved (returns undefined) so the caller can fall
65
+ * back to a freeform map. Undefined when the kind declares no input contract. */
66
+ inputTypeForKind(kind: string): Record<string, unknown> | undefined;
67
+ private capabilitiesForRefs;
26
68
  /**
27
69
  * Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
28
70
  * the shared manifest visitor, bound to this registry's definitions and
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzF,IAAI;IAQP;;;;OAIG;IACH,kBAAkB,IAAI,kBAAkB,EAAE;IAI1C,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAM/D,QAAQ,IAAI,MAAM,EAAE;IAIpB;mEAC+D;IAC/D,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAIxC;;;gCAG4B;IAC5B,oBAAoB,IAAI,MAAM,EAAE;IAIhC;wEACoE;IACpE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD;;;;;gEAK4D;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IA+B7D,qFAAqF;IACrF,QAAQ,IAAI,eAAe;CAG5B"}
1
+ {"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD;;wDAEwD;AACxD,MAAM,WAAW,YAAY;IAC3B;0CACsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;8EAG0E;IAC1E,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,YAAY,EAAE;IAoBhE;;;;;;wBAMoB;IACpB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQtD;;;;;;sFAMkF;IAClF,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAenE,OAAO,CAAC,mBAAmB;IAS3B;;;;;;OAMG;IACH,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzF,IAAI;IAQP;;;;OAIG;IACH,kBAAkB,IAAI,kBAAkB,EAAE;IAI1C,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAM/D,QAAQ,IAAI,MAAM,EAAE;IAIpB;mEAC+D;IAC/D,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAIxC;;;gCAG4B;IAC5B,oBAAoB,IAAI,MAAM,EAAE;IAIhC;wEACoE;IACpE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD;;;;;gEAK4D;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IA+B7D,qFAAqF;IACrF,QAAQ,IAAI,eAAe;CAG5B"}
@@ -4,6 +4,7 @@ import { DefinitionRegistry } from "./definition-registry.js";
4
4
  import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.js";
5
5
  import { visitManifest as runVisitManifest } from "./manifest-visitor.js";
6
6
  import { isRefEntry, isScopeEntry } from "./reference-field-map.js";
7
+ import { resolveTypeFieldToSchema } from "./validate-cel-context.js";
7
8
  /**
8
9
  * Accumulates type and alias knowledge for a running kernel or analysis session.
9
10
  * Wraps AliasResolver and DefinitionRegistry into a single domain-level interface
@@ -47,6 +48,79 @@ export class AnalysisRegistry {
47
48
  }
48
49
  }
49
50
  }
51
+ /**
52
+ * Returns every reference field a resource's definition declares, with arity
53
+ * and the capability each slot targets — derived purely from the schema field
54
+ * map, so it lists slots even when the manifest leaves them empty. Editor
55
+ * hosts render these as node ports (drag-to-wire for node-capability targets,
56
+ * inline picker for ambient targets).
57
+ */
58
+ refFieldsForResource(resource) {
59
+ const fieldMap = this.defs.expandedFieldMapForResource(resource, this.aliases, this.aliasesByModule);
60
+ if (!fieldMap)
61
+ return [];
62
+ const out = [];
63
+ for (const [path, entry] of fieldMap) {
64
+ if (!isRefEntry(entry))
65
+ continue;
66
+ out.push({
67
+ path,
68
+ isArray: entry.isArray,
69
+ refs: entry.refs,
70
+ capabilities: this.capabilitiesForRefs(entry.refs),
71
+ });
72
+ }
73
+ return out;
74
+ }
75
+ /** Base capability an `x-telo-ref` constraint targets. A definition's declared
76
+ * `capability` is always one of the base capabilities, so it wins — this
77
+ * resolves user-defined abstracts (e.g. `std/ai#Model`, declared
78
+ * `capability: Telo.Invocable`) to the capability instances satisfy, not the
79
+ * abstract kind. Builtin abstracts (`telo#Runnable`) carry no `capability`
80
+ * field — there the kind itself *is* the capability. Undefined when
81
+ * unresolvable. */
82
+ capabilityForRef(xTeloRef) {
83
+ const kind = this.defs.resolveRef(xTeloRef);
84
+ if (!kind)
85
+ return undefined;
86
+ const def = this.defs.resolve(kind);
87
+ if (!def)
88
+ return undefined;
89
+ return def.capability ?? kind;
90
+ }
91
+ /** Resolves the JSON Schema for a kind's `invoke()` inputs, for editor hosts
92
+ * that render a typed inputs form. Two-layer fallback mirroring the analyzer's
93
+ * template inputs typing: the definition's own `inputType`, then the
94
+ * `extends`-declared abstract's `inputType`. Resolves the inline
95
+ * (`{ kind: Type.JsonSchema, schema }`) and raw-schema forms; a bare named
96
+ * type reference is left unresolved (returns undefined) so the caller can fall
97
+ * back to a freeform map. Undefined when the kind declares no input contract. */
98
+ inputTypeForKind(kind) {
99
+ const def = this.resolveDefinition(kind);
100
+ if (!def)
101
+ return undefined;
102
+ const own = resolveTypeFieldToSchema(def.inputType, []);
103
+ if (own)
104
+ return own;
105
+ if (def.extends) {
106
+ const abstractDef = this.resolveDefinition(def.extends);
107
+ if (abstractDef) {
108
+ const inherited = resolveTypeFieldToSchema(abstractDef.inputType, []);
109
+ if (inherited)
110
+ return inherited;
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+ capabilitiesForRefs(refs) {
116
+ const out = [];
117
+ for (const ref of refs) {
118
+ const cap = this.capabilityForRef(ref);
119
+ if (cap && !out.includes(cap))
120
+ out.push(cap);
121
+ }
122
+ return out;
123
+ }
50
124
  /**
51
125
  * Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
52
126
  * the shared manifest visitor, bound to this registry's definitions and
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
+ export type { RefFieldInfo } from "./analysis-registry.js";
2
3
  export { StaticAnalyzer } from "./analyzer.js";
3
4
  export type { GraphLoadError, ImportEdge, LoadedFile, LoadedGraph, LoadedModule, ParseError, } from "./loaded-types.js";
4
5
  export { flattenForAnalyzer, flattenLoadedModule, selectModuleManifestsForAnalysis, } from "./flatten-for-analyzer.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,gCAAgC,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EACH,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3E,YAAY,EACR,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,KAAK,EACR,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,gCAAgC,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EACH,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3E,YAAY,EACR,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,KAAK,EACR,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/analyzer",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "Telo Analyzer - Static manifest validator for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
@@ -48,7 +48,7 @@
48
48
  "@types/node": "^20.0.0",
49
49
  "typescript": "^5.0.0",
50
50
  "vitest": "^2.1.8",
51
- "@telorun/sdk": "0.17.0"
51
+ "@telorun/sdk": "0.18.0"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "@telorun/sdk": "*"
@@ -6,6 +6,25 @@ import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.
6
6
  import { visitManifest as runVisitManifest, type ManifestVisitor } from "./manifest-visitor.js";
7
7
  import { isRefEntry, isScopeEntry } from "./reference-field-map.js";
8
8
  import type { AnalysisContext } from "./types.js";
9
+ import { resolveTypeFieldToSchema } from "./validate-cel-context.js";
10
+
11
+ /** One reference field declared by a resource's definition, derived purely from
12
+ * the schema field map (independent of whether the manifest fills it). Editor
13
+ * hosts render these as ports / adapters on a node. */
14
+ export interface RefFieldInfo {
15
+ /** Field-map path with `[]` / `{}` markers (e.g. `targets[]`,
16
+ * `routes[].handler`, `encoder`). */
17
+ path: string;
18
+ /** True when the path traverses at least one array. */
19
+ isArray: boolean;
20
+ /** Accepted `x-telo-ref` constraint strings (e.g. `telo#Runnable`). */
21
+ refs: string[];
22
+ /** Distinct capabilities the slot may target (`Telo.Runnable`,
23
+ * `Telo.Service`, `Telo.Provider`, …) — one per resolvable constraint. The
24
+ * first classifies the port (node-capability → edge, ambient → picker); the
25
+ * full set validates drag-to-wire endpoints. Empty when none resolve. */
26
+ capabilities: string[];
27
+ }
9
28
 
10
29
  /**
11
30
  * Accumulates type and alias knowledge for a running kernel or analysis session.
@@ -63,6 +82,79 @@ export class AnalysisRegistry {
63
82
  }
64
83
  }
65
84
 
85
+ /**
86
+ * Returns every reference field a resource's definition declares, with arity
87
+ * and the capability each slot targets — derived purely from the schema field
88
+ * map, so it lists slots even when the manifest leaves them empty. Editor
89
+ * hosts render these as node ports (drag-to-wire for node-capability targets,
90
+ * inline picker for ambient targets).
91
+ */
92
+ refFieldsForResource(resource: ResourceManifest): RefFieldInfo[] {
93
+ const fieldMap = this.defs.expandedFieldMapForResource(
94
+ resource,
95
+ this.aliases,
96
+ this.aliasesByModule,
97
+ );
98
+ if (!fieldMap) return [];
99
+ const out: RefFieldInfo[] = [];
100
+ for (const [path, entry] of fieldMap) {
101
+ if (!isRefEntry(entry)) continue;
102
+ out.push({
103
+ path,
104
+ isArray: entry.isArray,
105
+ refs: entry.refs,
106
+ capabilities: this.capabilitiesForRefs(entry.refs),
107
+ });
108
+ }
109
+ return out;
110
+ }
111
+
112
+ /** Base capability an `x-telo-ref` constraint targets. A definition's declared
113
+ * `capability` is always one of the base capabilities, so it wins — this
114
+ * resolves user-defined abstracts (e.g. `std/ai#Model`, declared
115
+ * `capability: Telo.Invocable`) to the capability instances satisfy, not the
116
+ * abstract kind. Builtin abstracts (`telo#Runnable`) carry no `capability`
117
+ * field — there the kind itself *is* the capability. Undefined when
118
+ * unresolvable. */
119
+ capabilityForRef(xTeloRef: string): string | undefined {
120
+ const kind = this.defs.resolveRef(xTeloRef);
121
+ if (!kind) return undefined;
122
+ const def = this.defs.resolve(kind);
123
+ if (!def) return undefined;
124
+ return def.capability ?? kind;
125
+ }
126
+
127
+ /** Resolves the JSON Schema for a kind's `invoke()` inputs, for editor hosts
128
+ * that render a typed inputs form. Two-layer fallback mirroring the analyzer's
129
+ * template inputs typing: the definition's own `inputType`, then the
130
+ * `extends`-declared abstract's `inputType`. Resolves the inline
131
+ * (`{ kind: Type.JsonSchema, schema }`) and raw-schema forms; a bare named
132
+ * type reference is left unresolved (returns undefined) so the caller can fall
133
+ * back to a freeform map. Undefined when the kind declares no input contract. */
134
+ inputTypeForKind(kind: string): Record<string, unknown> | undefined {
135
+ const def = this.resolveDefinition(kind);
136
+ if (!def) return undefined;
137
+ const own = resolveTypeFieldToSchema(def.inputType, []);
138
+ if (own) return own;
139
+ if (def.extends) {
140
+ const abstractDef = this.resolveDefinition(def.extends);
141
+ if (abstractDef) {
142
+ const inherited = resolveTypeFieldToSchema(abstractDef.inputType, []);
143
+ if (inherited) return inherited;
144
+ }
145
+ }
146
+ return undefined;
147
+ }
148
+
149
+ private capabilitiesForRefs(refs: string[]): string[] {
150
+ const out: string[] = [];
151
+ for (const ref of refs) {
152
+ const cap = this.capabilityForRef(ref);
153
+ if (cap && !out.includes(cap)) out.push(cap);
154
+ }
155
+ return out;
156
+ }
157
+
66
158
  /**
67
159
  * Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
68
160
  * the shared manifest visitor, bound to this registry's definitions and
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
+ export type { RefFieldInfo } from "./analysis-registry.js";
2
3
  export { StaticAnalyzer } from "./analyzer.js";
3
4
  export type {
4
5
  GraphLoadError,