@vibekiln/cutline-mcp-cli 0.13.0 → 0.15.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 +15 -0
- package/dist/auth/callback.d.ts +1 -1
- package/dist/auth/callback.js +9 -1
- package/dist/commands/login.js +4 -1
- package/dist/commands/serve.d.ts +4 -0
- package/dist/commands/serve.js +19 -6
- package/dist/commands/setup.js +17 -8
- package/dist/index.js +4 -2
- package/dist/servers/{chunk-RUCYK3TR.js → chunk-FHWY2TYO.js} +349 -89
- package/dist/servers/chunk-Q5V4VTF5.js +3180 -0
- package/dist/servers/{chunk-KMUSQOTJ.js → chunk-WTLGBZBN.js} +15 -1
- package/dist/servers/cutline-server.js +1218 -4011
- package/dist/servers/{data-client-RY2DCLME.js → data-client-3OADPXXN.js} +45 -3
- package/dist/servers/exploration-server.js +1 -1
- package/dist/servers/integrations-server.js +2 -2
- package/dist/servers/output-server.js +1 -1
- package/dist/servers/premortem-server.js +30 -65
- package/dist/servers/slopburn-server.js +10069 -0
- package/dist/servers/tools-server.js +67 -6
- package/package.json +5 -3
- package/server.json +1 -1
|
@@ -3,6 +3,21 @@ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import os from "os";
|
|
6
|
+
|
|
7
|
+
// ../mcp/dist/mcp/src/auth-cache.js
|
|
8
|
+
function buildTokenCredentialKey(refreshToken, environment) {
|
|
9
|
+
return `${environment ?? "production"}:${refreshToken}`;
|
|
10
|
+
}
|
|
11
|
+
function shouldReuseResolvedAuthCache(options) {
|
|
12
|
+
const now = options.now ?? Date.now();
|
|
13
|
+
if (!options.cachedIdToken || !options.cachedBaseUrl)
|
|
14
|
+
return false;
|
|
15
|
+
if (!options.tokenExpiresAt || now >= options.tokenExpiresAt)
|
|
16
|
+
return false;
|
|
17
|
+
return options.cachedCredentialKey === buildTokenCredentialKey(options.refreshToken, options.environment);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ../mcp/dist/mcp/src/utils.js
|
|
6
21
|
function decodeIdTokenLocally(idToken) {
|
|
7
22
|
const parts = idToken.split(".");
|
|
8
23
|
if (parts.length !== 3) {
|
|
@@ -162,34 +177,63 @@ function cleanupTokenCache() {
|
|
|
162
177
|
}
|
|
163
178
|
lastCleanup = now;
|
|
164
179
|
}
|
|
165
|
-
function getCachedToken(refreshToken) {
|
|
180
|
+
function getCachedToken(refreshToken, environment) {
|
|
181
|
+
const cacheKey = buildTokenCredentialKey(refreshToken, environment);
|
|
166
182
|
if (Date.now() - lastCleanup > CACHE_CLEANUP_INTERVAL) {
|
|
167
183
|
cleanupTokenCache();
|
|
168
184
|
}
|
|
169
|
-
const cached = tokenCache.get(
|
|
185
|
+
const cached = tokenCache.get(cacheKey);
|
|
170
186
|
if (!cached) {
|
|
171
187
|
return null;
|
|
172
188
|
}
|
|
173
189
|
if (Date.now() >= cached.expiresAt) {
|
|
174
|
-
tokenCache.delete(
|
|
190
|
+
tokenCache.delete(cacheKey);
|
|
175
191
|
return null;
|
|
176
192
|
}
|
|
177
193
|
cached.lastUsed = Date.now();
|
|
178
|
-
tokenCache.delete(
|
|
179
|
-
tokenCache.set(
|
|
194
|
+
tokenCache.delete(cacheKey);
|
|
195
|
+
tokenCache.set(cacheKey, cached);
|
|
180
196
|
return cached.idToken;
|
|
181
197
|
}
|
|
182
|
-
function setCachedToken(refreshToken, idToken, expiresAt) {
|
|
198
|
+
function setCachedToken(refreshToken, idToken, expiresAt, environment) {
|
|
199
|
+
const cacheKey = buildTokenCredentialKey(refreshToken, environment);
|
|
183
200
|
if (tokenCache.size >= MAX_CACHE_SIZE) {
|
|
184
201
|
cleanupTokenCache();
|
|
185
202
|
}
|
|
186
|
-
tokenCache.delete(
|
|
187
|
-
tokenCache.set(
|
|
203
|
+
tokenCache.delete(cacheKey);
|
|
204
|
+
tokenCache.set(cacheKey, {
|
|
188
205
|
idToken,
|
|
189
206
|
expiresAt,
|
|
190
207
|
lastUsed: Date.now()
|
|
191
208
|
});
|
|
192
209
|
}
|
|
210
|
+
function clearCachedAutoAuthState(options) {
|
|
211
|
+
if (!options?.refreshToken) {
|
|
212
|
+
tokenCache.clear();
|
|
213
|
+
cachedApiKey = null;
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
tokenCache.delete(buildTokenCredentialKey(options.refreshToken, options.environment));
|
|
217
|
+
}
|
|
218
|
+
async function resolveStoredIdToken(options) {
|
|
219
|
+
const { refreshToken, environment, forceRefresh = false } = options;
|
|
220
|
+
if (!forceRefresh) {
|
|
221
|
+
const cached = getCachedToken(refreshToken, environment);
|
|
222
|
+
if (cached) {
|
|
223
|
+
return cached;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const apiKeyToUse = await getFirebaseApiKey(environment);
|
|
227
|
+
try {
|
|
228
|
+
const idToken = await exchangeRefreshToken(refreshToken, apiKeyToUse);
|
|
229
|
+
setCachedToken(refreshToken, idToken, Date.now() + 50 * 60 * 1e3, environment);
|
|
230
|
+
return idToken;
|
|
231
|
+
} catch (e) {
|
|
232
|
+
console.error("Token exchange failed:", e);
|
|
233
|
+
clearCachedAutoAuthState({ refreshToken, environment });
|
|
234
|
+
return void 0;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
193
237
|
var cachedApiKey = null;
|
|
194
238
|
var API_KEY_CACHE_TTL = 36e5;
|
|
195
239
|
async function getFirebaseApiKey(environment) {
|
|
@@ -354,53 +398,82 @@ async function getStoredToken() {
|
|
|
354
398
|
}
|
|
355
399
|
return null;
|
|
356
400
|
}
|
|
401
|
+
function getForcedEnvironment() {
|
|
402
|
+
const raw = process.env.CUTLINE_ENV?.trim().toLowerCase();
|
|
403
|
+
if (raw === "staging")
|
|
404
|
+
return "staging";
|
|
405
|
+
if (raw === "production" || raw === "prod")
|
|
406
|
+
return "production";
|
|
407
|
+
return void 0;
|
|
408
|
+
}
|
|
409
|
+
function mergeEnvironmentOrThrow(resolved, sourceLabel) {
|
|
410
|
+
const forced = getForcedEnvironment();
|
|
411
|
+
if (!forced)
|
|
412
|
+
return resolved;
|
|
413
|
+
if (resolved && resolved !== forced) {
|
|
414
|
+
throw new McpError(ErrorCode.InvalidRequest, `Environment mismatch: CUTLINE_ENV=${forced} but ${sourceLabel} is ${resolved}. ` + `Run cutline-mcp login ${forced === "staging" ? "--staging" : ""}`.trim());
|
|
415
|
+
}
|
|
416
|
+
return forced;
|
|
417
|
+
}
|
|
357
418
|
async function requirePremiumWithAutoAuth(authToken) {
|
|
358
419
|
let idToken = authToken;
|
|
359
|
-
let environment;
|
|
420
|
+
let environment = getForcedEnvironment();
|
|
421
|
+
let storedTokenInfo = null;
|
|
360
422
|
if (!idToken) {
|
|
361
|
-
|
|
362
|
-
environment = storedTokenInfo?.environment;
|
|
423
|
+
storedTokenInfo = await getStoredToken();
|
|
424
|
+
environment = mergeEnvironmentOrThrow(storedTokenInfo?.environment, "stored refresh token");
|
|
363
425
|
if (storedTokenInfo) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
idToken = cached;
|
|
369
|
-
} else {
|
|
370
|
-
try {
|
|
371
|
-
idToken = await exchangeRefreshToken(refreshToken, apiKeyToUse);
|
|
372
|
-
setCachedToken(refreshToken, idToken, Date.now() + 50 * 60 * 1e3);
|
|
373
|
-
} catch (e) {
|
|
374
|
-
console.error("Token exchange failed:", e);
|
|
375
|
-
tokenCache.delete(refreshToken);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
426
|
+
idToken = await resolveStoredIdToken({
|
|
427
|
+
refreshToken: storedTokenInfo.refreshToken,
|
|
428
|
+
environment: environment || "production"
|
|
429
|
+
});
|
|
378
430
|
}
|
|
379
431
|
}
|
|
380
|
-
|
|
432
|
+
try {
|
|
433
|
+
return await requirePremium(idToken, environment);
|
|
434
|
+
} catch (error) {
|
|
435
|
+
if (!authToken && storedTokenInfo) {
|
|
436
|
+
clearCachedAutoAuthState({
|
|
437
|
+
refreshToken: storedTokenInfo.refreshToken,
|
|
438
|
+
environment: environment || "production"
|
|
439
|
+
});
|
|
440
|
+
const refreshedIdToken = await resolveStoredIdToken({
|
|
441
|
+
refreshToken: storedTokenInfo.refreshToken,
|
|
442
|
+
environment: environment || "production",
|
|
443
|
+
forceRefresh: true
|
|
444
|
+
});
|
|
445
|
+
return await requirePremium(refreshedIdToken, environment);
|
|
446
|
+
}
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
381
449
|
}
|
|
382
450
|
async function requireAuthOnly(authToken) {
|
|
383
451
|
let idToken = authToken;
|
|
452
|
+
let storedTokenInfo = null;
|
|
453
|
+
let environment;
|
|
384
454
|
if (!idToken) {
|
|
385
|
-
|
|
455
|
+
storedTokenInfo = await getStoredToken();
|
|
386
456
|
if (storedTokenInfo) {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
} else {
|
|
393
|
-
try {
|
|
394
|
-
idToken = await exchangeRefreshToken(refreshToken, apiKeyToUse);
|
|
395
|
-
setCachedToken(refreshToken, idToken, Date.now() + 50 * 60 * 1e3);
|
|
396
|
-
} catch (e) {
|
|
397
|
-
console.error("Token exchange failed:", e);
|
|
398
|
-
tokenCache.delete(refreshToken);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
457
|
+
environment = mergeEnvironmentOrThrow(storedTokenInfo.environment, "stored refresh token");
|
|
458
|
+
idToken = await resolveStoredIdToken({
|
|
459
|
+
refreshToken: storedTokenInfo.refreshToken,
|
|
460
|
+
environment: environment || "production"
|
|
461
|
+
});
|
|
401
462
|
}
|
|
402
463
|
}
|
|
403
|
-
|
|
464
|
+
let decoded = await validateAuth(idToken);
|
|
465
|
+
if (!decoded && !authToken && storedTokenInfo) {
|
|
466
|
+
clearCachedAutoAuthState({
|
|
467
|
+
refreshToken: storedTokenInfo.refreshToken,
|
|
468
|
+
environment: environment || "production"
|
|
469
|
+
});
|
|
470
|
+
const refreshedIdToken = await resolveStoredIdToken({
|
|
471
|
+
refreshToken: storedTokenInfo.refreshToken,
|
|
472
|
+
environment: environment || "production",
|
|
473
|
+
forceRefresh: true
|
|
474
|
+
});
|
|
475
|
+
decoded = await validateAuth(refreshedIdToken);
|
|
476
|
+
}
|
|
404
477
|
if (!decoded) {
|
|
405
478
|
throw new McpError(ErrorCode.InvalidRequest, "Authentication required. Run 'cutline-mcp login' to authenticate.");
|
|
406
479
|
}
|
|
@@ -420,10 +493,59 @@ async function resolveAuthContextFree(authToken) {
|
|
|
420
493
|
function getBaseUrl(environment) {
|
|
421
494
|
return environment === "staging" ? "https://us-central1-cutline-staging.cloudfunctions.net" : "https://us-central1-cutline-prod.cloudfunctions.net";
|
|
422
495
|
}
|
|
496
|
+
var STAGING_UNSUFFIXED_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
497
|
+
// Intentionally deployed without env suffix in staging.
|
|
498
|
+
"applyWikiEdits",
|
|
499
|
+
"mcpGenerateTokenG2",
|
|
500
|
+
"mcpSubscriptionStatus"
|
|
501
|
+
]);
|
|
502
|
+
function resolveFunctionEndpointName(functionName, environment) {
|
|
503
|
+
if (environment !== "staging")
|
|
504
|
+
return functionName;
|
|
505
|
+
if (STAGING_UNSUFFIXED_FUNCTIONS.has(functionName))
|
|
506
|
+
return functionName;
|
|
507
|
+
return `${functionName}-stg`;
|
|
508
|
+
}
|
|
423
509
|
function getSiteUrl(environment) {
|
|
424
510
|
return environment === "staging" ? "https://cutline-staging.web.app" : "https://thecutline.ai";
|
|
425
511
|
}
|
|
512
|
+
function getAppApiBaseUrl(environment) {
|
|
513
|
+
const override = process.env.CUTLINE_APP_API_BASE_URL?.trim() || process.env.CUTLINE_SSR_BASE_URL?.trim() || process.env.SSR_BASE_URL?.trim();
|
|
514
|
+
if (override) {
|
|
515
|
+
return override.replace(/\/+$/, "");
|
|
516
|
+
}
|
|
517
|
+
return environment === "staging" ? "https://ssrcutlinestaging-vi2gngz52a-uc.a.run.app" : "https://ssrcutline-y74odqxy3q-uc.a.run.app";
|
|
518
|
+
}
|
|
519
|
+
function getForcedEnvironment2() {
|
|
520
|
+
const raw = process.env.CUTLINE_ENV?.trim().toLowerCase();
|
|
521
|
+
if (raw === "staging")
|
|
522
|
+
return "staging";
|
|
523
|
+
if (raw === "production" || raw === "prod")
|
|
524
|
+
return "production";
|
|
525
|
+
return void 0;
|
|
526
|
+
}
|
|
527
|
+
function mergeEnvironment(resolved, sourceLabel) {
|
|
528
|
+
const forced = getForcedEnvironment2();
|
|
529
|
+
if (!forced) {
|
|
530
|
+
return resolved || "production";
|
|
531
|
+
}
|
|
532
|
+
if (resolved && resolved !== forced) {
|
|
533
|
+
throw new Error(`Environment mismatch: CUTLINE_ENV=${forced} but ${sourceLabel} is ${resolved}. ` + `Run cutline-mcp login ${forced === "staging" ? "--staging" : ""}`.trim());
|
|
534
|
+
}
|
|
535
|
+
return forced;
|
|
536
|
+
}
|
|
537
|
+
var __dataClientInternals = {
|
|
538
|
+
getBaseUrl,
|
|
539
|
+
resolveFunctionEndpointName,
|
|
540
|
+
getSiteUrl,
|
|
541
|
+
getAppApiBaseUrl,
|
|
542
|
+
mergeEnvironment
|
|
543
|
+
};
|
|
426
544
|
async function getPublicSiteUrlForCurrentAuth() {
|
|
545
|
+
const forced = getForcedEnvironment2();
|
|
546
|
+
if (forced) {
|
|
547
|
+
return getSiteUrl(forced);
|
|
548
|
+
}
|
|
427
549
|
const stored = await getStoredToken();
|
|
428
550
|
if (stored?.environment) {
|
|
429
551
|
return getSiteUrl(stored.environment);
|
|
@@ -436,7 +558,14 @@ async function getPublicSiteUrlForCurrentAuth() {
|
|
|
436
558
|
}
|
|
437
559
|
var cachedBaseUrl;
|
|
438
560
|
var cachedIdToken;
|
|
561
|
+
var cachedCredentialKey;
|
|
439
562
|
var tokenExpiresAt = 0;
|
|
563
|
+
function clearResolvedAuthCache() {
|
|
564
|
+
cachedBaseUrl = void 0;
|
|
565
|
+
cachedIdToken = void 0;
|
|
566
|
+
cachedCredentialKey = void 0;
|
|
567
|
+
tokenExpiresAt = 0;
|
|
568
|
+
}
|
|
440
569
|
var FIREBASE_API_KEY_CACHE = {};
|
|
441
570
|
async function getFirebaseApiKey2(environment) {
|
|
442
571
|
const envKey = process.env.FIREBASE_API_KEY || process.env.NEXT_PUBLIC_FIREBASE_API_KEY;
|
|
@@ -478,50 +607,76 @@ async function exchangeRefreshForId(refreshToken, environment) {
|
|
|
478
607
|
async function resolveAuth() {
|
|
479
608
|
const envApiKeyInfo = getStoredApiKey({ includeConfig: false });
|
|
480
609
|
if (envApiKeyInfo) {
|
|
610
|
+
const env = mergeEnvironment(envApiKeyInfo.environment, "CUTLINE_API_KEY credentials");
|
|
481
611
|
return {
|
|
482
|
-
baseUrl: getBaseUrl(
|
|
483
|
-
idToken: envApiKeyInfo.apiKey
|
|
612
|
+
baseUrl: getBaseUrl(env),
|
|
613
|
+
idToken: envApiKeyInfo.apiKey,
|
|
614
|
+
environment: env
|
|
484
615
|
};
|
|
485
616
|
}
|
|
486
|
-
if (cachedIdToken && Date.now() < tokenExpiresAt && cachedBaseUrl) {
|
|
487
|
-
return { baseUrl: cachedBaseUrl, idToken: cachedIdToken };
|
|
488
|
-
}
|
|
489
617
|
const stored = await getStoredToken();
|
|
490
618
|
if (stored) {
|
|
491
|
-
const env = stored.environment
|
|
619
|
+
const env = mergeEnvironment(stored.environment, "stored refresh token");
|
|
620
|
+
const credentialKey = buildTokenCredentialKey(stored.refreshToken, env);
|
|
621
|
+
if (shouldReuseResolvedAuthCache({
|
|
622
|
+
cachedCredentialKey,
|
|
623
|
+
cachedIdToken,
|
|
624
|
+
cachedBaseUrl,
|
|
625
|
+
tokenExpiresAt,
|
|
626
|
+
refreshToken: stored.refreshToken,
|
|
627
|
+
environment: env
|
|
628
|
+
})) {
|
|
629
|
+
return { baseUrl: getBaseUrl(env), idToken: cachedIdToken, environment: env };
|
|
630
|
+
}
|
|
631
|
+
if (cachedCredentialKey && cachedCredentialKey !== credentialKey) {
|
|
632
|
+
clearResolvedAuthCache();
|
|
633
|
+
}
|
|
492
634
|
const baseUrl = getBaseUrl(env);
|
|
493
635
|
const idToken = await exchangeRefreshForId(stored.refreshToken, env);
|
|
494
636
|
cachedBaseUrl = baseUrl;
|
|
495
637
|
cachedIdToken = idToken;
|
|
638
|
+
cachedCredentialKey = credentialKey;
|
|
496
639
|
tokenExpiresAt = Date.now() + 50 * 60 * 1e3;
|
|
497
|
-
return { baseUrl, idToken };
|
|
640
|
+
return { baseUrl, idToken, environment: env };
|
|
641
|
+
}
|
|
642
|
+
if (cachedCredentialKey) {
|
|
643
|
+
clearResolvedAuthCache();
|
|
498
644
|
}
|
|
499
645
|
const configApiKeyInfo = getStoredApiKey();
|
|
500
646
|
if (configApiKeyInfo) {
|
|
647
|
+
const env = mergeEnvironment(configApiKeyInfo.environment, "stored API key");
|
|
501
648
|
return {
|
|
502
|
-
baseUrl: getBaseUrl(
|
|
503
|
-
idToken: configApiKeyInfo.apiKey
|
|
649
|
+
baseUrl: getBaseUrl(env),
|
|
650
|
+
idToken: configApiKeyInfo.apiKey,
|
|
651
|
+
environment: env
|
|
504
652
|
};
|
|
505
653
|
}
|
|
506
654
|
throw new Error("Not authenticated. Run 'cutline-mcp login' or set CUTLINE_API_KEY.");
|
|
507
655
|
}
|
|
656
|
+
async function performAuthedRequest(makeRequest) {
|
|
657
|
+
let auth = await resolveAuth();
|
|
658
|
+
let response = await makeRequest(auth);
|
|
659
|
+
if (response.status === 401) {
|
|
660
|
+
clearResolvedAuthCache();
|
|
661
|
+
auth = await resolveAuth();
|
|
662
|
+
response = await makeRequest(auth);
|
|
663
|
+
}
|
|
664
|
+
return response;
|
|
665
|
+
}
|
|
508
666
|
async function proxy(action, params = {}) {
|
|
509
|
-
const { baseUrl, idToken }
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
667
|
+
const res = await performAuthedRequest(async ({ baseUrl, idToken, environment }) => {
|
|
668
|
+
const endpoint = resolveFunctionEndpointName("mcpDataProxy", environment);
|
|
669
|
+
return fetch(`${baseUrl}/${endpoint}`, {
|
|
670
|
+
method: "POST",
|
|
671
|
+
headers: {
|
|
672
|
+
"Content-Type": "application/json",
|
|
673
|
+
Authorization: `Bearer ${idToken}`
|
|
674
|
+
},
|
|
675
|
+
body: JSON.stringify({ action, params }),
|
|
676
|
+
signal: AbortSignal.timeout(3e4)
|
|
677
|
+
});
|
|
518
678
|
});
|
|
519
679
|
if (!res.ok) {
|
|
520
|
-
if (res.status === 401) {
|
|
521
|
-
cachedIdToken = void 0;
|
|
522
|
-
tokenExpiresAt = 0;
|
|
523
|
-
throw new Error("Authentication expired \u2014 retrying on next call");
|
|
524
|
-
}
|
|
525
680
|
const body = await res.text().catch(() => "");
|
|
526
681
|
throw new Error(`mcpDataProxy ${action} failed (${res.status}): ${body.slice(0, 200)}`);
|
|
527
682
|
}
|
|
@@ -569,6 +724,30 @@ async function listExplorationSessions(collection, limit) {
|
|
|
569
724
|
const res = await proxy("exploration.list", { collection, limit });
|
|
570
725
|
return res.docs;
|
|
571
726
|
}
|
|
727
|
+
async function listEngagements(opts) {
|
|
728
|
+
const res = await proxy("engagement.list", opts || {});
|
|
729
|
+
return res.docs;
|
|
730
|
+
}
|
|
731
|
+
async function getEngagement(id) {
|
|
732
|
+
const res = await proxy("engagement.get", { id });
|
|
733
|
+
return res.doc;
|
|
734
|
+
}
|
|
735
|
+
async function createEngagement(data) {
|
|
736
|
+
return proxy("engagement.create", data);
|
|
737
|
+
}
|
|
738
|
+
async function updateEngagement(id, data) {
|
|
739
|
+
return proxy("engagement.update", { id, ...data });
|
|
740
|
+
}
|
|
741
|
+
async function attachDeepDiveToEngagement(engagementId, deepDiveId) {
|
|
742
|
+
return proxy("engagement.attachDeepDive", { engagementId, deepDiveId });
|
|
743
|
+
}
|
|
744
|
+
async function summarizeEngagement(id) {
|
|
745
|
+
const res = await proxy("engagement.summarize", { id });
|
|
746
|
+
return res.doc;
|
|
747
|
+
}
|
|
748
|
+
async function selectEngagementProduct(id, primaryProductId) {
|
|
749
|
+
return proxy("engagement.selectProduct", { id, primaryProductId });
|
|
750
|
+
}
|
|
572
751
|
async function getAllEntities(productId) {
|
|
573
752
|
const res = await proxy("graph.getEntities", { productId });
|
|
574
753
|
return res.docs.map((d) => ({ ...d, ingested_at: new Date(d.ingested_at?._seconds ? d.ingested_at._seconds * 1e3 : d.ingested_at) }));
|
|
@@ -845,45 +1024,67 @@ async function getPersona(personaId) {
|
|
|
845
1024
|
const res = await proxy("persona.get", { id: personaId });
|
|
846
1025
|
return res.doc;
|
|
847
1026
|
}
|
|
1027
|
+
async function getProductAgenda(params) {
|
|
1028
|
+
return proxy("journey.product_agenda", params);
|
|
1029
|
+
}
|
|
1030
|
+
async function getDiscoverabilityAgenda(params) {
|
|
1031
|
+
return getProductAgenda(params);
|
|
1032
|
+
}
|
|
848
1033
|
async function callCF(functionName, body, timeoutMs = 6e4) {
|
|
849
|
-
const { baseUrl, idToken }
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
1034
|
+
const res = await performAuthedRequest(async ({ baseUrl, idToken, environment }) => {
|
|
1035
|
+
const endpoint = resolveFunctionEndpointName(functionName, environment);
|
|
1036
|
+
return fetch(`${baseUrl}/${endpoint}`, {
|
|
1037
|
+
method: "POST",
|
|
1038
|
+
headers: {
|
|
1039
|
+
"Content-Type": "application/json",
|
|
1040
|
+
Authorization: `Bearer ${idToken}`
|
|
1041
|
+
},
|
|
1042
|
+
body: JSON.stringify(body),
|
|
1043
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
1044
|
+
});
|
|
858
1045
|
});
|
|
859
1046
|
if (!res.ok) {
|
|
860
|
-
if (res.status === 401) {
|
|
861
|
-
cachedIdToken = void 0;
|
|
862
|
-
tokenExpiresAt = 0;
|
|
863
|
-
}
|
|
864
1047
|
const text = await res.text().catch(() => "");
|
|
865
1048
|
throw new Error(`CF ${functionName} failed (${res.status}): ${text.slice(0, 300)}`);
|
|
866
1049
|
}
|
|
867
1050
|
return res.json();
|
|
868
1051
|
}
|
|
869
1052
|
async function callCFGet(functionName, query, timeoutMs = 3e4) {
|
|
870
|
-
const { baseUrl, idToken }
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1053
|
+
const res = await performAuthedRequest(async ({ baseUrl, idToken, environment }) => {
|
|
1054
|
+
const endpoint = resolveFunctionEndpointName(functionName, environment);
|
|
1055
|
+
const qs = new URLSearchParams(query).toString();
|
|
1056
|
+
return fetch(`${baseUrl}/${endpoint}?${qs}`, {
|
|
1057
|
+
method: "GET",
|
|
1058
|
+
headers: { Authorization: `Bearer ${idToken}` },
|
|
1059
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
1060
|
+
});
|
|
876
1061
|
});
|
|
877
1062
|
if (!res.ok) {
|
|
878
|
-
if (res.status === 401) {
|
|
879
|
-
cachedIdToken = void 0;
|
|
880
|
-
tokenExpiresAt = 0;
|
|
881
|
-
}
|
|
882
1063
|
const text = await res.text().catch(() => "");
|
|
883
1064
|
throw new Error(`CF ${functionName} failed (${res.status}): ${text.slice(0, 300)}`);
|
|
884
1065
|
}
|
|
885
1066
|
return res.json();
|
|
886
1067
|
}
|
|
1068
|
+
async function callAppApi(apiPath, body, timeoutMs = 12e4) {
|
|
1069
|
+
const normalizedPath = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
|
|
1070
|
+
const response = await performAuthedRequest(async ({ idToken, environment }) => {
|
|
1071
|
+
const appBaseUrl = getAppApiBaseUrl(environment);
|
|
1072
|
+
return fetch(`${appBaseUrl}${normalizedPath}`, {
|
|
1073
|
+
method: "POST",
|
|
1074
|
+
headers: {
|
|
1075
|
+
"Content-Type": "application/json",
|
|
1076
|
+
Authorization: `Bearer ${idToken}`
|
|
1077
|
+
},
|
|
1078
|
+
body: JSON.stringify(body),
|
|
1079
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
1080
|
+
});
|
|
1081
|
+
});
|
|
1082
|
+
if (!response.ok) {
|
|
1083
|
+
const text = await response.text().catch(() => "");
|
|
1084
|
+
throw new Error(`API ${normalizedPath} failed (${response.status}): ${text.slice(0, 300)}`);
|
|
1085
|
+
}
|
|
1086
|
+
return response.json();
|
|
1087
|
+
}
|
|
887
1088
|
async function cfGenerateTrialRun(prompt) {
|
|
888
1089
|
const res = await callCF("trialRun", { prompt });
|
|
889
1090
|
return res.text;
|
|
@@ -923,6 +1124,9 @@ async function cfPremortemRun(input) {
|
|
|
923
1124
|
async function cfPremortemStart(input) {
|
|
924
1125
|
return callCF("premortemStart", input, 3e4);
|
|
925
1126
|
}
|
|
1127
|
+
async function cfPremortemStatus(jobId) {
|
|
1128
|
+
return callCFGet("premortemStatus", { id: jobId }, 3e4);
|
|
1129
|
+
}
|
|
926
1130
|
async function cfPremortemKick(jobId) {
|
|
927
1131
|
return callCF("premortemKick", { id: jobId }, 6e5);
|
|
928
1132
|
}
|
|
@@ -1017,6 +1221,41 @@ async function getPodcastIntroductions(productId, format = "json") {
|
|
|
1017
1221
|
}
|
|
1018
1222
|
return { format: "json", participants: introductions };
|
|
1019
1223
|
}
|
|
1224
|
+
async function upsertSlopburnRun(runId, data) {
|
|
1225
|
+
return proxy("slopburn.upsertRun", { runId, data });
|
|
1226
|
+
}
|
|
1227
|
+
async function getSlopburnRun(runId) {
|
|
1228
|
+
const res = await proxy("slopburn.getRun", { runId });
|
|
1229
|
+
return res.doc;
|
|
1230
|
+
}
|
|
1231
|
+
async function listSlopburnRuns(limit = 20) {
|
|
1232
|
+
const res = await proxy("slopburn.listRuns", { limit });
|
|
1233
|
+
return res.docs;
|
|
1234
|
+
}
|
|
1235
|
+
async function getGeneratedTestArtifactBundle(artifactBundleId) {
|
|
1236
|
+
const res = await proxy("verification.getGeneratedTestArtifactBundle", { artifactBundleId });
|
|
1237
|
+
return res.doc;
|
|
1238
|
+
}
|
|
1239
|
+
async function enqueueVerificationCycleJob(input) {
|
|
1240
|
+
return proxy("verification.enqueueCycleJob", input);
|
|
1241
|
+
}
|
|
1242
|
+
async function getVerificationCycleJob(jobId) {
|
|
1243
|
+
const res = await proxy("verification.getCycleJob", { jobId });
|
|
1244
|
+
return res.doc;
|
|
1245
|
+
}
|
|
1246
|
+
async function getVerificationTestExecutionJob(jobId) {
|
|
1247
|
+
const res = await proxy("verification.getTestExecutionJob", { jobId });
|
|
1248
|
+
return res.doc;
|
|
1249
|
+
}
|
|
1250
|
+
async function submitVerificationTestExecution(input) {
|
|
1251
|
+
return proxy("verification.submitTestExecution", input);
|
|
1252
|
+
}
|
|
1253
|
+
async function runVerificationCycle(input) {
|
|
1254
|
+
return callAppApi("/api/verification/cycle", input, 6e5);
|
|
1255
|
+
}
|
|
1256
|
+
async function ingestVerificationIntent(input) {
|
|
1257
|
+
return callAppApi("/api/verification/ingest-intent", input, 12e4);
|
|
1258
|
+
}
|
|
1020
1259
|
|
|
1021
1260
|
export {
|
|
1022
1261
|
validateRequestSize,
|
|
@@ -1027,6 +1266,7 @@ export {
|
|
|
1027
1266
|
getStoredInstallId,
|
|
1028
1267
|
requirePremiumWithAutoAuth,
|
|
1029
1268
|
resolveAuthContextFree,
|
|
1269
|
+
__dataClientInternals,
|
|
1030
1270
|
getPublicSiteUrlForCurrentAuth,
|
|
1031
1271
|
listPremortems,
|
|
1032
1272
|
getPremortem,
|
|
@@ -1040,6 +1280,13 @@ export {
|
|
|
1040
1280
|
getExplorationSession,
|
|
1041
1281
|
updateExplorationSession,
|
|
1042
1282
|
listExplorationSessions,
|
|
1283
|
+
listEngagements,
|
|
1284
|
+
getEngagement,
|
|
1285
|
+
createEngagement,
|
|
1286
|
+
updateEngagement,
|
|
1287
|
+
attachDeepDiveToEngagement,
|
|
1288
|
+
summarizeEngagement,
|
|
1289
|
+
selectEngagementProduct,
|
|
1043
1290
|
getAllEntities,
|
|
1044
1291
|
upsertEntities,
|
|
1045
1292
|
addEntity,
|
|
@@ -1084,6 +1331,8 @@ export {
|
|
|
1084
1331
|
updateScanRateLimit,
|
|
1085
1332
|
listPersonas,
|
|
1086
1333
|
getPersona,
|
|
1334
|
+
getProductAgenda,
|
|
1335
|
+
getDiscoverabilityAgenda,
|
|
1087
1336
|
cfGenerateTrialRun,
|
|
1088
1337
|
cfGenerateChatSuggestion,
|
|
1089
1338
|
cfGenerateAnswer,
|
|
@@ -1096,6 +1345,7 @@ export {
|
|
|
1096
1345
|
cfApplyEdits,
|
|
1097
1346
|
cfPremortemRun,
|
|
1098
1347
|
cfPremortemStart,
|
|
1348
|
+
cfPremortemStatus,
|
|
1099
1349
|
cfPremortemKick,
|
|
1100
1350
|
cfPremortemChatAgent,
|
|
1101
1351
|
cfRegenAssumptions,
|
|
@@ -1105,5 +1355,15 @@ export {
|
|
|
1105
1355
|
cfExplorationAgent,
|
|
1106
1356
|
cfConsultingDiscoveryAgent,
|
|
1107
1357
|
cfCreateLinearIssues,
|
|
1108
|
-
getPodcastIntroductions
|
|
1358
|
+
getPodcastIntroductions,
|
|
1359
|
+
upsertSlopburnRun,
|
|
1360
|
+
getSlopburnRun,
|
|
1361
|
+
listSlopburnRuns,
|
|
1362
|
+
getGeneratedTestArtifactBundle,
|
|
1363
|
+
enqueueVerificationCycleJob,
|
|
1364
|
+
getVerificationCycleJob,
|
|
1365
|
+
getVerificationTestExecutionJob,
|
|
1366
|
+
submitVerificationTestExecution,
|
|
1367
|
+
runVerificationCycle,
|
|
1368
|
+
ingestVerificationIntent
|
|
1109
1369
|
};
|