@ontrails/trails 1.0.0-beta.16 → 1.0.0-beta.17
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 +18 -0
- package/package.json +12 -10
- package/src/trails/survey.ts +29 -1
- package/src/trails/topo-output-schemas.ts +47 -3
- package/src/trails/topo-reports.ts +210 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# trails
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 41276d2: Expose a shipped surface projection inventory through survey output and trail detail reports.
|
|
8
|
+
- Updated dependencies [3dc8254]
|
|
9
|
+
- Updated dependencies [61497c5]
|
|
10
|
+
- @ontrails/core@1.0.0-beta.17
|
|
11
|
+
- @ontrails/cli@1.0.0-beta.17
|
|
12
|
+
- @ontrails/commander@1.0.0-beta.17
|
|
13
|
+
- @ontrails/http@1.0.0-beta.17
|
|
14
|
+
- @ontrails/mcp@1.0.0-beta.17
|
|
15
|
+
- @ontrails/observe@1.0.0-beta.17
|
|
16
|
+
- @ontrails/permits@1.0.0-beta.17
|
|
17
|
+
- @ontrails/topographer@1.0.0-beta.17
|
|
18
|
+
- @ontrails/tracing@1.0.0-beta.17
|
|
19
|
+
- @ontrails/warden@1.0.0-beta.17
|
|
20
|
+
|
|
3
21
|
## 1.0.0-beta.16
|
|
4
22
|
|
|
5
23
|
### Major Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/trails",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.17",
|
|
4
4
|
"bin": {
|
|
5
5
|
"trails": "./bin/trails.ts"
|
|
6
6
|
},
|
|
@@ -23,18 +23,20 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@clack/prompts": "^1.1.0",
|
|
26
|
-
"@ontrails/cli": "^1.0.0-beta.
|
|
27
|
-
"@ontrails/commander": "^1.0.0-beta.
|
|
28
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
29
|
-
"@ontrails/
|
|
30
|
-
"@ontrails/
|
|
31
|
-
"@ontrails/
|
|
32
|
-
"@ontrails/
|
|
33
|
-
"@ontrails/
|
|
26
|
+
"@ontrails/cli": "^1.0.0-beta.16",
|
|
27
|
+
"@ontrails/commander": "^1.0.0-beta.16",
|
|
28
|
+
"@ontrails/core": "^1.0.0-beta.16",
|
|
29
|
+
"@ontrails/http": "^1.0.0-beta.16",
|
|
30
|
+
"@ontrails/mcp": "^1.0.0-beta.16",
|
|
31
|
+
"@ontrails/observe": "^1.0.0-beta.16",
|
|
32
|
+
"@ontrails/permits": "^1.0.0-beta.16",
|
|
33
|
+
"@ontrails/topographer": "^1.0.0-beta.16",
|
|
34
|
+
"@ontrails/tracing": "^1.0.0-beta.16",
|
|
35
|
+
"@ontrails/warden": "^1.0.0-beta.16",
|
|
34
36
|
"commander": "^14.0.3",
|
|
35
37
|
"zod": "^4.3.5"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
|
-
"@ontrails/testing": "^1.0.0-beta.
|
|
40
|
+
"@ontrails/testing": "^1.0.0-beta.16"
|
|
39
41
|
}
|
|
40
42
|
}
|
package/src/trails/survey.ts
CHANGED
|
@@ -41,23 +41,30 @@ import {
|
|
|
41
41
|
import {
|
|
42
42
|
activationOverviewOutput,
|
|
43
43
|
resourceDetailOutput,
|
|
44
|
+
shippedSurfaceInventoryOutput,
|
|
44
45
|
signalDetailOutput,
|
|
45
46
|
trailDetailOutput,
|
|
46
47
|
} from './topo-output-schemas.js';
|
|
47
48
|
import { createIsolatedExampleInput } from './topo-support.js';
|
|
48
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
briefReportSchema,
|
|
51
|
+
deriveShippedSurfaceProjectionInventory,
|
|
52
|
+
} from './topo-reports.js';
|
|
49
53
|
import type { SurfaceLayerNames } from './topo-reports.js';
|
|
50
54
|
|
|
51
55
|
export {
|
|
52
56
|
briefReportSchema,
|
|
53
57
|
deriveBriefReport,
|
|
54
58
|
deriveResourceDetail,
|
|
59
|
+
deriveShippedSurfaceProjectionInventory,
|
|
55
60
|
deriveSignalDetail,
|
|
56
61
|
deriveSurveyList,
|
|
57
62
|
deriveTrailDetail,
|
|
58
63
|
} from './topo-reports.js';
|
|
59
64
|
export type {
|
|
60
65
|
BriefReport,
|
|
66
|
+
ShippedSurfaceInventoryReport,
|
|
67
|
+
ShippedSurfaceProjection,
|
|
61
68
|
SignalDetailReport,
|
|
62
69
|
SurfaceLayerNames,
|
|
63
70
|
SurveyListReport,
|
|
@@ -278,6 +285,9 @@ const buildSurveySignalDetail = (
|
|
|
278
285
|
: Result.ok(detail);
|
|
279
286
|
};
|
|
280
287
|
|
|
288
|
+
const buildSurveySurfaceInventory = (app: Topo): Result<object, Error> =>
|
|
289
|
+
Result.ok(deriveShippedSurfaceProjectionInventory(app));
|
|
290
|
+
|
|
281
291
|
interface SurveyInput {
|
|
282
292
|
id?: string | undefined;
|
|
283
293
|
module?: string | undefined;
|
|
@@ -506,6 +516,24 @@ export const surveyBriefTrail = trail('survey.brief', {
|
|
|
506
516
|
output: briefReportSchema,
|
|
507
517
|
});
|
|
508
518
|
|
|
519
|
+
export const surveySurfacesTrail = trail('survey.surfaces', {
|
|
520
|
+
blaze: async (input, ctx) =>
|
|
521
|
+
withResolvedSurveyApp(input, ctx.cwd, (app) =>
|
|
522
|
+
buildSurveySurfaceInventory(app)
|
|
523
|
+
),
|
|
524
|
+
description: 'Inventory shipped surface projections',
|
|
525
|
+
examples: [
|
|
526
|
+
{
|
|
527
|
+
description: 'Show CLI, MCP, and HTTP projections for public trails',
|
|
528
|
+
input: createIsolatedExampleInput('survey-surfaces'),
|
|
529
|
+
name: 'Shipped surface inventory',
|
|
530
|
+
},
|
|
531
|
+
],
|
|
532
|
+
input: moduleInputSchema,
|
|
533
|
+
intent: 'read',
|
|
534
|
+
output: shippedSurfaceInventoryOutput,
|
|
535
|
+
});
|
|
536
|
+
|
|
509
537
|
export const surveyDiffTrail = trail('survey.diff', {
|
|
510
538
|
blaze: async (input, ctx) =>
|
|
511
539
|
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
@@ -86,11 +86,55 @@ const contourDetailOutput = z.object({
|
|
|
86
86
|
surfaces: z.array(z.string()).readonly(),
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
const
|
|
89
|
+
const surfaceProjectionBaseOutput = {
|
|
90
90
|
derivedName: z.string(),
|
|
91
|
-
|
|
92
|
-
surface: z.string(),
|
|
91
|
+
source: z.enum(['authored', 'default-derived']),
|
|
93
92
|
trailId: z.string(),
|
|
93
|
+
} as const;
|
|
94
|
+
|
|
95
|
+
export const surfaceProjectionOutput = z.discriminatedUnion('surface', [
|
|
96
|
+
z.object({
|
|
97
|
+
...surfaceProjectionBaseOutput,
|
|
98
|
+
commandPath: z.array(z.string()).readonly(),
|
|
99
|
+
method: z.null(),
|
|
100
|
+
surface: z.literal('cli'),
|
|
101
|
+
}),
|
|
102
|
+
z.object({
|
|
103
|
+
...surfaceProjectionBaseOutput,
|
|
104
|
+
method: z.null(),
|
|
105
|
+
surface: z.literal('mcp'),
|
|
106
|
+
toolName: z.string(),
|
|
107
|
+
}),
|
|
108
|
+
z.object({
|
|
109
|
+
...surfaceProjectionBaseOutput,
|
|
110
|
+
method: z.string(),
|
|
111
|
+
path: z.string(),
|
|
112
|
+
surface: z.literal('http'),
|
|
113
|
+
}),
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
export const shippedSurfaceInventoryOutput = z.object({
|
|
117
|
+
count: z.number(),
|
|
118
|
+
excludedSurfaces: z
|
|
119
|
+
.array(
|
|
120
|
+
z.object({
|
|
121
|
+
reason: z.string(),
|
|
122
|
+
status: z.literal('planned'),
|
|
123
|
+
surface: z.literal('websocket'),
|
|
124
|
+
})
|
|
125
|
+
)
|
|
126
|
+
.readonly(),
|
|
127
|
+
projections: z.array(surfaceProjectionOutput).readonly(),
|
|
128
|
+
shippedSurfaces: z.array(z.enum(['cli', 'mcp', 'http'])).readonly(),
|
|
129
|
+
trails: z
|
|
130
|
+
.array(
|
|
131
|
+
z.object({
|
|
132
|
+
explicitSurfaces: z.array(z.string()).readonly(),
|
|
133
|
+
projections: z.array(surfaceProjectionOutput).readonly(),
|
|
134
|
+
trailId: z.string(),
|
|
135
|
+
})
|
|
136
|
+
)
|
|
137
|
+
.readonly(),
|
|
94
138
|
});
|
|
95
139
|
|
|
96
140
|
export const trailDetailOutput = z.object({
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DETOUR_MAX_ATTEMPTS_CAP,
|
|
3
|
+
deriveCliPath,
|
|
4
|
+
filterSurfaceTrails,
|
|
5
|
+
zodToJsonSchema,
|
|
6
|
+
} from '@ontrails/core';
|
|
2
7
|
import type { AnyTrail, Signal, Topo } from '@ontrails/core';
|
|
8
|
+
import { deriveHttpMethod } from '@ontrails/http';
|
|
9
|
+
import type { HttpMethod } from '@ontrails/http';
|
|
10
|
+
import { deriveToolName } from '@ontrails/mcp';
|
|
3
11
|
import { deriveTopoGraph } from '@ontrails/topographer';
|
|
4
12
|
import type {
|
|
5
13
|
JsonSchema,
|
|
@@ -66,6 +74,52 @@ export type SurfaceLayerNames = Readonly<
|
|
|
66
74
|
Record<SurfaceLayerKey, readonly string[]>
|
|
67
75
|
>;
|
|
68
76
|
|
|
77
|
+
export type ShippedSurfaceKey = 'cli' | 'mcp' | 'http';
|
|
78
|
+
|
|
79
|
+
export type SurfaceProjectionSource = 'authored' | 'default-derived';
|
|
80
|
+
|
|
81
|
+
export type ShippedSurfaceProjection =
|
|
82
|
+
| {
|
|
83
|
+
readonly commandPath: readonly string[];
|
|
84
|
+
readonly derivedName: string;
|
|
85
|
+
readonly method: null;
|
|
86
|
+
readonly source: SurfaceProjectionSource;
|
|
87
|
+
readonly surface: 'cli';
|
|
88
|
+
readonly trailId: string;
|
|
89
|
+
}
|
|
90
|
+
| {
|
|
91
|
+
readonly derivedName: string;
|
|
92
|
+
readonly method: null;
|
|
93
|
+
readonly source: SurfaceProjectionSource;
|
|
94
|
+
readonly surface: 'mcp';
|
|
95
|
+
readonly toolName: string;
|
|
96
|
+
readonly trailId: string;
|
|
97
|
+
}
|
|
98
|
+
| {
|
|
99
|
+
readonly derivedName: string;
|
|
100
|
+
readonly method: HttpMethod;
|
|
101
|
+
readonly path: string;
|
|
102
|
+
readonly source: SurfaceProjectionSource;
|
|
103
|
+
readonly surface: 'http';
|
|
104
|
+
readonly trailId: string;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export interface ShippedSurfaceInventoryReport {
|
|
108
|
+
readonly count: number;
|
|
109
|
+
readonly excludedSurfaces: readonly {
|
|
110
|
+
readonly reason: string;
|
|
111
|
+
readonly status: 'planned';
|
|
112
|
+
readonly surface: 'websocket';
|
|
113
|
+
}[];
|
|
114
|
+
readonly projections: readonly ShippedSurfaceProjection[];
|
|
115
|
+
readonly shippedSurfaces: readonly ShippedSurfaceKey[];
|
|
116
|
+
readonly trails: readonly {
|
|
117
|
+
readonly explicitSurfaces: readonly string[];
|
|
118
|
+
readonly projections: readonly ShippedSurfaceProjection[];
|
|
119
|
+
readonly trailId: string;
|
|
120
|
+
}[];
|
|
121
|
+
}
|
|
122
|
+
|
|
69
123
|
type TopoGraphContourEntry = TopoGraphEntry & { readonly kind: 'contour' };
|
|
70
124
|
|
|
71
125
|
export interface TrailDetailOptions {
|
|
@@ -155,12 +209,7 @@ export interface TrailDetailReport {
|
|
|
155
209
|
readonly pattern: string | null;
|
|
156
210
|
readonly safety: string;
|
|
157
211
|
readonly resources: readonly string[];
|
|
158
|
-
readonly surfaceProjections: readonly
|
|
159
|
-
readonly derivedName: string;
|
|
160
|
-
readonly method: string | null;
|
|
161
|
-
readonly surface: string;
|
|
162
|
-
readonly trailId: string;
|
|
163
|
-
}[];
|
|
212
|
+
readonly surfaceProjections: readonly ShippedSurfaceProjection[];
|
|
164
213
|
readonly surfaces: readonly string[];
|
|
165
214
|
}
|
|
166
215
|
|
|
@@ -454,25 +503,158 @@ const trailActivationEdgesFromTopoGraph = (
|
|
|
454
503
|
topoGraph?.activationGraph.edges.filter((edge) => edge.trailId === trailId) ??
|
|
455
504
|
fallback;
|
|
456
505
|
|
|
457
|
-
const
|
|
506
|
+
const SHIPPED_SURFACES = ['cli', 'mcp', 'http'] as const;
|
|
507
|
+
|
|
508
|
+
const PLANNED_SURFACE_EXCLUSIONS = [
|
|
509
|
+
{
|
|
510
|
+
reason: 'WebSocket is planned, but no public package or API ships yet.',
|
|
511
|
+
status: 'planned' as const,
|
|
512
|
+
surface: 'websocket' as const,
|
|
513
|
+
},
|
|
514
|
+
] as const;
|
|
515
|
+
|
|
516
|
+
const surfaceOrder = (surface: ShippedSurfaceKey): number =>
|
|
517
|
+
SHIPPED_SURFACES.indexOf(surface);
|
|
518
|
+
|
|
519
|
+
const sortSurfaceProjections = (
|
|
520
|
+
projections: readonly ShippedSurfaceProjection[]
|
|
521
|
+
): readonly ShippedSurfaceProjection[] =>
|
|
522
|
+
projections.toSorted(
|
|
523
|
+
(a, b) =>
|
|
524
|
+
a.trailId.localeCompare(b.trailId) ||
|
|
525
|
+
surfaceOrder(a.surface) - surfaceOrder(b.surface)
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
const explicitSurfacesForEntry = (
|
|
458
529
|
entry: TopoGraphEntry | undefined
|
|
459
|
-
):
|
|
460
|
-
|
|
530
|
+
): readonly string[] => entry?.surfaces ?? [];
|
|
531
|
+
|
|
532
|
+
const projectionSource = (
|
|
533
|
+
entry: TopoGraphEntry | undefined,
|
|
534
|
+
surface: ShippedSurfaceKey
|
|
535
|
+
): SurfaceProjectionSource =>
|
|
536
|
+
explicitSurfacesForEntry(entry).includes(surface)
|
|
537
|
+
? 'authored'
|
|
538
|
+
: 'default-derived';
|
|
539
|
+
|
|
540
|
+
const deriveHttpPath = (trailId: string): string =>
|
|
541
|
+
`/${trailId.replaceAll('.', '/')}`;
|
|
542
|
+
|
|
543
|
+
const isSurfaceEligibleTrail = (app: Topo, trail: AnyTrail): boolean =>
|
|
544
|
+
filterSurfaceTrails([trail]).length > 0 &&
|
|
545
|
+
app.trails.get(trail.id) !== undefined;
|
|
546
|
+
|
|
547
|
+
export const deriveShippedSurfaceProjectionsForTrail = (
|
|
548
|
+
app: Topo,
|
|
549
|
+
trail: AnyTrail,
|
|
550
|
+
topoGraph?: TopoGraph | undefined
|
|
551
|
+
): readonly ShippedSurfaceProjection[] => {
|
|
552
|
+
if (!isSurfaceEligibleTrail(app, trail)) {
|
|
461
553
|
return [];
|
|
462
554
|
}
|
|
463
555
|
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
556
|
+
const entry = findTopoEntry(
|
|
557
|
+
topoGraph ?? deriveTopoGraph(app),
|
|
558
|
+
trail.id,
|
|
559
|
+
'trail'
|
|
560
|
+
);
|
|
561
|
+
const commandPath = deriveCliPath(trail.id);
|
|
562
|
+
const httpMethod = deriveHttpMethod(trail.intent);
|
|
563
|
+
const httpPath = deriveHttpPath(trail.id);
|
|
564
|
+
const mcpToolName = deriveToolName(app.name, trail.id);
|
|
565
|
+
|
|
566
|
+
return sortSurfaceProjections([
|
|
567
|
+
{
|
|
568
|
+
commandPath,
|
|
569
|
+
derivedName: commandPath.join(' '),
|
|
570
|
+
method: null,
|
|
571
|
+
source: projectionSource(entry, 'cli'),
|
|
572
|
+
surface: 'cli',
|
|
573
|
+
trailId: trail.id,
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
derivedName: mcpToolName,
|
|
577
|
+
method: null,
|
|
578
|
+
source: projectionSource(entry, 'mcp'),
|
|
579
|
+
surface: 'mcp',
|
|
580
|
+
toolName: mcpToolName,
|
|
581
|
+
trailId: trail.id,
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
derivedName: httpPath,
|
|
585
|
+
method: httpMethod,
|
|
586
|
+
path: httpPath,
|
|
587
|
+
source: projectionSource(entry, 'http'),
|
|
588
|
+
surface: 'http',
|
|
589
|
+
trailId: trail.id,
|
|
590
|
+
},
|
|
591
|
+
]);
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
const deriveFallbackSurfaceProjections = (
|
|
595
|
+
entry: TopoGraphEntry | undefined
|
|
596
|
+
): readonly ShippedSurfaceProjection[] => {
|
|
597
|
+
if (entry?.cli === undefined) {
|
|
598
|
+
return [];
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
return [
|
|
602
|
+
{
|
|
603
|
+
commandPath: entry.cli.path,
|
|
604
|
+
derivedName: entry.cli.path.join(' '),
|
|
605
|
+
method: null,
|
|
606
|
+
source: projectionSource(entry, 'cli'),
|
|
607
|
+
surface: 'cli',
|
|
608
|
+
trailId: entry.id,
|
|
609
|
+
},
|
|
610
|
+
];
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
export const deriveShippedSurfaceProjectionInventory = (
|
|
614
|
+
app: Topo
|
|
615
|
+
): ShippedSurfaceInventoryReport => {
|
|
616
|
+
const topoGraph = deriveTopoGraph(app);
|
|
617
|
+
const trails = filterSurfaceTrails(app.list()).map((trail) => {
|
|
618
|
+
const entry = findTopoEntry(topoGraph, trail.id, 'trail');
|
|
619
|
+
const projections = deriveShippedSurfaceProjectionsForTrail(
|
|
620
|
+
app,
|
|
621
|
+
trail,
|
|
622
|
+
topoGraph
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
return {
|
|
626
|
+
explicitSurfaces: explicitSurfacesForEntry(entry),
|
|
627
|
+
projections,
|
|
628
|
+
trailId: trail.id,
|
|
629
|
+
};
|
|
630
|
+
});
|
|
631
|
+
const projections = sortSurfaceProjections(
|
|
632
|
+
trails.flatMap((trail) => trail.projections)
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
return {
|
|
636
|
+
count: trails.length,
|
|
637
|
+
excludedSurfaces: PLANNED_SURFACE_EXCLUSIONS,
|
|
638
|
+
projections,
|
|
639
|
+
shippedSurfaces: SHIPPED_SURFACES,
|
|
640
|
+
trails: trails.toSorted((a, b) => a.trailId.localeCompare(b.trailId)),
|
|
641
|
+
};
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
const deriveResolvedSurfaceProjections = (
|
|
645
|
+
app: Topo | undefined,
|
|
646
|
+
trailId: string,
|
|
647
|
+
topoEntry: TopoGraphEntry | undefined,
|
|
648
|
+
topoGraph: TopoGraph | undefined
|
|
649
|
+
): readonly ShippedSurfaceProjection[] => {
|
|
650
|
+
if (app === undefined) {
|
|
651
|
+
return deriveFallbackSurfaceProjections(topoEntry);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const trail = app.trails.get(trailId);
|
|
655
|
+
return trail === undefined
|
|
656
|
+
? deriveFallbackSurfaceProjections(topoEntry)
|
|
657
|
+
: deriveShippedSurfaceProjectionsForTrail(app, trail, topoGraph);
|
|
476
658
|
};
|
|
477
659
|
|
|
478
660
|
const deriveResolvedTrailGraphDetail = (
|
|
@@ -525,7 +707,12 @@ const deriveResolvedTrailGraphDetail = (
|
|
|
525
707
|
input: topoEntry?.input ?? null,
|
|
526
708
|
layers: topoEntry?.layers ?? [],
|
|
527
709
|
output: topoEntry?.output ?? null,
|
|
528
|
-
surfaceProjections:
|
|
710
|
+
surfaceProjections: deriveResolvedSurfaceProjections(
|
|
711
|
+
app,
|
|
712
|
+
trailId,
|
|
713
|
+
topoEntry,
|
|
714
|
+
topoGraph
|
|
715
|
+
),
|
|
529
716
|
surfaces: topoEntry?.surfaces ?? [],
|
|
530
717
|
};
|
|
531
718
|
};
|