@pitcher/cli-scripts 3.1.1 → 3.3.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/README.md +39 -2
- package/dist/index.js +2 -0
- package/dist/src/commands/analytics.d.ts +77 -0
- package/dist/src/commands/analytics.js +309 -1
- package/dist/src/commands/dsrLanding.js +1 -1
- package/dist/src/commands/roleplay.d.ts +236 -0
- package/dist/src/commands/roleplay.js +702 -0
- package/dist/src/core/dsr-engagement.d.ts +152 -0
- package/dist/src/core/dsr-engagement.js +301 -0
- package/dist/src/core/dsr-visits.d.ts +50 -0
- package/dist/src/core/dsr-visits.js +191 -0
- package/dist/src/core/envelope.d.ts +1 -0
- package/dist/src/core/envelope.js +6 -1
- package/dist/src/core/errors.d.ts +3 -1
- package/dist/src/core/errors.js +2 -2
- package/dist/src/core/http.js +7 -5
- package/dist/src/core/ld.js +2 -1
- package/dist/src/core/me.d.ts +3 -0
- package/dist/src/core/me.js +10 -0
- package/dist/src/core/roleplay-stats.d.ts +120 -0
- package/dist/src/core/roleplay-stats.js +171 -0
- package/dist/src/mcp/apps/confirm/define.d.ts +66 -0
- package/dist/src/mcp/apps/confirm/define.js +208 -0
- package/dist/src/mcp/apps/confirm/hash.d.ts +4 -0
- package/dist/src/mcp/apps/confirm/hash.js +23 -0
- package/dist/src/mcp/apps/confirm/types.d.ts +96 -0
- package/dist/src/mcp/apps/confirm/types.js +15 -0
- package/dist/src/mcp/apps/contentPicker.d.ts +104 -0
- package/dist/src/mcp/apps/contentPicker.js +268 -0
- package/dist/src/mcp/apps/dsrEngagement.d.ts +194 -0
- package/dist/src/mcp/apps/dsrEngagement.js +737 -0
- package/dist/src/mcp/apps/registry.d.ts +14 -0
- package/dist/src/mcp/apps/registry.js +25 -0
- package/dist/src/mcp/apps/roleplayManager.d.ts +228 -0
- package/dist/src/mcp/apps/roleplayManager.js +606 -0
- package/dist/src/mcp/apps/roleplayReps.d.ts +79 -0
- package/dist/src/mcp/apps/roleplayReps.js +328 -0
- package/dist/src/mcp/apps/roleplayWrites.d.ts +6 -0
- package/dist/src/mcp/apps/roleplayWrites.js +509 -0
- package/dist/src/mcp/apps/text.d.ts +41 -0
- package/dist/src/mcp/apps/text.js +58 -0
- package/dist/src/mcp/apps/types.d.ts +23 -0
- package/dist/src/mcp/apps/types.js +12 -0
- package/dist/src/mcp/apps/writeConfirm.d.ts +3 -0
- package/dist/src/mcp/apps/writeConfirm.js +8 -0
- package/dist/src/mcp/groups.d.ts +42 -0
- package/dist/src/mcp/groups.js +89 -0
- package/dist/src/mcp/hosted.d.ts +36 -0
- package/dist/src/mcp/hosted.js +47 -1
- package/dist/src/mcp/index.d.ts +9 -3
- package/dist/src/mcp/index.js +9 -2
- package/dist/src/mcp/prompts/registry.js +8 -7
- package/dist/src/mcp/prompts/types.d.ts +3 -0
- package/dist/src/mcp/registry.d.ts +4 -0
- package/dist/src/mcp/registry.js +30 -23
- package/dist/src/mcp/renderPolicy.d.ts +2 -1
- package/dist/src/mcp/renderPolicy.js +10 -3
- package/dist/src/mcp/resources/analyticsCatalog.d.ts +1 -1
- package/dist/src/mcp/resources/analyticsCatalog.js +23 -5
- package/dist/src/mcp/resources/registry.js +2 -2
- package/dist/src/mcp/resources/types.d.ts +3 -0
- package/dist/src/mcp/result.d.ts +2 -1
- package/dist/src/mcp/result.js +8 -6
- package/dist/src/mcp/server.d.ts +62 -0
- package/dist/src/mcp/server.js +161 -10
- package/dist/src/mcp/tools/analytics.js +88 -3
- package/dist/src/mcp/tools/roleplay.d.ts +2 -0
- package/dist/src/mcp/tools/roleplay.js +135 -0
- package/dist/src/mcp/tools/types.d.ts +35 -0
- package/package.json +7 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ToolDescriptor } from '../tools/types.js';
|
|
2
|
+
import type { AppViewDescriptor } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* MCP Apps registry (PIT-10066). Kept apart from `allTools` on purpose: app tools compose several run*
|
|
5
|
+
* functions and are not CLI commands, so the CLI registry guards (134 tools, one run* each) stay untouched.
|
|
6
|
+
* A follow-up view adds its descriptor and tools here and nowhere else on the server side.
|
|
7
|
+
*/
|
|
8
|
+
export declare const allAppViews: AppViewDescriptor[];
|
|
9
|
+
/**
|
|
10
|
+
* App tools carry their group on the descriptor (roleplay manager `roleplay`, DSR engagement `analytics`); the content
|
|
11
|
+
* picker module is assigned `content` here. `checkDescriptor` runs on every entry: it is the only guard for tools that
|
|
12
|
+
* set their own group (PIT-10113 confirm tools included). Every app tool must declare `access` explicitly.
|
|
13
|
+
*/
|
|
14
|
+
export declare const allAppTools: ToolDescriptor[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { checkDescriptor, inGroup } from '../groups.js';
|
|
2
|
+
import { contentPickerView, contentPickerTools } from './contentPicker.js';
|
|
3
|
+
import { dsrEngagementView, dsrEngagementTools } from './dsrEngagement.js';
|
|
4
|
+
import { roleplayManagerView, roleplayManagerTools } from './roleplayManager.js';
|
|
5
|
+
import { roleplayRepsTools } from './roleplayReps.js';
|
|
6
|
+
import { roleplayWriteTools } from './roleplayWrites.js';
|
|
7
|
+
import { writeConfirmView } from './writeConfirm.js';
|
|
8
|
+
/**
|
|
9
|
+
* MCP Apps registry (PIT-10066). Kept apart from `allTools` on purpose: app tools compose several run*
|
|
10
|
+
* functions and are not CLI commands, so the CLI registry guards (134 tools, one run* each) stay untouched.
|
|
11
|
+
* A follow-up view adds its descriptor and tools here and nowhere else on the server side.
|
|
12
|
+
*/
|
|
13
|
+
export const allAppViews = [contentPickerView, roleplayManagerView, dsrEngagementView, writeConfirmView];
|
|
14
|
+
/**
|
|
15
|
+
* App tools carry their group on the descriptor (roleplay manager `roleplay`, DSR engagement `analytics`); the content
|
|
16
|
+
* picker module is assigned `content` here. `checkDescriptor` runs on every entry: it is the only guard for tools that
|
|
17
|
+
* set their own group (PIT-10113 confirm tools included). Every app tool must declare `access` explicitly.
|
|
18
|
+
*/
|
|
19
|
+
export const allAppTools = [
|
|
20
|
+
...inGroup('content', contentPickerTools),
|
|
21
|
+
...roleplayManagerTools,
|
|
22
|
+
...roleplayRepsTools, // PIT-10116: the Reps tab of the roleplay manager view
|
|
23
|
+
...dsrEngagementTools,
|
|
24
|
+
...roleplayWriteTools,
|
|
25
|
+
].map(checkDescriptor);
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import type { AxiosInstance } from 'axios';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { type CoachAssignment, type CoachScope, type CoachSession, type Coverage, type TeamModel } from '../../commands/roleplay.js';
|
|
4
|
+
import { type Envelope } from '../../core/envelope.js';
|
|
5
|
+
import { type CommonOpts } from '../../core/http.js';
|
|
6
|
+
import { type LatestSkill, type RepStatus } from '../../core/roleplay-stats.js';
|
|
7
|
+
import type { ToolDescriptor } from '../tools/types.js';
|
|
8
|
+
import { type FitTextInput } from './text.js';
|
|
9
|
+
import type { AppViewDescriptor } from './types.js';
|
|
10
|
+
export type { Coverage } from '../../commands/roleplay.js';
|
|
11
|
+
export type { LatestSkill, RepStatus } from '../../core/roleplay-stats.js';
|
|
12
|
+
/**
|
|
13
|
+
* MCP Apps AI Roleplay manager view (PIT-10068): a KPI header and the assignment grid, then drills into one
|
|
14
|
+
* assignment's reps, one rep's sessions and one session's scorecard. Read-only. Every tool derives from
|
|
15
|
+
* `loadTeamModel`, the loader `pitcher_roleplay_team` uses, so the view and the text tool never disagree.
|
|
16
|
+
* The runners live here, not in commands/roleplay.ts: registry.test.ts requires every `run*` of a command
|
|
17
|
+
* module to back exactly one `allTools` tool, and app tools are not in `allTools` (D25).
|
|
18
|
+
*/
|
|
19
|
+
export declare const roleplayManagerView: AppViewDescriptor;
|
|
20
|
+
/** structuredContent budget per result (the picker's, PIT-10066 D14). */
|
|
21
|
+
export declare const ROLEPLAY_VIEW_MAX_BYTES = 120000;
|
|
22
|
+
/** Model-facing text budget per result, in UTF-8 bytes. */
|
|
23
|
+
export declare const ROLEPLAY_TEXT_MAX_BYTES = 4096;
|
|
24
|
+
export declare const REPS_PAGE_SIZE = 25;
|
|
25
|
+
export declare const REP_SESSIONS_MAX = 50;
|
|
26
|
+
export declare const VIEW_MAX_ASSIGNMENTS = 50;
|
|
27
|
+
export type StatusCounts = Record<RepStatus, number>;
|
|
28
|
+
export type ResultKind = 'overview' | 'assignment-reps' | 'rep-sessions' | 'scorecard' | 'reps' | 'rep-assignments';
|
|
29
|
+
export interface ScopedResult<K extends ResultKind = ResultKind> {
|
|
30
|
+
kind: K;
|
|
31
|
+
instanceId: string;
|
|
32
|
+
scope: CoachScope;
|
|
33
|
+
coverage: Coverage;
|
|
34
|
+
/** !coverage.sessionsCapped (D8); an empty bundle is complete. */
|
|
35
|
+
complete: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** Over ALL scoped assignments, not only the 50 shown. */
|
|
38
|
+
export interface ManagerHeader {
|
|
39
|
+
assignments: number;
|
|
40
|
+
reps: number;
|
|
41
|
+
sessions: number;
|
|
42
|
+
scoredSessions: number;
|
|
43
|
+
/**
|
|
44
|
+
* Raw mean of listed scored assignment sessions, as pitcher_roleplay_team and the manager app compute it (D21).
|
|
45
|
+
* `overallScore` is 0..100 on every row, legacy 5-point evaluations included (their `grading_scale` applies to
|
|
46
|
+
* the category scores only), so this never mixes scales.
|
|
47
|
+
*/
|
|
48
|
+
meanScore: number | null;
|
|
49
|
+
passedPairs: number;
|
|
50
|
+
repAssignmentPairs: number;
|
|
51
|
+
statusCounts: StatusCounts;
|
|
52
|
+
}
|
|
53
|
+
export interface AssignmentSummary {
|
|
54
|
+
id: string;
|
|
55
|
+
scenarioName: string | null;
|
|
56
|
+
type: string;
|
|
57
|
+
passingScore: number;
|
|
58
|
+
dueDate: string | null;
|
|
59
|
+
active: boolean;
|
|
60
|
+
repCount: number;
|
|
61
|
+
sessions: number;
|
|
62
|
+
meanScore: number | null;
|
|
63
|
+
statusCounts: StatusCounts;
|
|
64
|
+
}
|
|
65
|
+
export interface RepRow {
|
|
66
|
+
userId: string;
|
|
67
|
+
name: string | null;
|
|
68
|
+
status: RepStatus;
|
|
69
|
+
sessions: number;
|
|
70
|
+
scoredSessions: number;
|
|
71
|
+
bestScore: number | null;
|
|
72
|
+
avgScore: number | null;
|
|
73
|
+
trend: number | null;
|
|
74
|
+
lastSessionAt: string | null;
|
|
75
|
+
recentOnly: boolean;
|
|
76
|
+
passSource: 'stored' | 'live' | null;
|
|
77
|
+
}
|
|
78
|
+
export interface AssignmentRepsData extends ScopedResult<'assignment-reps'> {
|
|
79
|
+
assignmentId: string;
|
|
80
|
+
scenarioName: string | null;
|
|
81
|
+
status: RepStatus | null;
|
|
82
|
+
page: number;
|
|
83
|
+
pageSize: number;
|
|
84
|
+
totalReps: number;
|
|
85
|
+
hasMore: boolean;
|
|
86
|
+
reps: RepRow[];
|
|
87
|
+
}
|
|
88
|
+
export interface ManagerViewData extends ScopedResult<'overview'> {
|
|
89
|
+
generatedAt: string;
|
|
90
|
+
header: ManagerHeader;
|
|
91
|
+
assignments: AssignmentSummary[];
|
|
92
|
+
totalAssignments: number;
|
|
93
|
+
/** The input assignmentId, else the only assignment when there is exactly one, else null. */
|
|
94
|
+
selected: AssignmentRepsData | null;
|
|
95
|
+
/** The instance attempt was made: true = the server applied scope instance. null = not tried (scope 'coach' sent). */
|
|
96
|
+
canViewInstance: boolean | null;
|
|
97
|
+
truncated?: string;
|
|
98
|
+
}
|
|
99
|
+
export interface RepSessionRow {
|
|
100
|
+
id: string;
|
|
101
|
+
timestamp: string | null;
|
|
102
|
+
score: number | null;
|
|
103
|
+
durationMs: number | null;
|
|
104
|
+
evaluationStatus: string | null;
|
|
105
|
+
meetsPassingScore: boolean | null;
|
|
106
|
+
}
|
|
107
|
+
export interface RepSessionsData extends ScopedResult<'rep-sessions'> {
|
|
108
|
+
assignmentId: string;
|
|
109
|
+
scenarioName: string | null;
|
|
110
|
+
passingScore: number;
|
|
111
|
+
rep: RepRow;
|
|
112
|
+
latestSkills: {
|
|
113
|
+
sessionId: string;
|
|
114
|
+
timestamp: string | null;
|
|
115
|
+
skills: LatestSkill[];
|
|
116
|
+
} | null;
|
|
117
|
+
sessions: RepSessionRow[];
|
|
118
|
+
totalSessions: number;
|
|
119
|
+
}
|
|
120
|
+
export interface ScorecardCategory {
|
|
121
|
+
skill_id: string | null;
|
|
122
|
+
title: string | null;
|
|
123
|
+
score: number | null;
|
|
124
|
+
max_score: number | null;
|
|
125
|
+
feedback: string | null;
|
|
126
|
+
}
|
|
127
|
+
/** pickSessionDetail output, fitted. */
|
|
128
|
+
export interface ScorecardData {
|
|
129
|
+
kind: 'scorecard';
|
|
130
|
+
id: string;
|
|
131
|
+
scenario_name: string | null;
|
|
132
|
+
difficulty: string | null;
|
|
133
|
+
timestamp: string | null;
|
|
134
|
+
duration_ms: number | null;
|
|
135
|
+
overall_score: number | null;
|
|
136
|
+
scored: boolean;
|
|
137
|
+
evaluation_status: string | null;
|
|
138
|
+
evaluation: {
|
|
139
|
+
summary: string | null;
|
|
140
|
+
strengths: string[];
|
|
141
|
+
improvements: string[];
|
|
142
|
+
grading_scale: number | null;
|
|
143
|
+
category_scores: ScorecardCategory[];
|
|
144
|
+
} | null;
|
|
145
|
+
truncated?: string;
|
|
146
|
+
}
|
|
147
|
+
/** The roleplay text budget over the shared helper (also used by roleplayReps.ts). */
|
|
148
|
+
export declare const roleplayFitText: (input: FitTextInput) => string;
|
|
149
|
+
/** One decimal, no trailing ".0" (66.66666 -> "66.7"). */
|
|
150
|
+
export declare const fmtNum: (x: number) => string;
|
|
151
|
+
export declare const inRange: (x: number | null) => x is number;
|
|
152
|
+
/** "62/100", "unscored", or the whole token "invalid" when the score or the scale is outside 0..9999. */
|
|
153
|
+
export declare function scoreToken(score: number | null, scale: number | null): string;
|
|
154
|
+
/** "2026-11-02 14:05" in UTC (ASCII), or the fixed "unknown-date --:--". */
|
|
155
|
+
export declare function fmtUtc(ts: string | null | undefined): string;
|
|
156
|
+
export declare const name60: (s: string | null | undefined, fallback: string) => string;
|
|
157
|
+
export declare const STATUS_TEXT: Record<RepStatus, string>;
|
|
158
|
+
/** 8.2 row 9 (also the capped head of the overview text). */
|
|
159
|
+
export declare function cappedSentence(coverage: Coverage): string;
|
|
160
|
+
export declare const emptyCounts: () => StatusCounts;
|
|
161
|
+
export interface AssignmentModel {
|
|
162
|
+
assignment: CoachAssignment;
|
|
163
|
+
own: CoachSession[];
|
|
164
|
+
reps: RepRow[];
|
|
165
|
+
summary: AssignmentSummary;
|
|
166
|
+
}
|
|
167
|
+
export declare function deriveAssignment(model: TeamModel, a: CoachAssignment, now: Date): AssignmentModel;
|
|
168
|
+
export declare function scoped<K extends ResultKind>(kind: K, instanceId: string, model: TeamModel): ScopedResult<K>;
|
|
169
|
+
export declare const NAME_CHARS = 200;
|
|
170
|
+
/** Clip to `n` code points, "..." included; never leaves a lone surrogate (an emoji renders whole or not at all). */
|
|
171
|
+
export declare function clipChars(s: string, n: number): string;
|
|
172
|
+
/**
|
|
173
|
+
* Overview: drop `selected` whole first (never a shortened page, whose next page would skip reps; the view then
|
|
174
|
+
* loads that assignment's first page itself), then assignments from the end. Measured with `truncated` included.
|
|
175
|
+
*/
|
|
176
|
+
export declare function fitRoleplayView(data: ManagerViewData, max?: number): ManagerViewData;
|
|
177
|
+
/**
|
|
178
|
+
* Drill results keep every row (paging continues after the rows sent), so an oversized one clips its free-text
|
|
179
|
+
* names instead: rep, scenario and skill names to 200 characters, then to 60; then the rep's skills from the end.
|
|
180
|
+
*/
|
|
181
|
+
export declare function fitAssignmentReps(data: AssignmentRepsData, max?: number): AssignmentRepsData;
|
|
182
|
+
export declare function fitRepSessions(data: RepSessionsData, max?: number): RepSessionsData;
|
|
183
|
+
/**
|
|
184
|
+
* Scorecard: clip every strength and improvement to 500 characters; then, while the FINAL payload (`truncated`
|
|
185
|
+
* included) is over budget: drop category feedback from the end, strengths and improvements from the end, clip the
|
|
186
|
+
* summary to 2000 characters and the names to 200, then drop categories from the end.
|
|
187
|
+
*/
|
|
188
|
+
export declare function fitScorecard(data: ScorecardData, max?: number): ScorecardData;
|
|
189
|
+
export interface ViewOpts extends CommonOpts {
|
|
190
|
+
instanceId?: string;
|
|
191
|
+
assignmentId?: string;
|
|
192
|
+
userId?: string;
|
|
193
|
+
status?: string;
|
|
194
|
+
page?: number;
|
|
195
|
+
scope?: string;
|
|
196
|
+
entryId?: string;
|
|
197
|
+
}
|
|
198
|
+
export type Deps = {
|
|
199
|
+
client?: AxiosInstance;
|
|
200
|
+
};
|
|
201
|
+
export declare function checkCommon(opts: ViewOpts): {
|
|
202
|
+
instanceId: string;
|
|
203
|
+
scope?: CoachScope;
|
|
204
|
+
status: RepStatus | null;
|
|
205
|
+
};
|
|
206
|
+
export declare function runRoleplayManagerView(opts: ViewOpts, deps?: Deps): Promise<Envelope<ManagerViewData>>;
|
|
207
|
+
export declare function managerViewText(raw: unknown): string;
|
|
208
|
+
export declare function runRoleplayAssignmentReps(opts: ViewOpts, deps?: Deps): Promise<Envelope<AssignmentRepsData>>;
|
|
209
|
+
export declare function assignmentRepsText(raw: unknown): string;
|
|
210
|
+
export declare function runRoleplayRepSessions(opts: ViewOpts, deps?: Deps): Promise<Envelope<RepSessionsData>>;
|
|
211
|
+
export declare function repSessionsText(raw: unknown): string;
|
|
212
|
+
/** session_get, fitted and tagged for the view (D4). */
|
|
213
|
+
export declare function fitScorecardEnvelope(env: Envelope<unknown>): Envelope<ScorecardData>;
|
|
214
|
+
export declare const runRoleplaySessionScorecard: (opts: ViewOpts, deps?: Deps) => Promise<Envelope<ScorecardData>>;
|
|
215
|
+
export declare function scorecardText(raw: unknown): string;
|
|
216
|
+
export declare const instanceId: z.ZodString;
|
|
217
|
+
export declare const statusEnum: z.ZodEnum<{
|
|
218
|
+
passed: "passed";
|
|
219
|
+
in_progress: "in_progress";
|
|
220
|
+
not_started: "not_started";
|
|
221
|
+
overdue: "overdue";
|
|
222
|
+
needs_coaching: "needs_coaching";
|
|
223
|
+
}>;
|
|
224
|
+
export declare const scopeEnum: z.ZodEnum<{
|
|
225
|
+
instance: "instance";
|
|
226
|
+
coach: "coach";
|
|
227
|
+
}>;
|
|
228
|
+
export declare const roleplayManagerTools: ToolDescriptor[];
|