@lensmcp/protocol-types 1.17.0 → 1.17.2

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/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from './lib/event.js';
5
5
  export * from './lib/node.js';
6
6
  export * from './lib/edge.js';
7
7
  export * from './lib/attributes.js';
8
+ export * from './lib/producer-health.js';
8
9
  export * from './lib/resources.js';
9
10
  export * from './lib/tokens.js';
10
11
  export * from './lib/capture-demand.js';
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC"}
package/index.js CHANGED
@@ -5,6 +5,7 @@ export * from './lib/event.js';
5
5
  export * from './lib/node.js';
6
6
  export * from './lib/edge.js';
7
7
  export * from './lib/attributes.js';
8
+ export * from './lib/producer-health.js';
8
9
  export * from './lib/resources.js';
9
10
  export * from './lib/tokens.js';
10
11
  export * from './lib/capture-demand.js';
@@ -0,0 +1,136 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Producer health — the "is anybody actually watching?" half of every check
4
+ * resource (`typecheck://current`, `lint://current`, `build://current`).
5
+ *
6
+ * WHY this exists, concretely: `typecheck://current` shipped as
7
+ * `{"status":"unknown","errorCount":0,"revision":0}` and `lint://current` as
8
+ * `{"status":"unknown","errorCount":0,"warningCount":0,"revision":0}` — and an
9
+ * agent reading either one cannot tell those apart from a healthy, silent,
10
+ * genuinely-clean system. They were not clean. `startTscCollector` and
11
+ * `runEslintOnce` existed, were exported from `@lensmcp/session`, and were
12
+ * called by NOTHING; the dev cluster's real type checking (the tsgo plugin)
13
+ * printed diagnostics to the console and to no bus at all. So those resources
14
+ * had never received a single event in their lives, and said so in a way that
15
+ * read exactly like "all good".
16
+ *
17
+ * `revision: 0` was the only tell, and it is far too subtle to be a contract:
18
+ * one empty read teaches a reader to stop asking, which is precisely what
19
+ * happened. So every check resource now states, in the body, whether a
20
+ * producer has EVER reported (`producer`), which producers are live
21
+ * (`producers`), how old the newest report is (`ageMs`/`stale`), and a
22
+ * sentence a human or an agent can act on (`detail`).
23
+ *
24
+ * `status` keeps its original value set (`unknown | clean | …`) so existing
25
+ * readers — the MCP resource wrappers and the human dashboard — are unaffected;
26
+ * everything here is additive.
27
+ */
28
+ /**
29
+ * Has any producer ever reported into this resource?
30
+ *
31
+ * - `none` — no producer has ever reported. `status` is NOT evidence of
32
+ * health; nothing is watching. This is the state the three
33
+ * check resources were silently stuck in.
34
+ * - `connected` — at least one producer has reported at least once, so
35
+ * `status` reflects a real run.
36
+ *
37
+ * Deliberately NOT a third `stale` member: staleness is orthogonal (a
38
+ * connected producer that has not re-run recently is still connected), and
39
+ * folding it in here would force readers to re-derive "did anyone ever
40
+ * report?" from a union. Read `stale`/`ageMs` for freshness.
41
+ */
42
+ export declare const ProducerStateSchema: z.ZodEnum<{
43
+ none: "none";
44
+ connected: "connected";
45
+ }>;
46
+ export type ProducerState = z.infer<typeof ProducerStateSchema>;
47
+ /** Outcome of a producer's most recent run. */
48
+ export declare const ProducerRunStatusSchema: z.ZodEnum<{
49
+ error: "error";
50
+ running: "running";
51
+ clean: "clean";
52
+ failing: "failing";
53
+ }>;
54
+ export type ProducerRunStatus = z.infer<typeof ProducerRunStatusSchema>;
55
+ /**
56
+ * One reporting producer. Keyed by `id` so a multi-service cluster (13 pods,
57
+ * each running its own tsgo check against its own tsconfig, all appending to
58
+ * ONE `.lensmcp/events.jsonl`) shows up as 13 rows rather than a single
59
+ * last-writer-wins verdict.
60
+ */
61
+ export declare const ProducerReportSchema: z.ZodObject<{
62
+ id: z.ZodString;
63
+ tool: z.ZodString;
64
+ project: z.ZodOptional<z.ZodString>;
65
+ firstReportedAt: z.ZodNumber;
66
+ lastReportedAt: z.ZodNumber;
67
+ lastRunStatus: z.ZodEnum<{
68
+ error: "error";
69
+ running: "running";
70
+ clean: "clean";
71
+ failing: "failing";
72
+ }>;
73
+ lastRunDurationMs: z.ZodOptional<z.ZodNumber>;
74
+ errorCount: z.ZodNumber;
75
+ warningCount: z.ZodOptional<z.ZodNumber>;
76
+ error: z.ZodOptional<z.ZodString>;
77
+ }, z.core.$strip>;
78
+ export type ProducerReport = z.infer<typeof ProducerReportSchema>;
79
+ /**
80
+ * The additive block every check resource carries. Mixed into
81
+ * `typecheck://current`, `lint://current` and `build://current`.
82
+ */
83
+ export declare const ProducerHealthSchema: z.ZodObject<{
84
+ producer: z.ZodEnum<{
85
+ none: "none";
86
+ connected: "connected";
87
+ }>;
88
+ producers: z.ZodArray<z.ZodObject<{
89
+ id: z.ZodString;
90
+ tool: z.ZodString;
91
+ project: z.ZodOptional<z.ZodString>;
92
+ firstReportedAt: z.ZodNumber;
93
+ lastReportedAt: z.ZodNumber;
94
+ lastRunStatus: z.ZodEnum<{
95
+ error: "error";
96
+ running: "running";
97
+ clean: "clean";
98
+ failing: "failing";
99
+ }>;
100
+ lastRunDurationMs: z.ZodOptional<z.ZodNumber>;
101
+ errorCount: z.ZodNumber;
102
+ warningCount: z.ZodOptional<z.ZodNumber>;
103
+ error: z.ZodOptional<z.ZodString>;
104
+ }, z.core.$strip>>;
105
+ lastReportedAt: z.ZodOptional<z.ZodNumber>;
106
+ ageMs: z.ZodOptional<z.ZodNumber>;
107
+ stale: z.ZodBoolean;
108
+ detail: z.ZodString;
109
+ }, z.core.$strip>;
110
+ export type ProducerHealth = z.infer<typeof ProducerHealthSchema>;
111
+ /**
112
+ * A connected producer whose newest report is older than this is reported
113
+ * `stale`. Generous on purpose: these producers are edge-triggered (they run
114
+ * on rebuild / on demand), so silence is normal and is NOT evidence of a
115
+ * problem — it only means the verdict may predate the current source.
116
+ */
117
+ export declare const PRODUCER_STALE_AFTER_MS: number;
118
+ /**
119
+ * Fold a producer registry into the {@link ProducerHealth} block.
120
+ *
121
+ * Lives here rather than in each reducer so `typecheck`, `lint` and `build`
122
+ * cannot drift into three different definitions of "nobody is watching" — the
123
+ * exact class of divergence that let the original bug hide in two of the three.
124
+ *
125
+ * `now` is injected so the value is testable and so callers can pin one clock
126
+ * across a single resource render.
127
+ */
128
+ export declare function summariseProducers(args: {
129
+ producers: readonly ProducerReport[];
130
+ /** Domain label used in `detail`, e.g. `typecheck`. */
131
+ domain: string;
132
+ /** Appended to `detail` when there is no producer — how to get one. */
133
+ noProducerHint: string;
134
+ now?: number;
135
+ }): ProducerHealth;
136
+ //# sourceMappingURL=producer-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"producer-health.d.ts","sourceRoot":"","sources":["../../src/lib/producer-health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB;;;EAAgC,CAAC;AACjE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,+CAA+C;AAC/C,eAAO,MAAM,uBAAuB;;;;;EASlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;iBAe/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgB/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAAc,CAAC;AAEnD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,cAAc,CAuCjB"}
@@ -0,0 +1,154 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Producer health — the "is anybody actually watching?" half of every check
4
+ * resource (`typecheck://current`, `lint://current`, `build://current`).
5
+ *
6
+ * WHY this exists, concretely: `typecheck://current` shipped as
7
+ * `{"status":"unknown","errorCount":0,"revision":0}` and `lint://current` as
8
+ * `{"status":"unknown","errorCount":0,"warningCount":0,"revision":0}` — and an
9
+ * agent reading either one cannot tell those apart from a healthy, silent,
10
+ * genuinely-clean system. They were not clean. `startTscCollector` and
11
+ * `runEslintOnce` existed, were exported from `@lensmcp/session`, and were
12
+ * called by NOTHING; the dev cluster's real type checking (the tsgo plugin)
13
+ * printed diagnostics to the console and to no bus at all. So those resources
14
+ * had never received a single event in their lives, and said so in a way that
15
+ * read exactly like "all good".
16
+ *
17
+ * `revision: 0` was the only tell, and it is far too subtle to be a contract:
18
+ * one empty read teaches a reader to stop asking, which is precisely what
19
+ * happened. So every check resource now states, in the body, whether a
20
+ * producer has EVER reported (`producer`), which producers are live
21
+ * (`producers`), how old the newest report is (`ageMs`/`stale`), and a
22
+ * sentence a human or an agent can act on (`detail`).
23
+ *
24
+ * `status` keeps its original value set (`unknown | clean | …`) so existing
25
+ * readers — the MCP resource wrappers and the human dashboard — are unaffected;
26
+ * everything here is additive.
27
+ */
28
+ /**
29
+ * Has any producer ever reported into this resource?
30
+ *
31
+ * - `none` — no producer has ever reported. `status` is NOT evidence of
32
+ * health; nothing is watching. This is the state the three
33
+ * check resources were silently stuck in.
34
+ * - `connected` — at least one producer has reported at least once, so
35
+ * `status` reflects a real run.
36
+ *
37
+ * Deliberately NOT a third `stale` member: staleness is orthogonal (a
38
+ * connected producer that has not re-run recently is still connected), and
39
+ * folding it in here would force readers to re-derive "did anyone ever
40
+ * report?" from a union. Read `stale`/`ageMs` for freshness.
41
+ */
42
+ export const ProducerStateSchema = z.enum(['none', 'connected']);
43
+ /** Outcome of a producer's most recent run. */
44
+ export const ProducerRunStatusSchema = z.enum([
45
+ /** A run is in flight; its diagnostics have not landed yet. */
46
+ 'running',
47
+ /** The run completed with zero errors. */
48
+ 'clean',
49
+ /** The run completed and reported at least one error. */
50
+ 'failing',
51
+ /** The tool itself failed to run (crash / bad config) — the run produced NO verdict. */
52
+ 'error',
53
+ ]);
54
+ /**
55
+ * One reporting producer. Keyed by `id` so a multi-service cluster (13 pods,
56
+ * each running its own tsgo check against its own tsconfig, all appending to
57
+ * ONE `.lensmcp/events.jsonl`) shows up as 13 rows rather than a single
58
+ * last-writer-wins verdict.
59
+ */
60
+ export const ProducerReportSchema = z.object({
61
+ /** Stable identity: `<tool>:<project ?? '*'>`. */
62
+ id: z.string(),
63
+ /** The tool behind it — `tsgo`, `tsc`, `eslint`, `vite`, … */
64
+ tool: z.string(),
65
+ /** Nx project the run covered; absent for a workspace-wide producer. */
66
+ project: z.string().optional(),
67
+ firstReportedAt: z.number().int().nonnegative(),
68
+ lastReportedAt: z.number().int().nonnegative(),
69
+ lastRunStatus: ProducerRunStatusSchema,
70
+ lastRunDurationMs: z.number().int().nonnegative().optional(),
71
+ errorCount: z.number().int().nonnegative(),
72
+ warningCount: z.number().int().nonnegative().optional(),
73
+ /** Set when `lastRunStatus === 'error'` — why the tool could not produce a verdict. */
74
+ error: z.string().optional(),
75
+ });
76
+ /**
77
+ * The additive block every check resource carries. Mixed into
78
+ * `typecheck://current`, `lint://current` and `build://current`.
79
+ */
80
+ export const ProducerHealthSchema = z.object({
81
+ producer: ProducerStateSchema,
82
+ producers: z.array(ProducerReportSchema),
83
+ /** Epoch ms of the newest report across all producers. Absent iff `producer === 'none'`. */
84
+ lastReportedAt: z.number().int().nonnegative().optional(),
85
+ /** Age of `lastReportedAt` at read time. Absent iff `producer === 'none'`. */
86
+ ageMs: z.number().int().nonnegative().optional(),
87
+ /**
88
+ * `true` when connected but the newest report is older than
89
+ * {@link PRODUCER_STALE_AFTER_MS}. A stale CLEAN result means "clean as of
90
+ * `ageMs` ago, and nothing has re-checked since" — not "clean now".
91
+ * Always `false` when `producer === 'none'` (nothing to be stale).
92
+ */
93
+ stale: z.boolean(),
94
+ /** One sentence a reader can act on. Never empty. */
95
+ detail: z.string(),
96
+ });
97
+ /**
98
+ * A connected producer whose newest report is older than this is reported
99
+ * `stale`. Generous on purpose: these producers are edge-triggered (they run
100
+ * on rebuild / on demand), so silence is normal and is NOT evidence of a
101
+ * problem — it only means the verdict may predate the current source.
102
+ */
103
+ export const PRODUCER_STALE_AFTER_MS = 10 * 60_000;
104
+ /**
105
+ * Fold a producer registry into the {@link ProducerHealth} block.
106
+ *
107
+ * Lives here rather than in each reducer so `typecheck`, `lint` and `build`
108
+ * cannot drift into three different definitions of "nobody is watching" — the
109
+ * exact class of divergence that let the original bug hide in two of the three.
110
+ *
111
+ * `now` is injected so the value is testable and so callers can pin one clock
112
+ * across a single resource render.
113
+ */
114
+ export function summariseProducers(args) {
115
+ const now = args.now ?? Date.now();
116
+ const producers = [...args.producers].sort((a, b) => b.lastReportedAt - a.lastReportedAt);
117
+ if (producers.length === 0) {
118
+ return {
119
+ producer: 'none',
120
+ producers: [],
121
+ stale: false,
122
+ detail: `No ${args.domain} producer has ever reported into this session — ` +
123
+ `this is NOT a clean result, nothing is watching. ${args.noProducerHint}`,
124
+ };
125
+ }
126
+ const lastReportedAt = producers[0].lastReportedAt;
127
+ const ageMs = Math.max(0, now - lastReportedAt);
128
+ const stale = ageMs > PRODUCER_STALE_AFTER_MS;
129
+ const failing = producers.filter((p) => p.lastRunStatus === 'failing');
130
+ const errored = producers.filter((p) => p.lastRunStatus === 'error');
131
+ const parts = [
132
+ `${producers.length} ${args.domain} producer${producers.length === 1 ? '' : 's'} reporting ` +
133
+ `(${producers.map((p) => p.id).join(', ')}); newest report ${describeAge(ageMs)}.`,
134
+ ];
135
+ if (errored.length > 0) {
136
+ parts.push(`${errored.length} produced NO verdict (the tool itself failed): ` +
137
+ `${errored.map((p) => `${p.id} — ${p.error ?? 'unknown error'}`).join('; ')}.`);
138
+ }
139
+ if (failing.length > 0)
140
+ parts.push(`${failing.length} reporting errors.`);
141
+ if (stale) {
142
+ parts.push(`Older than ${Math.round(PRODUCER_STALE_AFTER_MS / 60_000)}m — the verdict may predate the current source.`);
143
+ }
144
+ return { producer: 'connected', producers, lastReportedAt, ageMs, stale, detail: parts.join(' ') };
145
+ }
146
+ function describeAge(ageMs) {
147
+ if (ageMs < 1_000)
148
+ return 'just now';
149
+ if (ageMs < 60_000)
150
+ return `${Math.round(ageMs / 1_000)}s ago`;
151
+ if (ageMs < 3_600_000)
152
+ return `${Math.round(ageMs / 60_000)}m ago`;
153
+ return `${Math.round(ageMs / 3_600_000)}h ago`;
154
+ }
@@ -13,19 +13,19 @@ export declare const ResourceEnvelopeSchema: z.ZodObject<{
13
13
  }, z.core.$strip>;
14
14
  export type ResourceEnvelope = z.infer<typeof ResourceEnvelopeSchema>;
15
15
  export declare const AgentStatusKindSchema: z.ZodEnum<{
16
- starting: "starting";
17
- clean: "clean";
18
16
  warning: "warning";
17
+ clean: "clean";
19
18
  failing: "failing";
19
+ starting: "starting";
20
20
  }>;
21
21
  export type AgentStatusKind = z.infer<typeof AgentStatusKindSchema>;
22
22
  export declare const AgentBlockingItemSchema: z.ZodObject<{
23
23
  source: z.ZodString;
24
24
  severity: z.ZodEnum<{
25
25
  error: "error";
26
- warning: "warning";
27
26
  debug: "debug";
28
27
  info: "info";
28
+ warning: "warning";
29
29
  fatal: "fatal";
30
30
  }>;
31
31
  title: z.ZodString;
@@ -45,37 +45,37 @@ export declare const AgentBlockingItemSchema: z.ZodObject<{
45
45
  export type AgentBlockingItem = z.infer<typeof AgentBlockingItemSchema>;
46
46
  export declare const AgentChecksSchema: z.ZodObject<{
47
47
  typecheck: z.ZodOptional<z.ZodEnum<{
48
+ unknown: "unknown";
48
49
  passed: "passed";
49
50
  failed: "failed";
50
- unknown: "unknown";
51
51
  }>>;
52
52
  lint: z.ZodOptional<z.ZodEnum<{
53
+ unknown: "unknown";
53
54
  passed: "passed";
54
55
  failed: "failed";
55
- unknown: "unknown";
56
56
  }>>;
57
57
  build: z.ZodOptional<z.ZodEnum<{
58
+ unknown: "unknown";
58
59
  passed: "passed";
59
60
  failed: "failed";
60
- unknown: "unknown";
61
61
  }>>;
62
62
  runtime: z.ZodOptional<z.ZodEnum<{
63
63
  warning: "warning";
64
+ unknown: "unknown";
64
65
  passed: "passed";
65
66
  failed: "failed";
66
- unknown: "unknown";
67
67
  }>>;
68
68
  visual: z.ZodOptional<z.ZodEnum<{
69
69
  warning: "warning";
70
+ unknown: "unknown";
70
71
  passed: "passed";
71
72
  failed: "failed";
72
- unknown: "unknown";
73
73
  }>>;
74
74
  memory: z.ZodOptional<z.ZodEnum<{
75
75
  warning: "warning";
76
+ unknown: "unknown";
76
77
  passed: "passed";
77
78
  failed: "failed";
78
- unknown: "unknown";
79
79
  }>>;
80
80
  }, z.core.$strip>;
81
81
  export declare const AgentCurrentStatusSchema: z.ZodObject<{
@@ -85,10 +85,10 @@ export declare const AgentCurrentStatusSchema: z.ZodObject<{
85
85
  updatedAt: z.ZodOptional<z.ZodString>;
86
86
  sessionId: z.ZodString;
87
87
  status: z.ZodEnum<{
88
- starting: "starting";
89
- clean: "clean";
90
88
  warning: "warning";
89
+ clean: "clean";
91
90
  failing: "failing";
91
+ starting: "starting";
92
92
  }>;
93
93
  activeTab: z.ZodOptional<z.ZodString>;
94
94
  tabsWithIssues: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -96,9 +96,9 @@ export declare const AgentCurrentStatusSchema: z.ZodObject<{
96
96
  source: z.ZodString;
97
97
  severity: z.ZodEnum<{
98
98
  error: "error";
99
- warning: "warning";
100
99
  debug: "debug";
101
100
  info: "info";
101
+ warning: "warning";
102
102
  fatal: "fatal";
103
103
  }>;
104
104
  title: z.ZodString;
@@ -119,9 +119,9 @@ export declare const AgentCurrentStatusSchema: z.ZodObject<{
119
119
  source: z.ZodString;
120
120
  severity: z.ZodEnum<{
121
121
  error: "error";
122
- warning: "warning";
123
122
  debug: "debug";
124
123
  info: "info";
124
+ warning: "warning";
125
125
  fatal: "fatal";
126
126
  }>;
127
127
  title: z.ZodString;
@@ -141,37 +141,37 @@ export declare const AgentCurrentStatusSchema: z.ZodObject<{
141
141
  suggestedReads: z.ZodArray<z.ZodString>;
142
142
  checks: z.ZodOptional<z.ZodObject<{
143
143
  typecheck: z.ZodOptional<z.ZodEnum<{
144
+ unknown: "unknown";
144
145
  passed: "passed";
145
146
  failed: "failed";
146
- unknown: "unknown";
147
147
  }>>;
148
148
  lint: z.ZodOptional<z.ZodEnum<{
149
+ unknown: "unknown";
149
150
  passed: "passed";
150
151
  failed: "failed";
151
- unknown: "unknown";
152
152
  }>>;
153
153
  build: z.ZodOptional<z.ZodEnum<{
154
+ unknown: "unknown";
154
155
  passed: "passed";
155
156
  failed: "failed";
156
- unknown: "unknown";
157
157
  }>>;
158
158
  runtime: z.ZodOptional<z.ZodEnum<{
159
159
  warning: "warning";
160
+ unknown: "unknown";
160
161
  passed: "passed";
161
162
  failed: "failed";
162
- unknown: "unknown";
163
163
  }>>;
164
164
  visual: z.ZodOptional<z.ZodEnum<{
165
165
  warning: "warning";
166
+ unknown: "unknown";
166
167
  passed: "passed";
167
168
  failed: "failed";
168
- unknown: "unknown";
169
169
  }>>;
170
170
  memory: z.ZodOptional<z.ZodEnum<{
171
171
  warning: "warning";
172
+ unknown: "unknown";
172
173
  passed: "passed";
173
174
  failed: "failed";
174
- unknown: "unknown";
175
175
  }>>;
176
176
  }, z.core.$strip>>;
177
177
  }, z.core.$strip>;
@@ -248,4 +248,205 @@ export declare const AgentSessionSchema: z.ZodObject<{
248
248
  }, z.core.$strip>>;
249
249
  }, z.core.$strip>;
250
250
  export type AgentSession = z.infer<typeof AgentSessionSchema>;
251
+ /**
252
+ * The three "is my code OK?" resources: an envelope + a status + counts + the
253
+ * {@link ProducerHealthSchema} block.
254
+ *
255
+ * The producer block is what makes `status` legible. Without it,
256
+ * `{"status":"unknown","errorCount":0,"revision":0}` is ambiguous between
257
+ * "checked, nothing wrong" and "nothing has ever checked" — and for
258
+ * `typecheck://` and `lint://` it was always the second, because neither had a
259
+ * producer wired at all. Read `producer` BEFORE trusting `status`.
260
+ */
261
+ declare const CheckEntrySchema: z.ZodObject<{
262
+ id: z.ZodString;
263
+ timestamp: z.ZodNumber;
264
+ message: z.ZodString;
265
+ fingerprint: z.ZodString;
266
+ code: z.ZodOptional<z.ZodString>;
267
+ rule: z.ZodOptional<z.ZodString>;
268
+ severity: z.ZodOptional<z.ZodEnum<{
269
+ error: "error";
270
+ debug: "debug";
271
+ info: "info";
272
+ warning: "warning";
273
+ fatal: "fatal";
274
+ }>>;
275
+ file: z.ZodOptional<z.ZodString>;
276
+ line: z.ZodOptional<z.ZodNumber>;
277
+ column: z.ZodOptional<z.ZodNumber>;
278
+ project: z.ZodOptional<z.ZodString>;
279
+ }, z.core.$strip>;
280
+ export type CheckEntry = z.infer<typeof CheckEntrySchema>;
281
+ export declare const TypecheckCurrentSchema: z.ZodObject<{
282
+ $schema: z.ZodOptional<z.ZodString>;
283
+ schemaVersion: z.ZodLiteral<1>;
284
+ revision: z.ZodNumber;
285
+ updatedAt: z.ZodOptional<z.ZodString>;
286
+ producer: z.ZodEnum<{
287
+ none: "none";
288
+ connected: "connected";
289
+ }>;
290
+ producers: z.ZodArray<z.ZodObject<{
291
+ id: z.ZodString;
292
+ tool: z.ZodString;
293
+ project: z.ZodOptional<z.ZodString>;
294
+ firstReportedAt: z.ZodNumber;
295
+ lastReportedAt: z.ZodNumber;
296
+ lastRunStatus: z.ZodEnum<{
297
+ error: "error";
298
+ running: "running";
299
+ clean: "clean";
300
+ failing: "failing";
301
+ }>;
302
+ lastRunDurationMs: z.ZodOptional<z.ZodNumber>;
303
+ errorCount: z.ZodNumber;
304
+ warningCount: z.ZodOptional<z.ZodNumber>;
305
+ error: z.ZodOptional<z.ZodString>;
306
+ }, z.core.$strip>>;
307
+ lastReportedAt: z.ZodOptional<z.ZodNumber>;
308
+ ageMs: z.ZodOptional<z.ZodNumber>;
309
+ stale: z.ZodBoolean;
310
+ detail: z.ZodString;
311
+ status: z.ZodEnum<{
312
+ unknown: "unknown";
313
+ clean: "clean";
314
+ failing: "failing";
315
+ }>;
316
+ errorCount: z.ZodNumber;
317
+ lastRunAt: z.ZodOptional<z.ZodNumber>;
318
+ }, z.core.$strip>;
319
+ export type TypecheckCurrent = z.infer<typeof TypecheckCurrentSchema>;
320
+ export declare const TypecheckErrorsSchema: z.ZodObject<{
321
+ $schema: z.ZodOptional<z.ZodString>;
322
+ schemaVersion: z.ZodLiteral<1>;
323
+ revision: z.ZodNumber;
324
+ updatedAt: z.ZodOptional<z.ZodString>;
325
+ producer: z.ZodEnum<{
326
+ none: "none";
327
+ connected: "connected";
328
+ }>;
329
+ producers: z.ZodArray<z.ZodObject<{
330
+ id: z.ZodString;
331
+ tool: z.ZodString;
332
+ project: z.ZodOptional<z.ZodString>;
333
+ firstReportedAt: z.ZodNumber;
334
+ lastReportedAt: z.ZodNumber;
335
+ lastRunStatus: z.ZodEnum<{
336
+ error: "error";
337
+ running: "running";
338
+ clean: "clean";
339
+ failing: "failing";
340
+ }>;
341
+ lastRunDurationMs: z.ZodOptional<z.ZodNumber>;
342
+ errorCount: z.ZodNumber;
343
+ warningCount: z.ZodOptional<z.ZodNumber>;
344
+ error: z.ZodOptional<z.ZodString>;
345
+ }, z.core.$strip>>;
346
+ lastReportedAt: z.ZodOptional<z.ZodNumber>;
347
+ ageMs: z.ZodOptional<z.ZodNumber>;
348
+ stale: z.ZodBoolean;
349
+ detail: z.ZodString;
350
+ errors: z.ZodArray<z.ZodObject<{
351
+ id: z.ZodString;
352
+ timestamp: z.ZodNumber;
353
+ message: z.ZodString;
354
+ fingerprint: z.ZodString;
355
+ code: z.ZodOptional<z.ZodString>;
356
+ rule: z.ZodOptional<z.ZodString>;
357
+ severity: z.ZodOptional<z.ZodEnum<{
358
+ error: "error";
359
+ debug: "debug";
360
+ info: "info";
361
+ warning: "warning";
362
+ fatal: "fatal";
363
+ }>>;
364
+ file: z.ZodOptional<z.ZodString>;
365
+ line: z.ZodOptional<z.ZodNumber>;
366
+ column: z.ZodOptional<z.ZodNumber>;
367
+ project: z.ZodOptional<z.ZodString>;
368
+ }, z.core.$strip>>;
369
+ }, z.core.$strip>;
370
+ export type TypecheckErrors = z.infer<typeof TypecheckErrorsSchema>;
371
+ export declare const LintCurrentSchema: z.ZodObject<{
372
+ $schema: z.ZodOptional<z.ZodString>;
373
+ schemaVersion: z.ZodLiteral<1>;
374
+ revision: z.ZodNumber;
375
+ updatedAt: z.ZodOptional<z.ZodString>;
376
+ producer: z.ZodEnum<{
377
+ none: "none";
378
+ connected: "connected";
379
+ }>;
380
+ producers: z.ZodArray<z.ZodObject<{
381
+ id: z.ZodString;
382
+ tool: z.ZodString;
383
+ project: z.ZodOptional<z.ZodString>;
384
+ firstReportedAt: z.ZodNumber;
385
+ lastReportedAt: z.ZodNumber;
386
+ lastRunStatus: z.ZodEnum<{
387
+ error: "error";
388
+ running: "running";
389
+ clean: "clean";
390
+ failing: "failing";
391
+ }>;
392
+ lastRunDurationMs: z.ZodOptional<z.ZodNumber>;
393
+ errorCount: z.ZodNumber;
394
+ warningCount: z.ZodOptional<z.ZodNumber>;
395
+ error: z.ZodOptional<z.ZodString>;
396
+ }, z.core.$strip>>;
397
+ lastReportedAt: z.ZodOptional<z.ZodNumber>;
398
+ ageMs: z.ZodOptional<z.ZodNumber>;
399
+ stale: z.ZodBoolean;
400
+ detail: z.ZodString;
401
+ status: z.ZodEnum<{
402
+ warning: "warning";
403
+ unknown: "unknown";
404
+ clean: "clean";
405
+ failing: "failing";
406
+ }>;
407
+ errorCount: z.ZodNumber;
408
+ warningCount: z.ZodNumber;
409
+ lastRunAt: z.ZodOptional<z.ZodNumber>;
410
+ }, z.core.$strip>;
411
+ export type LintCurrent = z.infer<typeof LintCurrentSchema>;
412
+ export declare const BuildCurrentSchema: z.ZodObject<{
413
+ $schema: z.ZodOptional<z.ZodString>;
414
+ schemaVersion: z.ZodLiteral<1>;
415
+ revision: z.ZodNumber;
416
+ updatedAt: z.ZodOptional<z.ZodString>;
417
+ producer: z.ZodEnum<{
418
+ none: "none";
419
+ connected: "connected";
420
+ }>;
421
+ producers: z.ZodArray<z.ZodObject<{
422
+ id: z.ZodString;
423
+ tool: z.ZodString;
424
+ project: z.ZodOptional<z.ZodString>;
425
+ firstReportedAt: z.ZodNumber;
426
+ lastReportedAt: z.ZodNumber;
427
+ lastRunStatus: z.ZodEnum<{
428
+ error: "error";
429
+ running: "running";
430
+ clean: "clean";
431
+ failing: "failing";
432
+ }>;
433
+ lastRunDurationMs: z.ZodOptional<z.ZodNumber>;
434
+ errorCount: z.ZodNumber;
435
+ warningCount: z.ZodOptional<z.ZodNumber>;
436
+ error: z.ZodOptional<z.ZodString>;
437
+ }, z.core.$strip>>;
438
+ lastReportedAt: z.ZodOptional<z.ZodNumber>;
439
+ ageMs: z.ZodOptional<z.ZodNumber>;
440
+ stale: z.ZodBoolean;
441
+ detail: z.ZodString;
442
+ status: z.ZodEnum<{
443
+ warning: "warning";
444
+ unknown: "unknown";
445
+ clean: "clean";
446
+ failing: "failing";
447
+ }>;
448
+ hmrUpdates: z.ZodNumber;
449
+ }, z.core.$strip>;
450
+ export type BuildCurrent = z.infer<typeof BuildCurrentSchema>;
451
+ export {};
251
452
  //# sourceMappingURL=resources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/lib/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;GAGG;AACH,eAAO,MAAM,WAAW,+OAyBd,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAIrD,eAAO,MAAM,sBAAsB;;;;;iBAKjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;iBASlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAO5B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;iBAmBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkB7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/lib/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;GAGG;AACH,eAAO,MAAM,WAAW,+OAyBd,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAIrD,eAAO,MAAM,sBAAsB;;;;;iBAKjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;iBASlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAO5B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAI1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;iBAmBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkB7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;;;;;;;;GASG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;iBAYpB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAK5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
package/lib/resources.js CHANGED
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  import { SCHEMA_VERSION } from './schema-version.js';
3
3
  import { SourceLocationSchema } from './source-location.js';
4
4
  import { SeveritySchema } from './event.js';
5
+ import { ProducerHealthSchema } from './producer-health.js';
5
6
  /**
6
7
  * Well-known URI schemes used by LensMCP. See `planning/03-mcp-surface.md`.
7
8
  * Each scheme maps 1:1 to a FrontMCP @App package.
@@ -108,6 +109,7 @@ export const AgentStorageStatsSchema = z.object({
108
109
  /** The per-event `raw` limit in force. */
109
110
  rawByteLimit: z.number().int().nonnegative().optional(),
110
111
  });
112
+ // -------- agent://session --------
111
113
  export const AgentSessionSchema = ResourceEnvelopeSchema.extend({
112
114
  sessionId: z.string(),
113
115
  supportedResources: z.array(z.string()),
@@ -127,3 +129,45 @@ export const AgentSessionSchema = ResourceEnvelopeSchema.extend({
127
129
  /** Optional — absent when the backend reports no stats. */
128
130
  storage: AgentStorageStatsSchema.optional(),
129
131
  });
132
+ // -------- the check resources: typecheck:// · lint:// · build:// --------
133
+ /**
134
+ * The three "is my code OK?" resources: an envelope + a status + counts + the
135
+ * {@link ProducerHealthSchema} block.
136
+ *
137
+ * The producer block is what makes `status` legible. Without it,
138
+ * `{"status":"unknown","errorCount":0,"revision":0}` is ambiguous between
139
+ * "checked, nothing wrong" and "nothing has ever checked" — and for
140
+ * `typecheck://` and `lint://` it was always the second, because neither had a
141
+ * producer wired at all. Read `producer` BEFORE trusting `status`.
142
+ */
143
+ const CheckEntrySchema = z.object({
144
+ id: z.string(),
145
+ timestamp: z.number().int().nonnegative(),
146
+ message: z.string(),
147
+ fingerprint: z.string(),
148
+ code: z.string().optional(),
149
+ rule: z.string().optional(),
150
+ severity: SeveritySchema.optional(),
151
+ file: z.string().optional(),
152
+ line: z.number().int().nonnegative().optional(),
153
+ column: z.number().int().nonnegative().optional(),
154
+ project: z.string().optional(),
155
+ });
156
+ export const TypecheckCurrentSchema = ResourceEnvelopeSchema.merge(ProducerHealthSchema).extend({
157
+ status: z.enum(['unknown', 'clean', 'failing']),
158
+ errorCount: z.number().int().nonnegative(),
159
+ lastRunAt: z.number().int().nonnegative().optional(),
160
+ });
161
+ export const TypecheckErrorsSchema = ResourceEnvelopeSchema.merge(ProducerHealthSchema).extend({
162
+ errors: z.array(CheckEntrySchema),
163
+ });
164
+ export const LintCurrentSchema = ResourceEnvelopeSchema.merge(ProducerHealthSchema).extend({
165
+ status: z.enum(['unknown', 'clean', 'warning', 'failing']),
166
+ errorCount: z.number().int().nonnegative(),
167
+ warningCount: z.number().int().nonnegative(),
168
+ lastRunAt: z.number().int().nonnegative().optional(),
169
+ });
170
+ export const BuildCurrentSchema = ResourceEnvelopeSchema.merge(ProducerHealthSchema).extend({
171
+ status: z.enum(['unknown', 'clean', 'warning', 'failing']),
172
+ hmrUpdates: z.number().int().nonnegative(),
173
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/protocol-types",
3
- "version": "1.17.0",
3
+ "version": "1.17.2",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",