@agentrysh/mcp 0.0.12 → 0.0.14
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 +1 -1
- package/dist/api.d.ts +150 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +43 -2
- package/dist/api.js.map +1 -1
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +14 -6
- package/dist/onboarding.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +460 -22
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
package/dist/tools.js
CHANGED
|
@@ -16,12 +16,14 @@ export const TOOL_DESCRIPTORS = [
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
name: "agentry_login",
|
|
19
|
-
description: "Authenticate the user via
|
|
19
|
+
description: "Authenticate the user via the agentry sign-in page (GitHub, Google, or magic link — " +
|
|
20
|
+
"user picks any provider). Returns an API key, stored locally. " +
|
|
20
21
|
"" +
|
|
21
22
|
"RECOMMENDED two-call sequence for interactive sessions: " +
|
|
22
|
-
" 1. Call with mode='start_only' → returns user_code + verification_uri + device_code
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
" 1. Call with mode='start_only' → returns user_code + verification_uri + device_code " +
|
|
24
|
+
" (plus verification_uri_complete with the code pre-filled). Show the user the URL " +
|
|
25
|
+
" and code (DO NOT ask them to confirm authorization — they'll open the URL, sign in " +
|
|
26
|
+
" with their provider of choice, and you'll poll). " +
|
|
25
27
|
" 2. IMMEDIATELY call again with mode='full' + the device_code from step 1. " +
|
|
26
28
|
" This blocks and auto-polls every ~5s for up to timeout_seconds (default 300 = 5min). " +
|
|
27
29
|
" Returns the api_key when the user authorizes, or status='expired'/'denied' on failure. " +
|
|
@@ -451,8 +453,8 @@ export const TOOL_DESCRIPTORS = [
|
|
|
451
453
|
{
|
|
452
454
|
name: "agentry_get_session_replay",
|
|
453
455
|
description: "Fetch a single session recording's metadata + player URL. Open `player_url` in a " +
|
|
454
|
-
"browser to watch. For programmatic DOM-event inspection (the
|
|
455
|
-
"
|
|
456
|
+
"browser to watch. For programmatic DOM-event inspection (the rrweb snapshots), " +
|
|
457
|
+
"call agentry_get_replay_snapshots.",
|
|
456
458
|
inputSchema: {
|
|
457
459
|
type: "object",
|
|
458
460
|
properties: {
|
|
@@ -463,17 +465,163 @@ export const TOOL_DESCRIPTORS = [
|
|
|
463
465
|
additionalProperties: false,
|
|
464
466
|
},
|
|
465
467
|
},
|
|
468
|
+
{
|
|
469
|
+
name: "agentry_get_replay_snapshots",
|
|
470
|
+
description: "Fetch the rrweb-format DOM snapshots for one recording. Each snapshot has type " +
|
|
471
|
+
"(Meta / FullSnapshot / IncrementalSnapshot — values 4 / 2 / 3) and timestamp. " +
|
|
472
|
+
"For agent inspection: filter type=3 events for user actions (clicks, scrolls, " +
|
|
473
|
+
"inputs). Useful for reconstructing exactly what the user did before an error.",
|
|
474
|
+
inputSchema: {
|
|
475
|
+
type: "object",
|
|
476
|
+
properties: {
|
|
477
|
+
project_id: { type: "string" },
|
|
478
|
+
replay_id: { type: "string" },
|
|
479
|
+
source: {
|
|
480
|
+
type: "string",
|
|
481
|
+
enum: ["realtime", "blob"],
|
|
482
|
+
description: "PostHog snapshot source. 'realtime' for live, 'blob' for archived.",
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
required: ["replay_id"],
|
|
486
|
+
additionalProperties: false,
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
name: "agentry_evaluate_feature_flag",
|
|
491
|
+
description: "Evaluate feature flags for one user (distinct_id). Two shapes:" +
|
|
492
|
+
"" +
|
|
493
|
+
" - Pass `key` to get a single flag's value (boolean / variant string / null if " +
|
|
494
|
+
" not active for this user)." +
|
|
495
|
+
" - Omit `key` to get a map of all currently-active flags for the user." +
|
|
496
|
+
"" +
|
|
497
|
+
"Use this when investigating a bug — 'is this user in the new checkout flow?' is " +
|
|
498
|
+
"one call away. Pass `person_properties` to override the stored properties for " +
|
|
499
|
+
"what-if evaluation.",
|
|
500
|
+
inputSchema: {
|
|
501
|
+
type: "object",
|
|
502
|
+
properties: {
|
|
503
|
+
project_id: { type: "string" },
|
|
504
|
+
distinct_id: { type: "string", description: "Stable per-user id, same as case.affected_users[].distinct_id." },
|
|
505
|
+
key: { type: "string", description: "Flag key. Omit to get all flags." },
|
|
506
|
+
person_properties: { type: "object", description: "Override stored properties for what-if." },
|
|
507
|
+
groups: { type: "object", description: "Group analytics overrides if your flag targets groups." },
|
|
508
|
+
},
|
|
509
|
+
required: ["distinct_id"],
|
|
510
|
+
additionalProperties: false,
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
name: "agentry_get_distinct_id_summary",
|
|
515
|
+
description: "One-call user dossier. Returns: PostHog person properties, total event count, " +
|
|
516
|
+
"first/last seen, last 20 events, recent session recordings (if replay is on), and " +
|
|
517
|
+
"a deep-link URL into PostHog's persons UI. Use this when investigating a case — " +
|
|
518
|
+
"the affected_users[].distinct_id from agentry_get_case lets you build the full " +
|
|
519
|
+
"picture without 3+ separate HogQL calls.",
|
|
520
|
+
inputSchema: {
|
|
521
|
+
type: "object",
|
|
522
|
+
properties: {
|
|
523
|
+
project_id: { type: "string" },
|
|
524
|
+
distinct_id: { type: "string" },
|
|
525
|
+
},
|
|
526
|
+
required: ["distinct_id"],
|
|
527
|
+
additionalProperties: false,
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "agentry_survey_responses",
|
|
532
|
+
description: "Roll-up of survey responses. Returns: the survey definition (questions + choice " +
|
|
533
|
+
"labels), a response_distribution (counts per choice), the last 50 free-text " +
|
|
534
|
+
"responses with timestamps, and a web UI deep-link. Saves the agent from composing " +
|
|
535
|
+
"HogQL with $survey_response property unpacking.",
|
|
536
|
+
inputSchema: {
|
|
537
|
+
type: "object",
|
|
538
|
+
properties: {
|
|
539
|
+
project_id: { type: "string" },
|
|
540
|
+
survey_id: { type: "string" },
|
|
541
|
+
},
|
|
542
|
+
required: ["survey_id"],
|
|
543
|
+
additionalProperties: false,
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
name: "agentry_create_ab_test",
|
|
548
|
+
description: "Composite tool: creates a multivariate feature flag AND returns the bound " +
|
|
549
|
+
"conversion-rate HogQL query an agent can run later via agentry_analytics_query. " +
|
|
550
|
+
"" +
|
|
551
|
+
"Pass `name`, `success_event` (e.g. 'checkout_completed'), and `variants` (array of " +
|
|
552
|
+
"{key} — auto-split rollout if rollout_percentage not given; must sum to 100 if " +
|
|
553
|
+
"any are explicit). Optional flag_key (default: slugified name)." +
|
|
554
|
+
"" +
|
|
555
|
+
"Returns: flag_id, conversion_query string, web_ui_url. Recommended: ≥1000 users " +
|
|
556
|
+
"per variant before drawing conclusions.",
|
|
557
|
+
inputSchema: {
|
|
558
|
+
type: "object",
|
|
559
|
+
properties: {
|
|
560
|
+
project_id: { type: "string" },
|
|
561
|
+
name: { type: "string" },
|
|
562
|
+
flag_key: { type: "string", description: "Override the slugified name." },
|
|
563
|
+
success_event: { type: "string", description: "The event whose conversion you're measuring." },
|
|
564
|
+
variants: {
|
|
565
|
+
type: "array",
|
|
566
|
+
items: {
|
|
567
|
+
type: "object",
|
|
568
|
+
properties: {
|
|
569
|
+
key: { type: "string" },
|
|
570
|
+
name: { type: "string" },
|
|
571
|
+
rollout_percentage: { type: "number" },
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
description: "Min 2 variants. Auto-split if rollout_percentage omitted.",
|
|
575
|
+
},
|
|
576
|
+
},
|
|
577
|
+
required: ["name", "success_event", "variants"],
|
|
578
|
+
additionalProperties: false,
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
name: "agentry_recent_changes",
|
|
583
|
+
description: "Read the agent-mutation audit log. Returns every flag/cohort/survey/publication/" +
|
|
584
|
+
"session-replay mutation the agent (or anyone with your `agk_` key) has made in the " +
|
|
585
|
+
"last N hours." +
|
|
586
|
+
"" +
|
|
587
|
+
"Default window is 24 hours. Pass `hours` to widen — 48, 72, 168 (week), max 720 (30d)." +
|
|
588
|
+
"Pass `action_prefix` (e.g. 'feature_flag.' / 'cohort.' / 'survey.' / 'publication.' / " +
|
|
589
|
+
"'session_replay.') or `resource_type` to filter. Use this as a periodic " +
|
|
590
|
+
"'what-did-the-agent-do' check when leaving agents to run unattended.",
|
|
591
|
+
inputSchema: {
|
|
592
|
+
type: "object",
|
|
593
|
+
properties: {
|
|
594
|
+
hours: { type: "number", description: "Lookback window. 1..720. Default 24." },
|
|
595
|
+
action_prefix: {
|
|
596
|
+
type: "string",
|
|
597
|
+
description: "Filter by action prefix (e.g. 'feature_flag.' matches both create + delete).",
|
|
598
|
+
},
|
|
599
|
+
resource_type: {
|
|
600
|
+
type: "string",
|
|
601
|
+
enum: ["feature_flag", "cohort", "survey", "publication", "session_replay", "ab_test"],
|
|
602
|
+
},
|
|
603
|
+
project_id: { type: "string", description: "Restrict to one project." },
|
|
604
|
+
limit: { type: "number", description: "Max rows (default 200, max 500)." },
|
|
605
|
+
},
|
|
606
|
+
additionalProperties: false,
|
|
607
|
+
},
|
|
608
|
+
},
|
|
466
609
|
{
|
|
467
610
|
name: "agentry_repair_analytics",
|
|
468
|
-
description: "Re-attempt PostHog provisioning for
|
|
469
|
-
"
|
|
611
|
+
description: "Re-attempt PostHog provisioning for one project. Idempotent — if the project already " +
|
|
612
|
+
"has a PostHog team binding, returns its id without recreating. Use this when " +
|
|
470
613
|
"agentry_verify_install reports analytics ❌ with reason 'no_posthog_project' OR when a " +
|
|
471
614
|
"/v1/track/ call returns 503 with that code. " +
|
|
472
615
|
"" +
|
|
473
616
|
"DO NOT re-run agentry_login for this failure mode — that mints a new api_key and " +
|
|
474
|
-
"churns the user's local config. This tool
|
|
475
|
-
|
|
476
|
-
|
|
617
|
+
"churns the user's local config. This tool repairs the project-scoped analytics binding only.",
|
|
618
|
+
inputSchema: {
|
|
619
|
+
type: "object",
|
|
620
|
+
properties: {
|
|
621
|
+
project_id: { type: "string", description: "Project to repair. Defaults to local default_project_id." },
|
|
622
|
+
},
|
|
623
|
+
additionalProperties: false,
|
|
624
|
+
},
|
|
477
625
|
},
|
|
478
626
|
{
|
|
479
627
|
name: "agentry_rotate_key",
|
|
@@ -1198,6 +1346,59 @@ export const TOOL_DESCRIPTORS = [
|
|
|
1198
1346
|
additionalProperties: false,
|
|
1199
1347
|
},
|
|
1200
1348
|
},
|
|
1349
|
+
{
|
|
1350
|
+
name: "agentry_invite_teammate",
|
|
1351
|
+
description: "Mint a one-shot invite URL granting a teammate access to a project. Owner-only. " +
|
|
1352
|
+
"The recipient opens the URL, signs in with any provider (GitHub / Google / magic link), " +
|
|
1353
|
+
"and gets their own agentry account + API key automatically scoped to this project — they " +
|
|
1354
|
+
"do NOT use your API key. " +
|
|
1355
|
+
"" +
|
|
1356
|
+
"After this returns, share `invite_url` with your teammate (Slack, email — manual for v1). " +
|
|
1357
|
+
"Invite expires in 7 days, single-use.",
|
|
1358
|
+
inputSchema: {
|
|
1359
|
+
type: "object",
|
|
1360
|
+
properties: {
|
|
1361
|
+
project_id: { type: "string", description: "Defaults to the local default project." },
|
|
1362
|
+
email: {
|
|
1363
|
+
type: "string",
|
|
1364
|
+
description: "Optional — shown on the invite landing page as a hint to the recipient. " +
|
|
1365
|
+
"Does NOT restrict who can consume the invite; the link is the credential.",
|
|
1366
|
+
},
|
|
1367
|
+
role: {
|
|
1368
|
+
type: "string",
|
|
1369
|
+
enum: ["member", "owner"],
|
|
1370
|
+
description: "Defaults to 'member'. 'owner' is rare — only add other owners deliberately.",
|
|
1371
|
+
},
|
|
1372
|
+
},
|
|
1373
|
+
additionalProperties: false,
|
|
1374
|
+
},
|
|
1375
|
+
},
|
|
1376
|
+
{
|
|
1377
|
+
name: "agentry_list_members",
|
|
1378
|
+
description: "List members of a project + any pending (un-consumed, un-expired) invites. " +
|
|
1379
|
+
"Any member can see the full roster; remove members via agentry_remove_member.",
|
|
1380
|
+
inputSchema: {
|
|
1381
|
+
type: "object",
|
|
1382
|
+
properties: {
|
|
1383
|
+
project_id: { type: "string", description: "Defaults to the local default project." },
|
|
1384
|
+
},
|
|
1385
|
+
additionalProperties: false,
|
|
1386
|
+
},
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
name: "agentry_remove_member",
|
|
1390
|
+
description: "Remove a teammate from a project. Owner-only. Cannot remove the last remaining owner, " +
|
|
1391
|
+
"and an owner cannot remove themselves (transfer ownership first — TBD).",
|
|
1392
|
+
inputSchema: {
|
|
1393
|
+
type: "object",
|
|
1394
|
+
properties: {
|
|
1395
|
+
project_id: { type: "string", description: "Defaults to the local default project." },
|
|
1396
|
+
user_id: { type: "string", description: "The user_id from agentry_list_members." },
|
|
1397
|
+
},
|
|
1398
|
+
required: ["user_id"],
|
|
1399
|
+
additionalProperties: false,
|
|
1400
|
+
},
|
|
1401
|
+
},
|
|
1201
1402
|
];
|
|
1202
1403
|
// ---------------------------------------------------------------------------
|
|
1203
1404
|
// Helpers shared across tool handlers
|
|
@@ -1312,7 +1513,7 @@ export async function dispatchTool(name, args) {
|
|
|
1312
1513
|
case "agentry_rotate_key":
|
|
1313
1514
|
return await handleRotateKey();
|
|
1314
1515
|
case "agentry_repair_analytics":
|
|
1315
|
-
return await handleRepairAnalytics();
|
|
1516
|
+
return await handleRepairAnalytics(a.project_id ? String(a.project_id) : undefined);
|
|
1316
1517
|
case "agentry_publish_query":
|
|
1317
1518
|
return await handlePublishQuery({
|
|
1318
1519
|
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
@@ -1437,6 +1638,52 @@ export async function dispatchTool(name, args) {
|
|
|
1437
1638
|
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1438
1639
|
replay_id: String(a.replay_id ?? ""),
|
|
1439
1640
|
});
|
|
1641
|
+
case "agentry_get_replay_snapshots":
|
|
1642
|
+
return await handleGetReplaySnapshots({
|
|
1643
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1644
|
+
replay_id: String(a.replay_id ?? ""),
|
|
1645
|
+
source: a.source ? String(a.source) : undefined,
|
|
1646
|
+
});
|
|
1647
|
+
case "agentry_evaluate_feature_flag":
|
|
1648
|
+
return await handleEvaluateFeatureFlag({
|
|
1649
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1650
|
+
distinct_id: String(a.distinct_id ?? ""),
|
|
1651
|
+
key: a.key ? String(a.key) : undefined,
|
|
1652
|
+
person_properties: a.person_properties && typeof a.person_properties === "object"
|
|
1653
|
+
? a.person_properties
|
|
1654
|
+
: undefined,
|
|
1655
|
+
groups: a.groups && typeof a.groups === "object"
|
|
1656
|
+
? a.groups
|
|
1657
|
+
: undefined,
|
|
1658
|
+
});
|
|
1659
|
+
case "agentry_get_distinct_id_summary":
|
|
1660
|
+
return await handleGetDistinctIdSummary({
|
|
1661
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1662
|
+
distinct_id: String(a.distinct_id ?? ""),
|
|
1663
|
+
});
|
|
1664
|
+
case "agentry_survey_responses":
|
|
1665
|
+
return await handleSurveyResponses({
|
|
1666
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1667
|
+
survey_id: String(a.survey_id ?? ""),
|
|
1668
|
+
});
|
|
1669
|
+
case "agentry_create_ab_test":
|
|
1670
|
+
return await handleCreateAbTest({
|
|
1671
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1672
|
+
name: String(a.name ?? ""),
|
|
1673
|
+
flag_key: a.flag_key ? String(a.flag_key) : undefined,
|
|
1674
|
+
success_event: String(a.success_event ?? ""),
|
|
1675
|
+
variants: Array.isArray(a.variants)
|
|
1676
|
+
? a.variants
|
|
1677
|
+
: [],
|
|
1678
|
+
});
|
|
1679
|
+
case "agentry_recent_changes":
|
|
1680
|
+
return await handleRecentChanges({
|
|
1681
|
+
hours: typeof a.hours === "number" ? a.hours : undefined,
|
|
1682
|
+
action_prefix: a.action_prefix ? String(a.action_prefix) : undefined,
|
|
1683
|
+
resource_type: a.resource_type ? String(a.resource_type) : undefined,
|
|
1684
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1685
|
+
limit: typeof a.limit === "number" ? a.limit : undefined,
|
|
1686
|
+
});
|
|
1440
1687
|
case "agentry_list_projects":
|
|
1441
1688
|
return await handleListProjects();
|
|
1442
1689
|
case "agentry_create_project":
|
|
@@ -1634,6 +1881,19 @@ export async function dispatchTool(name, args) {
|
|
|
1634
1881
|
kind: a.kind ? String(a.kind) : undefined,
|
|
1635
1882
|
resolved: typeof a.resolved === "boolean" ? a.resolved : undefined,
|
|
1636
1883
|
});
|
|
1884
|
+
case "agentry_invite_teammate":
|
|
1885
|
+
return await handleInviteTeammate({
|
|
1886
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1887
|
+
email: a.email ? String(a.email) : undefined,
|
|
1888
|
+
role: a.role === "owner" ? "owner" : "member",
|
|
1889
|
+
});
|
|
1890
|
+
case "agentry_list_members":
|
|
1891
|
+
return await handleListMembers(a.project_id ? String(a.project_id) : undefined);
|
|
1892
|
+
case "agentry_remove_member":
|
|
1893
|
+
return await handleRemoveMember({
|
|
1894
|
+
project_id: a.project_id ? String(a.project_id) : undefined,
|
|
1895
|
+
user_id: String(a.user_id ?? ""),
|
|
1896
|
+
});
|
|
1637
1897
|
default:
|
|
1638
1898
|
return {
|
|
1639
1899
|
error: {
|
|
@@ -1663,7 +1923,13 @@ function handleStatus() {
|
|
|
1663
1923
|
project_count: projectIds.length,
|
|
1664
1924
|
projects: projectIds.map((id) => {
|
|
1665
1925
|
const p = cfg.projects[id];
|
|
1666
|
-
return {
|
|
1926
|
+
return {
|
|
1927
|
+
id,
|
|
1928
|
+
name: p.name,
|
|
1929
|
+
local_path: p.local_path,
|
|
1930
|
+
analytics_ready: p.analytics_ready ?? null,
|
|
1931
|
+
posthog_project_id: p.posthog_project_id ?? null,
|
|
1932
|
+
};
|
|
1667
1933
|
}),
|
|
1668
1934
|
onboarding: hint,
|
|
1669
1935
|
next_steps: [hint.message, hint.next_action],
|
|
@@ -1673,14 +1939,16 @@ async function handleLogin(input) {
|
|
|
1673
1939
|
const cfg = loadConfig();
|
|
1674
1940
|
if (input.mode === "start_only") {
|
|
1675
1941
|
const start = await api.startDeviceFlow(cfg);
|
|
1942
|
+
const openUrl = start.verification_uri_complete ?? start.verification_uri;
|
|
1676
1943
|
return {
|
|
1677
1944
|
mode: "start_only",
|
|
1678
1945
|
verification_uri: start.verification_uri,
|
|
1946
|
+
verification_uri_complete: start.verification_uri_complete,
|
|
1679
1947
|
user_code: start.user_code,
|
|
1680
1948
|
device_code: start.device_code,
|
|
1681
1949
|
interval: start.interval,
|
|
1682
1950
|
expires_in: start.expires_in,
|
|
1683
|
-
next_action: `Show the user:
|
|
1951
|
+
next_action: `Show the user a clickable link: ${openUrl} — one click takes them to sign-in, no code entry. ` +
|
|
1684
1952
|
`Then IMMEDIATELY call agentry_login again with mode='full' and device_code='${start.device_code}'. ` +
|
|
1685
1953
|
`That call will block and auto-poll for up to ${start.expires_in}s — DO NOT ask the user to confirm authorization before polling.`,
|
|
1686
1954
|
};
|
|
@@ -1779,7 +2047,7 @@ async function handleLogin(input) {
|
|
|
1779
2047
|
device_code: deviceCode,
|
|
1780
2048
|
next_action: `Timed out after ${input.timeout_seconds ?? 300}s. ` +
|
|
1781
2049
|
(verificationUri && userCode
|
|
1782
|
-
? `Confirm the user opened ${verificationUri}
|
|
2050
|
+
? `Confirm the user opened ${verificationUri}?code=${userCode}, `
|
|
1783
2051
|
: "Confirm the user has authorized, ") +
|
|
1784
2052
|
`then call agentry_login again with mode='full' and device_code='${deviceCode}' to resume polling.`,
|
|
1785
2053
|
};
|
|
@@ -1808,7 +2076,7 @@ async function handleRotateKey() {
|
|
|
1808
2076
|
"New key stored locally. Old key is revoked — update any places it was pasted (CI envs, etc).",
|
|
1809
2077
|
};
|
|
1810
2078
|
}
|
|
1811
|
-
async function handleRepairAnalytics() {
|
|
2079
|
+
async function handleRepairAnalytics(projectId) {
|
|
1812
2080
|
const cfg = loadConfig();
|
|
1813
2081
|
if (!cfg.api_key) {
|
|
1814
2082
|
return {
|
|
@@ -1819,9 +2087,32 @@ async function handleRepairAnalytics() {
|
|
|
1819
2087
|
},
|
|
1820
2088
|
};
|
|
1821
2089
|
}
|
|
2090
|
+
const picked = pickProject(cfg, projectId);
|
|
2091
|
+
if (!picked || !picked.project) {
|
|
2092
|
+
return {
|
|
2093
|
+
error: {
|
|
2094
|
+
code: "no_project",
|
|
2095
|
+
message: "No local project selected for analytics repair.",
|
|
2096
|
+
next_action: "Create a project first or pass a project_id from agentry_list_projects.",
|
|
2097
|
+
},
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
1822
2100
|
try {
|
|
1823
|
-
const resp = await api.repairAnalyticsBackend(cfg);
|
|
1824
|
-
|
|
2101
|
+
const resp = await api.repairAnalyticsBackend(cfg, picked.id);
|
|
2102
|
+
const updatedProject = {
|
|
2103
|
+
...picked.project,
|
|
2104
|
+
analytics_ready: resp.posthog_project_id !== null,
|
|
2105
|
+
posthog_project_id: resp.posthog_project_id,
|
|
2106
|
+
};
|
|
2107
|
+
const nextCfg = {
|
|
2108
|
+
...cfg,
|
|
2109
|
+
projects: {
|
|
2110
|
+
...cfg.projects,
|
|
2111
|
+
[picked.id]: updatedProject,
|
|
2112
|
+
},
|
|
2113
|
+
};
|
|
2114
|
+
saveConfig(nextCfg);
|
|
2115
|
+
return { project_id: picked.id, ...resp };
|
|
1825
2116
|
}
|
|
1826
2117
|
catch (err) {
|
|
1827
2118
|
return {
|
|
@@ -1829,7 +2120,7 @@ async function handleRepairAnalytics() {
|
|
|
1829
2120
|
code: "repair_failed",
|
|
1830
2121
|
message: err instanceof Error ? err.message : String(err),
|
|
1831
2122
|
next_action: "Upstream PostHog provisioning failed. If the error mentions 5xx / timeouts / rate " +
|
|
1832
|
-
"limits, wait 30–60s and call agentry_repair_analytics again. Errors and deploys are " +
|
|
2123
|
+
"limits, wait 30–60s and call agentry_repair_analytics again for the same project. Errors and deploys are " +
|
|
1833
2124
|
"unaffected; only analytics ingest needs PostHog.",
|
|
1834
2125
|
},
|
|
1835
2126
|
};
|
|
@@ -2135,6 +2426,91 @@ async function handleGetSessionReplay(input) {
|
|
|
2135
2426
|
return r.error;
|
|
2136
2427
|
return await api.getSessionReplay(cfg, r.id, input.replay_id);
|
|
2137
2428
|
}
|
|
2429
|
+
async function handleGetReplaySnapshots(input) {
|
|
2430
|
+
if (!input.replay_id) {
|
|
2431
|
+
return { error: { code: "invalid_payload", message: "replay_id is required.", next_action: "Pass replay_id from agentry_list_session_replays." } };
|
|
2432
|
+
}
|
|
2433
|
+
const cfg = loadConfig();
|
|
2434
|
+
const r = pickOrError(cfg, input.project_id);
|
|
2435
|
+
if (!r.ok)
|
|
2436
|
+
return r.error;
|
|
2437
|
+
return await api.getReplaySnapshots(cfg, r.id, input.replay_id, input.source);
|
|
2438
|
+
}
|
|
2439
|
+
async function handleEvaluateFeatureFlag(input) {
|
|
2440
|
+
if (!input.distinct_id) {
|
|
2441
|
+
return { error: { code: "invalid_payload", message: "distinct_id is required.", next_action: "Pass the user identifier (same as case.affected_users[].distinct_id)." } };
|
|
2442
|
+
}
|
|
2443
|
+
const cfg = loadConfig();
|
|
2444
|
+
const r = pickOrError(cfg, input.project_id);
|
|
2445
|
+
if (!r.ok)
|
|
2446
|
+
return r.error;
|
|
2447
|
+
return await api.evaluateFeatureFlag(cfg, r.id, {
|
|
2448
|
+
distinct_id: input.distinct_id,
|
|
2449
|
+
key: input.key,
|
|
2450
|
+
person_properties: input.person_properties,
|
|
2451
|
+
groups: input.groups,
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
async function handleGetDistinctIdSummary(input) {
|
|
2455
|
+
if (!input.distinct_id) {
|
|
2456
|
+
return { error: { code: "invalid_payload", message: "distinct_id is required.", next_action: "Pass the user identifier." } };
|
|
2457
|
+
}
|
|
2458
|
+
const cfg = loadConfig();
|
|
2459
|
+
const r = pickOrError(cfg, input.project_id);
|
|
2460
|
+
if (!r.ok)
|
|
2461
|
+
return r.error;
|
|
2462
|
+
return await api.getDistinctIdSummary(cfg, r.id, input.distinct_id);
|
|
2463
|
+
}
|
|
2464
|
+
async function handleSurveyResponses(input) {
|
|
2465
|
+
if (!input.survey_id) {
|
|
2466
|
+
return { error: { code: "invalid_payload", message: "survey_id is required.", next_action: "Pass survey_id from agentry_list_surveys." } };
|
|
2467
|
+
}
|
|
2468
|
+
const cfg = loadConfig();
|
|
2469
|
+
const r = pickOrError(cfg, input.project_id);
|
|
2470
|
+
if (!r.ok)
|
|
2471
|
+
return r.error;
|
|
2472
|
+
return await api.getSurveyResponses(cfg, r.id, input.survey_id);
|
|
2473
|
+
}
|
|
2474
|
+
async function handleCreateAbTest(input) {
|
|
2475
|
+
if (!input.name) {
|
|
2476
|
+
return { error: { code: "invalid_payload", message: "name is required.", next_action: "Pass an A/B test name." } };
|
|
2477
|
+
}
|
|
2478
|
+
if (!input.success_event) {
|
|
2479
|
+
return { error: { code: "invalid_payload", message: "success_event is required.", next_action: "Pass the conversion event name (e.g. 'checkout_completed')." } };
|
|
2480
|
+
}
|
|
2481
|
+
if (!Array.isArray(input.variants) || input.variants.length < 2) {
|
|
2482
|
+
return { error: { code: "invalid_payload", message: "variants must be ≥2 entries.", next_action: "Pass variants: [{key:'control'},{key:'treatment'}]." } };
|
|
2483
|
+
}
|
|
2484
|
+
const cfg = loadConfig();
|
|
2485
|
+
const r = pickOrError(cfg, input.project_id);
|
|
2486
|
+
if (!r.ok)
|
|
2487
|
+
return r.error;
|
|
2488
|
+
return await api.createAbTest(cfg, r.id, {
|
|
2489
|
+
name: input.name,
|
|
2490
|
+
flag_key: input.flag_key,
|
|
2491
|
+
success_event: input.success_event,
|
|
2492
|
+
variants: input.variants,
|
|
2493
|
+
});
|
|
2494
|
+
}
|
|
2495
|
+
async function handleRecentChanges(input) {
|
|
2496
|
+
const cfg = loadConfig();
|
|
2497
|
+
if (!cfg.api_key) {
|
|
2498
|
+
return {
|
|
2499
|
+
error: {
|
|
2500
|
+
code: "no_key",
|
|
2501
|
+
message: "No API key on file.",
|
|
2502
|
+
next_action: "Call agentry_login.",
|
|
2503
|
+
},
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
return await api.listRecentChanges(cfg, {
|
|
2507
|
+
hours: input.hours,
|
|
2508
|
+
actionPrefix: input.action_prefix,
|
|
2509
|
+
resourceType: input.resource_type,
|
|
2510
|
+
projectId: input.project_id,
|
|
2511
|
+
limit: input.limit,
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2138
2514
|
async function handleListProjects() {
|
|
2139
2515
|
const cfg = loadConfig();
|
|
2140
2516
|
if (!cfg.api_key) {
|
|
@@ -2153,6 +2529,8 @@ async function handleListProjects() {
|
|
|
2153
2529
|
...p,
|
|
2154
2530
|
local_path: local?.local_path ?? null,
|
|
2155
2531
|
dsn_known_locally: Boolean(local?.dsn),
|
|
2532
|
+
analytics_ready: local?.analytics_ready ?? null,
|
|
2533
|
+
posthog_project_id: local?.posthog_project_id ?? null,
|
|
2156
2534
|
is_default: cfg.default_project_id === p.id,
|
|
2157
2535
|
};
|
|
2158
2536
|
});
|
|
@@ -2197,6 +2575,8 @@ async function handleCreateProject(input) {
|
|
|
2197
2575
|
dsn: resp.dsn,
|
|
2198
2576
|
local_path: input.local_path ?? null,
|
|
2199
2577
|
default_branch: resp.default_branch ?? input.default_branch ?? "main",
|
|
2578
|
+
analytics_ready: resp.analytics?.ready,
|
|
2579
|
+
posthog_project_id: resp.analytics?.posthog_project_id ?? null,
|
|
2200
2580
|
};
|
|
2201
2581
|
const nextCfg = {
|
|
2202
2582
|
...cfg,
|
|
@@ -2225,6 +2605,7 @@ async function handleCreateProject(input) {
|
|
|
2225
2605
|
logs_url: resp.logs_url,
|
|
2226
2606
|
analytics_url: resp.analytics_url,
|
|
2227
2607
|
deploys_url: resp.deploys_url,
|
|
2608
|
+
analytics: resp.analytics,
|
|
2228
2609
|
},
|
|
2229
2610
|
install_snippet: install,
|
|
2230
2611
|
next_action: resp.next_action ??
|
|
@@ -3038,17 +3419,17 @@ async function handleVerifyInstall(input) {
|
|
|
3038
3419
|
const analyticsDetail = checks.analytics?.detail ?? "";
|
|
3039
3420
|
const noPosthogProject = !checks.analytics?.ok &&
|
|
3040
3421
|
(analyticsDetail.includes("no_posthog_project") ||
|
|
3041
|
-
analyticsDetail.includes("
|
|
3422
|
+
analyticsDetail.includes("project has no PostHog project provisioned"));
|
|
3042
3423
|
const baseAction = failed.length === 0
|
|
3043
3424
|
? "Install verified. Errors land in agentry_list_cases; analytics flow to PostHog; deploys via agentry_list_deploys."
|
|
3044
3425
|
: noPosthogProject && failed.length === 1
|
|
3045
3426
|
? "Analytics is the only failed signal AND the cause is missing PostHog provisioning " +
|
|
3046
|
-
"(
|
|
3427
|
+
"(the project binding is missing). Call agentry_repair_analytics " +
|
|
3047
3428
|
"— it's idempotent and runs the same provisioning step. Then re-run agentry_verify_install. " +
|
|
3048
3429
|
"DO NOT re-run agentry_login for this."
|
|
3049
3430
|
: `Install incomplete. Failed signal types: ${failed.join(", ")}. ` +
|
|
3050
3431
|
(noPosthogProject
|
|
3051
|
-
? "Analytics failed because the
|
|
3432
|
+
? "Analytics failed because the project has no PostHog project provisioned — " +
|
|
3052
3433
|
"call agentry_repair_analytics, then re-run verify. "
|
|
3053
3434
|
: "") +
|
|
3054
3435
|
"For each failed type, re-read its corresponding step in agentry_install_guide and fix.";
|
|
@@ -3502,4 +3883,61 @@ async function handleListFeedback(input) {
|
|
|
3502
3883
|
const resp = await api.listFeedback(cfg, opts);
|
|
3503
3884
|
return resp;
|
|
3504
3885
|
}
|
|
3886
|
+
// ---------------------------------------------------------------------------
|
|
3887
|
+
// Team invites + member management (Phase 4)
|
|
3888
|
+
// ---------------------------------------------------------------------------
|
|
3889
|
+
async function handleInviteTeammate(input) {
|
|
3890
|
+
const cfg = loadConfig();
|
|
3891
|
+
const picked = pickProject(cfg, input.project_id);
|
|
3892
|
+
if (!picked) {
|
|
3893
|
+
return {
|
|
3894
|
+
error: {
|
|
3895
|
+
code: "no_project",
|
|
3896
|
+
message: "No project_id given and no default project set.",
|
|
3897
|
+
next_action: "Pass project_id, or call agentry_create_project.",
|
|
3898
|
+
},
|
|
3899
|
+
};
|
|
3900
|
+
}
|
|
3901
|
+
const body = { role: input.role };
|
|
3902
|
+
if (input.email)
|
|
3903
|
+
body.email = input.email;
|
|
3904
|
+
return await api.inviteTeammate(cfg, picked.id, body);
|
|
3905
|
+
}
|
|
3906
|
+
async function handleListMembers(projectId) {
|
|
3907
|
+
const cfg = loadConfig();
|
|
3908
|
+
const picked = pickProject(cfg, projectId);
|
|
3909
|
+
if (!picked) {
|
|
3910
|
+
return {
|
|
3911
|
+
error: {
|
|
3912
|
+
code: "no_project",
|
|
3913
|
+
message: "No project_id given and no default project set.",
|
|
3914
|
+
next_action: "Pass project_id.",
|
|
3915
|
+
},
|
|
3916
|
+
};
|
|
3917
|
+
}
|
|
3918
|
+
return await api.listMembers(cfg, picked.id);
|
|
3919
|
+
}
|
|
3920
|
+
async function handleRemoveMember(input) {
|
|
3921
|
+
const cfg = loadConfig();
|
|
3922
|
+
const picked = pickProject(cfg, input.project_id);
|
|
3923
|
+
if (!picked) {
|
|
3924
|
+
return {
|
|
3925
|
+
error: {
|
|
3926
|
+
code: "no_project",
|
|
3927
|
+
message: "No project_id given and no default project set.",
|
|
3928
|
+
next_action: "Pass project_id.",
|
|
3929
|
+
},
|
|
3930
|
+
};
|
|
3931
|
+
}
|
|
3932
|
+
if (!input.user_id) {
|
|
3933
|
+
return {
|
|
3934
|
+
error: {
|
|
3935
|
+
code: "invalid_payload",
|
|
3936
|
+
message: "user_id is required.",
|
|
3937
|
+
next_action: "Call agentry_list_members to find the user_id to remove.",
|
|
3938
|
+
},
|
|
3939
|
+
};
|
|
3940
|
+
}
|
|
3941
|
+
return await api.removeMember(cfg, picked.id, input.user_id);
|
|
3942
|
+
}
|
|
3505
3943
|
//# sourceMappingURL=tools.js.map
|