@pitcher/cli-scripts 3.1.0 → 3.2.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 +40 -3
- 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/metadataTemplate.js +3 -2
- package/dist/src/commands/roleplay.d.ts +85 -0
- package/dist/src/commands/roleplay.js +449 -0
- package/dist/src/core/dsr-visits.d.ts +50 -0
- package/dist/src/core/dsr-visits.js +191 -0
- package/dist/src/core/pitcherAuth.d.ts +0 -7
- package/dist/src/core/pitcherAuth.js +0 -3
- package/dist/src/core/roleplay-stats.d.ts +79 -0
- package/dist/src/core/roleplay-stats.js +114 -0
- package/dist/src/mcp/hosted.js +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/mcp/registry.js +2 -0
- package/dist/src/mcp/renderPolicy.d.ts +1 -1
- package/dist/src/mcp/renderPolicy.js +2 -1
- package/dist/src/mcp/resources/analyticsCatalog.d.ts +1 -1
- package/dist/src/mcp/resources/analyticsCatalog.js +23 -5
- package/dist/src/mcp/server.d.ts +1 -0
- package/dist/src/mcp/server.js +4 -4
- package/dist/src/mcp/tools/analytics.js +88 -3
- package/dist/src/mcp/tools/metadataTemplate.js +3 -2
- package/dist/src/mcp/tools/roleplay.d.ts +2 -0
- package/dist/src/mcp/tools/roleplay.js +106 -0
- package/package.json +6 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { KPI_TYPES } from '../../core/kpiTypes.js';
|
|
3
|
-
import { runAnalyticsOrg, runAnalyticsInstance, runAnalyticsKpi, runAnalyticsEngagement, runAnalyticsPopularity, runAnalyticsUsers, runAnalyticsFiles, runAnalyticsCanvases, runAnalyticsViewers, runAnalyticsSessions, } from '../../commands/analytics.js';
|
|
3
|
+
import { runAnalyticsOrg, runAnalyticsInstance, runAnalyticsKpi, runAnalyticsEngagement, runAnalyticsPopularity, runAnalyticsUsers, runAnalyticsFiles, runAnalyticsCanvases, runAnalyticsViewers, runAnalyticsSessions, runAnalyticsFileUsers, runAnalyticsFilePages, runAnalyticsCanvasUsers, runAnalyticsViewerVisits, } from '../../commands/analytics.js';
|
|
4
4
|
export const analyticsTools = [
|
|
5
5
|
{
|
|
6
6
|
name: 'pitcher_analytics_org',
|
|
@@ -23,7 +23,7 @@ export const analyticsTools = [
|
|
|
23
23
|
title: 'Instance KPI metrics',
|
|
24
24
|
description: 'Read KPI metrics for an instance from the clickhouse analytics service (PIT-7647). ' +
|
|
25
25
|
'Access follows the signed-in user’s own role; activity-metric types need start/end dates ' +
|
|
26
|
-
'(inventory counts like total-members do not).',
|
|
26
|
+
'(inventory counts like total-members do not). Every value and growth figure is a number.',
|
|
27
27
|
inputShape: {
|
|
28
28
|
instanceId: z.string().describe('Instance ID (required)'),
|
|
29
29
|
type: z.enum(KPI_TYPES).describe('KPI type'),
|
|
@@ -97,7 +97,9 @@ export const analyticsTools = [
|
|
|
97
97
|
name: 'pitcher_analytics_files',
|
|
98
98
|
title: 'File usage analytics',
|
|
99
99
|
description: 'File usage analytics for an instance (views/opens/engagement per file), summarized and capped to ' +
|
|
100
|
-
'`limit`. Requires an org-admin key. Defaults to a 30-day window when dates are omitted.'
|
|
100
|
+
'`limit`. Requires an org-admin key. Defaults to a 30-day window when dates are omitted. ' +
|
|
101
|
+
'Pass userEmails to answer "which files did this user open"; for "who opened this file" use ' +
|
|
102
|
+
'pitcher_analytics_file_users.',
|
|
101
103
|
inputShape: {
|
|
102
104
|
instanceId: z.string().describe('Instance ID (required)'),
|
|
103
105
|
startDate: z.string().optional().describe('Window start, ISO date (defaults to 30 days ago)'),
|
|
@@ -173,4 +175,87 @@ export const analyticsTools = [
|
|
|
173
175
|
run: runAnalyticsSessions,
|
|
174
176
|
readOnly: true,
|
|
175
177
|
},
|
|
178
|
+
{
|
|
179
|
+
name: 'pitcher_analytics_file_users',
|
|
180
|
+
title: 'Who opened a file',
|
|
181
|
+
description: 'Who opened ONE file in an instance: per user (email, name, role) the opens, seconds, days active and the ' +
|
|
182
|
+
'last day opened, sorted by opens and capped to `limit` (total_count/has_more state the cap). Internal users ' +
|
|
183
|
+
'only. pageNumber (0-based) narrows to one page of the file. Needs an instance editor, instance admin or org ' +
|
|
184
|
+
'admin. Defaults to a 30-day window. For time per page use pitcher_analytics_file_pages.',
|
|
185
|
+
inputShape: {
|
|
186
|
+
instanceId: z.string().describe('Instance ID (required)'),
|
|
187
|
+
fileId: z.string().describe('File ID (required)'),
|
|
188
|
+
startDate: z.string().optional().describe('Window start, ISO date (defaults to 30 days ago)'),
|
|
189
|
+
endDate: z.string().optional().describe('Window end, ISO date (defaults to today)'),
|
|
190
|
+
pageNumber: z.number().int().min(0).optional().describe('Only this page of the file (0-based)'),
|
|
191
|
+
groupIds: z.string().optional().describe('Comma-separated distribution-group IDs'),
|
|
192
|
+
userEmails: z.string().optional().describe('Comma-separated user emails to scope by'),
|
|
193
|
+
limit: z.number().int().optional().describe('Max rows to return (default 20, max 100)'),
|
|
194
|
+
},
|
|
195
|
+
run: runAnalyticsFileUsers,
|
|
196
|
+
readOnly: true,
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'pitcher_analytics_file_pages',
|
|
200
|
+
title: 'Time per page of a file',
|
|
201
|
+
description: 'Time per page of ONE file: per page (1-based page_number) the internal opens, internal seconds and mean ' +
|
|
202
|
+
'seconds, plus external (DSR) views. Pass a single userEmails value for one user\'s time per page. Every page ' +
|
|
203
|
+
'is returned. Needs an instance editor, instance admin or org admin. Defaults to a 30-day window.',
|
|
204
|
+
inputShape: {
|
|
205
|
+
instanceId: z.string().describe('Instance ID (required)'),
|
|
206
|
+
fileId: z.string().describe('File ID (required)'),
|
|
207
|
+
startDate: z.string().optional().describe('Window start, ISO date (defaults to 30 days ago)'),
|
|
208
|
+
endDate: z.string().optional().describe('Window end, ISO date (defaults to today)'),
|
|
209
|
+
groupIds: z.string().optional().describe('Comma-separated distribution-group IDs'),
|
|
210
|
+
userEmails: z.string().optional().describe('Comma-separated user emails to scope by (one email: that user)'),
|
|
211
|
+
},
|
|
212
|
+
run: runAnalyticsFilePages,
|
|
213
|
+
readOnly: true,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: 'pitcher_analytics_canvas_users',
|
|
217
|
+
title: 'Per-user canvas usage',
|
|
218
|
+
description: 'Per-user canvas usage in an instance: one row per user and canvas (who, canvas_id, canvas_name, views = ' +
|
|
219
|
+
'visits, total_seconds, last_viewed_at), most visits first, `limit` rows per page with total_count/has_more. ' +
|
|
220
|
+
'With canvasId, each row also lists the pages (sections) of that canvas the user viewed with their seconds. ' +
|
|
221
|
+
'Internal users only (external DSR viewers: pitcher_analytics_viewer_visits); presentation time only, not ' +
|
|
222
|
+
'editing. Needs an instance editor, instance admin or org admin. Defaults to a 30-day window.',
|
|
223
|
+
inputShape: {
|
|
224
|
+
instanceId: z.string().describe('Instance ID (required)'),
|
|
225
|
+
canvasId: z.string().optional().describe("One canvas: adds each user's seconds per page (section)"),
|
|
226
|
+
startDate: z.string().optional().describe('Window start, ISO date (defaults to 30 days ago)'),
|
|
227
|
+
endDate: z.string().optional().describe('Window end, ISO date (defaults to today)'),
|
|
228
|
+
groupIds: z.string().optional().describe('Comma-separated distribution-group IDs'),
|
|
229
|
+
userEmails: z.string().optional().describe('Comma-separated user emails to scope by'),
|
|
230
|
+
page: z.number().int().optional().describe('Page number (default 1)'),
|
|
231
|
+
limit: z.number().int().optional().describe('Rows per page (default 20, max 100)'),
|
|
232
|
+
},
|
|
233
|
+
run: runAnalyticsCanvasUsers,
|
|
234
|
+
readOnly: true,
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: 'pitcher_analytics_viewer_visits',
|
|
238
|
+
title: 'DSR viewer visits and page time',
|
|
239
|
+
description: 'Per viewer of a DSR canvas: each visit (start, engaged seconds) and in it the sections, files and pages ' +
|
|
240
|
+
'viewed with views and seconds (`estimated: true` where an exit event was missing and the time is ' +
|
|
241
|
+
'inferred). One viewer (userEmail, verbatim from pitcher_analytics_viewers) or the most recently active ' +
|
|
242
|
+
'viewers (limit, default 10, max 25; viewers_total and truncated state the cap). format "csv" returns the ' +
|
|
243
|
+
'same as CSV text in `csv` (one row per viewer, visit and item) with a suggested filename, for export: hand ' +
|
|
244
|
+
'it to the user as a file. Works for any member. The server applies its own default window.',
|
|
245
|
+
inputShape: {
|
|
246
|
+
instanceId: z.string().describe('Instance ID (required)'),
|
|
247
|
+
canvasId: z.string().describe('DSR canvas ID (required)'),
|
|
248
|
+
userEmail: z
|
|
249
|
+
.string()
|
|
250
|
+
.optional()
|
|
251
|
+
.describe('One viewer: normalized_email (or email) from pitcher_analytics_viewers, VERBATIM'),
|
|
252
|
+
viewerType: z.string().optional().describe("Viewer type when listing: all, internal, external (default 'all')"),
|
|
253
|
+
startDate: z.string().optional().describe('Window start, ISO date (server default applies if omitted)'),
|
|
254
|
+
endDate: z.string().optional().describe('Window end, ISO date (server default applies if omitted)'),
|
|
255
|
+
limit: z.number().int().optional().describe('Viewers to read when no userEmail (default 10, max 25)'),
|
|
256
|
+
format: z.enum(['json', 'csv']).optional().describe('json (default) or csv for an export'),
|
|
257
|
+
},
|
|
258
|
+
run: runAnalyticsViewerVisits,
|
|
259
|
+
readOnly: true,
|
|
260
|
+
},
|
|
176
261
|
];
|
|
@@ -25,8 +25,9 @@ export const metadataTemplateTools = [
|
|
|
25
25
|
name: 'pitcher_metadata_template_upsert',
|
|
26
26
|
title: 'Upsert a metadata template',
|
|
27
27
|
description: "Upsert an instance's metadata-field schema. Merges the incoming sections by section 'label' — a " +
|
|
28
|
-
'section whose label matches an existing one is
|
|
29
|
-
'a section
|
|
28
|
+
'section whose label matches an existing one is REPLACED WHOLE (fields left out of it are removed), other ' +
|
|
29
|
+
'sections are preserved. Cannot remove a whole section. Pass exactly one of sections or sectionsFile. ' +
|
|
30
|
+
'Requires an instance- or org-admin key.',
|
|
30
31
|
inputShape: {
|
|
31
32
|
instanceId: z.string().describe('Instance ID (required)'),
|
|
32
33
|
sections: z.string().optional().describe('Sections JSON array (inline)'),
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ROLEPLAY_DIFFICULTIES, ROLEPLAY_GROUP_BY, ROLEPLAY_SESSION_SORT, runRoleplayKpis, runRoleplayRepSummary, runRoleplayScenariosList, runRoleplaySessionGet, runRoleplaySessions, runRoleplayTeam, } from '../../commands/roleplay.js';
|
|
3
|
+
const instanceId = z.string().describe('Instance ID (required)');
|
|
4
|
+
/** The shared roleplay_statements filters. Dates have NO default window: omitted means all time. */
|
|
5
|
+
const filters = {
|
|
6
|
+
instanceId,
|
|
7
|
+
startDate: z.string().optional().describe('Window start, ISO date. Omitted = all time (no default window)'),
|
|
8
|
+
endDate: z.string().optional().describe('Window end, ISO date. Omitted = all time (no default window)'),
|
|
9
|
+
rep: z.string().optional().describe('Rep name or email contains (case-insensitive)'),
|
|
10
|
+
scenario: z.string().optional().describe('Scenario or persona name contains (case-insensitive)'),
|
|
11
|
+
difficulty: z.enum(ROLEPLAY_DIFFICULTIES).optional().describe('Scenario difficulty'),
|
|
12
|
+
};
|
|
13
|
+
const UNSCORED = 'A session without a score (score null: the AI evaluation failed or is pending) is UNSCORED, never 0: ' +
|
|
14
|
+
'never count it in an average or as a fail.';
|
|
15
|
+
const CH_SOURCE = 'Reads the AI Roleplay analytics replica (ClickHouse roleplay_statements, the Admin Analytics tab). ' +
|
|
16
|
+
'Dates are optional and there is no default window: omitted means all time.';
|
|
17
|
+
const ADMIN_ONLY = 'Instance or org admins only; anyone else gets an AUTH error, and a coaching manager should use pitcher_roleplay_team.';
|
|
18
|
+
export const roleplayTools = [
|
|
19
|
+
{
|
|
20
|
+
name: 'pitcher_roleplay_kpis',
|
|
21
|
+
title: 'AI Roleplay KPIs',
|
|
22
|
+
description: 'AI Roleplay totals for an instance: total, scored and unscored sessions, the mean score of SCORED sessions, ' +
|
|
23
|
+
`mean duration and active reps, with optional rep/scenario/difficulty filters. ${UNSCORED} ${CH_SOURCE} ${ADMIN_ONLY}`,
|
|
24
|
+
inputShape: filters,
|
|
25
|
+
run: runRoleplayKpis,
|
|
26
|
+
readOnly: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'pitcher_roleplay_sessions',
|
|
30
|
+
title: 'AI Roleplay sessions',
|
|
31
|
+
description: 'AI Roleplay session list for an instance, newest first: entry_id, session_at, rep_name, who (rep email), ' +
|
|
32
|
+
'scenario_name, persona_name, difficulty, score, evaluated, rating, duration_ms. Default 20 rows, max 100 per ' +
|
|
33
|
+
`page; total_count/has_more say when there are more. ${UNSCORED} ${CH_SOURCE} ${ADMIN_ONLY} ` +
|
|
34
|
+
'Open one session with pitcher_roleplay_session_get (its entry_id).',
|
|
35
|
+
inputShape: {
|
|
36
|
+
...filters,
|
|
37
|
+
sortBy: z.enum(ROLEPLAY_SESSION_SORT).optional().describe('Sort field (default session_at)'),
|
|
38
|
+
sortOrder: z.enum(['asc', 'desc']).optional().describe('Sort direction (default desc); unscored sessions sort last'),
|
|
39
|
+
page: z.number().int().optional().describe('Page number (default 1)'),
|
|
40
|
+
limit: z.number().int().optional().describe('Rows per page (default 20, max 100)'),
|
|
41
|
+
},
|
|
42
|
+
run: runRoleplaySessions,
|
|
43
|
+
readOnly: true,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'pitcher_roleplay_rep_summary',
|
|
47
|
+
title: 'AI Roleplay per-rep or per-scenario summary',
|
|
48
|
+
description: 'Per-rep (groupBy rep, keyed on the rep email) or per-scenario (groupBy scenario) session counts, scored ' +
|
|
49
|
+
'counts, mean score of scored sessions and last session, up to 50 groups with the most sessions. Exact up to ' +
|
|
50
|
+
'5000 sessions in the window (read newest first); `complete: false` means the figures cover only the newest ' +
|
|
51
|
+
`5000, so narrow the dates. ${UNSCORED} ${CH_SOURCE} ${ADMIN_ONLY}`,
|
|
52
|
+
inputShape: {
|
|
53
|
+
...filters,
|
|
54
|
+
groupBy: z.enum(ROLEPLAY_GROUP_BY).optional().describe('Group by rep (default) or scenario'),
|
|
55
|
+
},
|
|
56
|
+
run: runRoleplayRepSummary,
|
|
57
|
+
readOnly: true,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'pitcher_roleplay_team',
|
|
61
|
+
title: 'AI Roleplay assignment completion',
|
|
62
|
+
description: 'Roleplay assignment completion per rep, as the AI Roleplay manager app shows it: per assignment its passing ' +
|
|
63
|
+
'score and due date, each rep\'s status (passed, in_progress, not_started, overdue, needs_coaching), sessions, ' +
|
|
64
|
+
'scored sessions, best and mean score, trend, last session, plus per-skill mean scores. Instance or org admins ' +
|
|
65
|
+
'get every roleplay assignment on the instance (scope "instance"); a coaching manager gets the assignments ' +
|
|
66
|
+
'they coach (scope "coach"). Works for any member (an empty list when they coach nobody). ' +
|
|
67
|
+
`${UNSCORED} Reads Postgres appsDB through next-core (cch-assignment, cch-session-result), not ClickHouse. ` +
|
|
68
|
+
'The server returns at most the newest 1000 sessions; `complete: false` says the cap was hit. ' +
|
|
69
|
+
'Up to 50 assignments and 100 reps each; filter with assignmentId or status.',
|
|
70
|
+
inputShape: {
|
|
71
|
+
instanceId,
|
|
72
|
+
assignmentId: z.string().optional().describe('Only this assignment (its id from an earlier call)'),
|
|
73
|
+
status: z
|
|
74
|
+
.enum(['passed', 'in_progress', 'not_started', 'overdue', 'needs_coaching'])
|
|
75
|
+
.optional()
|
|
76
|
+
.describe('Only reps with this status'),
|
|
77
|
+
},
|
|
78
|
+
run: runRoleplayTeam,
|
|
79
|
+
readOnly: true,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'pitcher_roleplay_session_get',
|
|
83
|
+
title: 'AI Roleplay session detail',
|
|
84
|
+
description: 'One AI Roleplay session: scenario, difficulty, time, duration, overall score (null = unscored, never 0), ' +
|
|
85
|
+
'evaluation status, and the evaluation summary, strengths, improvements and per-skill scores with feedback. ' +
|
|
86
|
+
'Never the transcript, messages or recordings. Opens to the rep, a coach of that rep, or an instance or org ' +
|
|
87
|
+
'admin; anyone else gets an AUTH error. Reads Postgres appsDB (cch-session-result) through next-core. ' +
|
|
88
|
+
'Takes entryId = entry_id from pitcher_roleplay_sessions.',
|
|
89
|
+
inputShape: {
|
|
90
|
+
instanceId,
|
|
91
|
+
entryId: z.string().describe('Session entry ID (entry_id from pitcher_roleplay_sessions)'),
|
|
92
|
+
},
|
|
93
|
+
run: runRoleplaySessionGet,
|
|
94
|
+
readOnly: true,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'pitcher_roleplay_scenarios_list',
|
|
98
|
+
title: 'AI Roleplay scenarios',
|
|
99
|
+
description: 'The AI Roleplay scenario catalog of an instance: id, kind, name, persona title, description, difficulty, ' +
|
|
100
|
+
'active, time limit and the skills it is graded on (title and weight). Never a prompt. Any member. ' +
|
|
101
|
+
'Reads the instance config (appsDB cch-config) through next-core.',
|
|
102
|
+
inputShape: { instanceId },
|
|
103
|
+
run: runRoleplayScenariosList,
|
|
104
|
+
readOnly: true,
|
|
105
|
+
},
|
|
106
|
+
];
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pitcher/cli-scripts",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "The Pitcher CLI for various tasks in its ecosystem.",
|
|
5
5
|
"author": "Pitcher AG",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/PitcherAG/web.git",
|
|
10
|
+
"directory": "packages/libs/cli-scripts"
|
|
11
|
+
},
|
|
7
12
|
"keywords": [
|
|
8
13
|
"pitcher",
|
|
9
14
|
"cli",
|