@adminide-stack/yantra-mobile 12.0.51 → 12.0.52-alpha.1
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/lib/components/KeyboardComposerDock.js +4 -3
- package/lib/components/KeyboardComposerDock.js.map +1 -1
- package/lib/features/attachments/buildGatewayMedia.js +22 -15
- package/lib/features/attachments/buildGatewayMedia.js.map +1 -1
- package/lib/features/attachments/uploadChatAttachments.js +6 -4
- package/lib/features/attachments/uploadChatAttachments.js.map +1 -1
- package/lib/features/attachments/useImageAttachments.js +63 -17
- package/lib/features/attachments/useImageAttachments.js.map +1 -1
- package/lib/features/chat/AskUserCard.js +367 -0
- package/lib/features/chat/AskUserCard.js.map +1 -0
- package/lib/features/chat/ChatTranscript.js +203 -98
- package/lib/features/chat/ChatTranscript.js.map +1 -1
- package/lib/features/chat/ToolTimeline.js +118 -0
- package/lib/features/chat/ToolTimeline.js.map +1 -0
- package/lib/features/chat/askUser.js +136 -0
- package/lib/features/chat/askUser.js.map +1 -0
- package/lib/features/chat/streamingMarkdown.js +7 -0
- package/lib/features/chat/streamingMarkdown.js.map +1 -0
- package/lib/features/chat/toolActivity.js +77 -0
- package/lib/features/chat/toolActivity.js.map +1 -0
- package/lib/features/chat/transcriptGroups.js +29 -0
- package/lib/features/chat/transcriptGroups.js.map +1 -0
- package/lib/hooks/mintSurfaceSystemToken.js +28 -14
- package/lib/hooks/mintSurfaceSystemToken.js.map +1 -1
- package/lib/hooks/systemTokenJwt.js +75 -0
- package/lib/hooks/systemTokenJwt.js.map +1 -0
- package/lib/hooks/useCdecliAutoConnect.js +116 -138
- package/lib/hooks/useCdecliAutoConnect.js.map +1 -1
- package/lib/hooks/useChatApi.js +43 -17
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +61 -13
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/useObtainSystemToken.js +121 -36
- package/lib/hooks/useObtainSystemToken.js.map +1 -1
- package/lib/screens/Chat/index.js +29 -5
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +21 -6
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/ChatHistoryLanding.js +46 -16
- package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const MAX_ASK_USER_QUESTIONS = 4;
|
|
2
|
+
const ASK_USER_RE = /\[ASK_USER\]([\s\S]*?)\[\/ASK_USER\]/;
|
|
3
|
+
const ASK_USER_OPEN_RE = /\[ASK_USER\]/;
|
|
4
|
+
function unwrapJsonCandidate(inner) {
|
|
5
|
+
let s = inner.trim();
|
|
6
|
+
const fence = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(s);
|
|
7
|
+
if (fence) s = fence[1].trim();
|
|
8
|
+
return s;
|
|
9
|
+
}
|
|
10
|
+
function parseJsonObject(s) {
|
|
11
|
+
const start = s.indexOf("{");
|
|
12
|
+
if (start < 0) return null;
|
|
13
|
+
let depth = 0;
|
|
14
|
+
let inStr = false;
|
|
15
|
+
let esc = false;
|
|
16
|
+
for (let i = start; i < s.length; i++) {
|
|
17
|
+
const c = s[i];
|
|
18
|
+
if (inStr) {
|
|
19
|
+
if (esc) {
|
|
20
|
+
esc = false;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (c === "\\") {
|
|
24
|
+
esc = true;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (c === '"') inStr = false;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (c === '"') {
|
|
31
|
+
inStr = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (c === "{") depth += 1;
|
|
35
|
+
else if (c === "}") {
|
|
36
|
+
depth -= 1;
|
|
37
|
+
if (depth === 0) {
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(s.slice(start, i + 1));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function normalizeQuestion(raw) {
|
|
49
|
+
if (!raw || typeof raw !== "object") return null;
|
|
50
|
+
const q = raw;
|
|
51
|
+
const id = typeof q.id === "string" ? q.id : "";
|
|
52
|
+
const title = typeof q.title === "string" ? q.title : typeof q.question === "string" ? q.question : "";
|
|
53
|
+
if (!id || !title.trim()) return null;
|
|
54
|
+
const options = Array.isArray(q.options) ? q.options.filter((o) => !!o && typeof o === "object" && typeof o.id === "string" && typeof o.label === "string") : void 0;
|
|
55
|
+
return {
|
|
56
|
+
id,
|
|
57
|
+
title: title.trim(),
|
|
58
|
+
header: typeof q.header === "string" ? q.header : void 0,
|
|
59
|
+
options,
|
|
60
|
+
allowText: q.allowText !== false,
|
|
61
|
+
textPlaceholder: typeof q.textPlaceholder === "string" ? q.textPlaceholder : void 0,
|
|
62
|
+
multiSelect: q.multiSelect === true
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function parseAskUser(raw) {
|
|
66
|
+
var _a;
|
|
67
|
+
if (!(raw == null ? void 0 : raw.trim())) return null;
|
|
68
|
+
const tagged = (_a = ASK_USER_RE.exec(raw)) != null ? _a : ASK_USER_OPEN_RE.test(raw) ? /\[ASK_USER\]([\s\S]*)$/.exec(raw) : null;
|
|
69
|
+
if (!tagged) return null;
|
|
70
|
+
const parsed = parseJsonObject(unwrapJsonCandidate(tagged[1]));
|
|
71
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
72
|
+
const body = parsed;
|
|
73
|
+
if (typeof body.requestId !== "string" || !Array.isArray(body.questions)) return null;
|
|
74
|
+
const questions = body.questions.map(normalizeQuestion).filter((q) => q !== null).slice(0, MAX_ASK_USER_QUESTIONS);
|
|
75
|
+
return questions.length ? {
|
|
76
|
+
requestId: body.requestId,
|
|
77
|
+
questions
|
|
78
|
+
} : null;
|
|
79
|
+
}
|
|
80
|
+
function stripAskUser(raw) {
|
|
81
|
+
if (!raw) return "";
|
|
82
|
+
let stripped = raw.replace(new RegExp(ASK_USER_RE.source, "g"), "");
|
|
83
|
+
stripped = stripped.replace(/\[ASK_USER\][\s\S]*$/, "");
|
|
84
|
+
if (stripped === raw) return raw;
|
|
85
|
+
return stripped.replace(/\n{3,}/g, "\n\n").trim();
|
|
86
|
+
}
|
|
87
|
+
function splitAskUserParts(raw) {
|
|
88
|
+
if (!raw) return {
|
|
89
|
+
before: "",
|
|
90
|
+
after: "",
|
|
91
|
+
hasMarker: false
|
|
92
|
+
};
|
|
93
|
+
const tagged = ASK_USER_RE.exec(raw);
|
|
94
|
+
if (tagged && tagged.index !== void 0) {
|
|
95
|
+
return {
|
|
96
|
+
before: raw.slice(0, tagged.index).trim(),
|
|
97
|
+
after: raw.slice(tagged.index + tagged[0].length).trim(),
|
|
98
|
+
hasMarker: true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const open = raw.search(ASK_USER_OPEN_RE);
|
|
102
|
+
if (open >= 0) {
|
|
103
|
+
return {
|
|
104
|
+
before: raw.slice(0, open).trim(),
|
|
105
|
+
after: "",
|
|
106
|
+
hasMarker: true
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
before: "",
|
|
111
|
+
after: "",
|
|
112
|
+
hasMarker: false
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function displayAskUserAssistantText(raw, answered) {
|
|
116
|
+
const parts = splitAskUserParts(raw);
|
|
117
|
+
if (!parts.hasMarker) return stripAskUser(raw);
|
|
118
|
+
const keep = answered ? parts.after : [parts.before, parts.after].filter(Boolean).join("\n\n");
|
|
119
|
+
return stripAskUser(keep || (answered ? "" : parts.before));
|
|
120
|
+
}
|
|
121
|
+
function pendingAskUser(messages) {
|
|
122
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
123
|
+
const msg = messages[i];
|
|
124
|
+
if (msg.role === "user") return null;
|
|
125
|
+
const parsed = msg.role === "assistant" ? parseAskUser(msg.content) : null;
|
|
126
|
+
if (parsed) return parsed;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
function formatAskUserAnswers(questions, answers) {
|
|
131
|
+
return questions.map((q) => {
|
|
132
|
+
var _a;
|
|
133
|
+
const answer = (_a = answers[q.id]) == null ? void 0 : _a.trim();
|
|
134
|
+
return answer ? `**${q.title.replace(/:\s*$/, "")}:** ${answer}` : null;
|
|
135
|
+
}).filter(Boolean).join("\n\n");
|
|
136
|
+
}export{MAX_ASK_USER_QUESTIONS,displayAskUserAssistantText,formatAskUserAnswers,parseAskUser,pendingAskUser,splitAskUserParts,stripAskUser};//# sourceMappingURL=askUser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"askUser.js","sources":["../../../src/features/chat/askUser.ts"],"sourcesContent":["/**\n * The `[ASK_USER]` clarifying-question protocol, mobile side (Clockbook #1643).\n *\n * cdecli emits the block itself — from Claude's AskUserQuestion and its own\n * ask_user_question tool — and PARKS the run until the answer arrives:\n *\n * [ASK_USER]{\"requestId\":\"ask-…\",\"questions\":[{\"id\":\"q1\",\"title\":\"Which\n * database?\",\"header\":\"Database\",\"options\":[{\"id\":\"o1\",\"label\":\"Postgres\",\n * \"detail\":\"…\"}],\"allowText\":true}]}[/ASK_USER]\n *\n * The reply is deliberately NOT a marker: answers are formatted into one visible\n * user message (`**Title:** answer` lines) and sent through the normal chat path,\n * so the producer needs no reply-protocol support. Only the question side is\n * structured.\n *\n * Deliberately a copy of the web's `responsePromptProtocol` rather than an\n * import — mobile is a separate bundle and shares no code with the web shell.\n * The reply side is plain text, so the two stay compatible without a shared\n * version.\n */\n\nexport interface AskUserOption {\n id: string;\n label: string;\n /** Secondary line under the label. */\n detail?: string;\n /** \"Something else\": focuses the free-text row instead of answering. */\n other?: boolean;\n}\n\nexport interface AskUserQuestion {\n id: string;\n /** Also the bold prefix of the formatted answer. */\n title: string;\n /** Short category eyebrow above the title, e.g. \"Database\". */\n header?: string;\n options?: AskUserOption[];\n /** Show the free-text row (default true). */\n allowText?: boolean;\n textPlaceholder?: string;\n /** Pick several options; the answer is sent as comma-joined labels. */\n multiSelect?: boolean;\n}\n\nexport interface AskUserPayload {\n requestId: string;\n questions: AskUserQuestion[];\n}\n\n/** Anything longer is a form, not a prompt — the web caps it the same way. */\nexport const MAX_ASK_USER_QUESTIONS = 4;\n\n// Not anchored: the channel layer may prepend a stream envelope or cost banner.\nconst ASK_USER_RE = /\\[ASK_USER\\]([\\s\\S]*?)\\[\\/ASK_USER\\]/;\nconst ASK_USER_OPEN_RE = /\\[ASK_USER\\]/;\n\nfunction unwrapJsonCandidate(inner: string): string {\n let s = inner.trim();\n const fence = /^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/i.exec(s);\n if (fence) s = fence[1].trim();\n return s;\n}\n\n/** First complete `{...}` object in `s`, or null while the JSON is still streaming. */\nfunction parseJsonObject(s: string): unknown | null {\n const start = s.indexOf('{');\n if (start < 0) return null;\n let depth = 0;\n let inStr = false;\n let esc = false;\n for (let i = start; i < s.length; i++) {\n const c = s[i];\n if (inStr) {\n if (esc) {\n esc = false;\n continue;\n }\n if (c === '\\\\') {\n esc = true;\n continue;\n }\n if (c === '\"') inStr = false;\n continue;\n }\n if (c === '\"') {\n inStr = true;\n continue;\n }\n if (c === '{') depth += 1;\n else if (c === '}') {\n depth -= 1;\n if (depth === 0) {\n try {\n return JSON.parse(s.slice(start, i + 1));\n } catch {\n return null;\n }\n }\n }\n }\n return null;\n}\n\nfunction normalizeQuestion(raw: unknown): AskUserQuestion | null {\n if (!raw || typeof raw !== 'object') return null;\n const q = raw as Record<string, unknown>;\n const id = typeof q.id === 'string' ? q.id : '';\n const title = typeof q.title === 'string' ? q.title : typeof q.question === 'string' ? q.question : '';\n if (!id || !title.trim()) return null;\n const options = Array.isArray(q.options)\n ? q.options.filter(\n (o): o is AskUserOption =>\n !!o &&\n typeof o === 'object' &&\n typeof (o as AskUserOption).id === 'string' &&\n typeof (o as AskUserOption).label === 'string',\n )\n : undefined;\n return {\n id,\n title: title.trim(),\n header: typeof q.header === 'string' ? q.header : undefined,\n options,\n allowText: q.allowText !== false,\n textPlaceholder: typeof q.textPlaceholder === 'string' ? q.textPlaceholder : undefined,\n multiSelect: q.multiSelect === true,\n };\n}\n\n/** Parse an `[ASK_USER]…[/ASK_USER]` message, or null if it isn't one. */\nexport function parseAskUser(raw: string | null | undefined): AskUserPayload | null {\n if (!raw?.trim()) return null;\n const tagged = ASK_USER_RE.exec(raw) ?? (ASK_USER_OPEN_RE.test(raw) ? /\\[ASK_USER\\]([\\s\\S]*)$/.exec(raw) : null);\n if (!tagged) return null;\n const parsed = parseJsonObject(unwrapJsonCandidate(tagged[1]));\n if (!parsed || typeof parsed !== 'object') return null;\n const body = parsed as { requestId?: unknown; questions?: unknown };\n if (typeof body.requestId !== 'string' || !Array.isArray(body.questions)) return null;\n const questions = body.questions\n .map(normalizeQuestion)\n .filter((q): q is AskUserQuestion => q !== null)\n .slice(0, MAX_ASK_USER_QUESTIONS);\n return questions.length ? { requestId: body.requestId, questions } : null;\n}\n\n/**\n * Remove every `[ASK_USER]` block, leaving the rest of the message intact.\n *\n * cdecli emits the block MID-turn and keeps streaming its reply into the SAME\n * message once the answer releases the parked run, so the block and the reply it\n * was asked for share one message. Hiding the whole message — which is what a\n * naive implementation does — would swallow that reply.\n *\n * An unclosed `[ASK_USER]` (still streaming) is also stripped so the raw JSON\n * never paints in the bubble the way it does on web after `stripAskUser`.\n */\nexport function stripAskUser(raw: string | null | undefined): string {\n if (!raw) return '';\n let stripped = raw.replace(new RegExp(ASK_USER_RE.source, 'g'), '');\n stripped = stripped.replace(/\\[ASK_USER\\][\\s\\S]*$/, '');\n if (stripped === raw) return raw;\n return stripped.replace(/\\n{3,}/g, '\\n\\n').trim();\n}\n\n/**\n * Text around an `[ASK_USER]` marker. cdecli often speaks an intro *before* the\n * card (\"I'll need a couple more details…\") and streams the real reply *after*\n * the user answers. Once there is a user reply, the intro is stale.\n */\nexport function splitAskUserParts(raw: string | null | undefined): {\n before: string;\n after: string;\n hasMarker: boolean;\n} {\n if (!raw) return { before: '', after: '', hasMarker: false };\n const tagged = ASK_USER_RE.exec(raw);\n if (tagged && tagged.index !== undefined) {\n return {\n before: raw.slice(0, tagged.index).trim(),\n after: raw.slice(tagged.index + tagged[0].length).trim(),\n hasMarker: true,\n };\n }\n const open = raw.search(ASK_USER_OPEN_RE);\n if (open >= 0) {\n return { before: raw.slice(0, open).trim(), after: '', hasMarker: true };\n }\n return { before: '', after: '', hasMarker: false };\n}\n\n/**\n * Assistant prose to paint. After the user answers the card, drop the intro that\n * sat above `[ASK_USER]` so we don't re-ask for details already in the thread.\n */\nexport function displayAskUserAssistantText(raw: string | null | undefined, answered: boolean): string {\n const parts = splitAskUserParts(raw);\n if (!parts.hasMarker) return stripAskUser(raw);\n const keep = answered ? parts.after : [parts.before, parts.after].filter(Boolean).join('\\n\\n');\n return stripAskUser(keep || (answered ? '' : parts.before));\n}\n\n/**\n * The question still awaiting an answer: the last assistant block, unless the\n * user has already replied after it. Scanning backwards means a stale card from\n * earlier in the thread never reappears.\n */\nexport function pendingAskUser(messages: ReadonlyArray<{ role: string; content: string }>): AskUserPayload | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'user') return null;\n const parsed = msg.role === 'assistant' ? parseAskUser(msg.content) : null;\n if (parsed) return parsed;\n }\n return null;\n}\n\n/**\n * Fold the answers into the single visible reply message:\n *\n * **Which database?:** Postgres\n *\n * Skipped questions are omitted; an empty result means \"nothing to send\", which\n * the card treats as a dismiss.\n */\nexport function formatAskUserAnswers(questions: readonly AskUserQuestion[], answers: Record<string, string>): string {\n return questions\n .map((q) => {\n const answer = answers[q.id]?.trim();\n return answer ? `**${q.title.replace(/:\\s*$/, '')}:** ${answer}` : null;\n })\n .filter(Boolean)\n .join('\\n\\n');\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
function closeOpenMarkdownFences(text) {
|
|
2
|
+
if (!text) return text;
|
|
3
|
+
const opens = text.match(/^ {0,3}```/gm);
|
|
4
|
+
if (!opens || opens.length % 2 === 0) return text;
|
|
5
|
+
return `${text}
|
|
6
|
+
\`\`\``;
|
|
7
|
+
}export{closeOpenMarkdownFences};//# sourceMappingURL=streamingMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamingMarkdown.js","sources":["../../../src/features/chat/streamingMarkdown.ts"],"sourcesContent":["/**\n * Streaming markdown is incomplete: the model often has an open ``` fence\n * when the next token has not arrived. Closing it for the preview makes\n * react-native-markdown-display paint a code block instead of raw fences.\n */\nexport function closeOpenMarkdownFences(text: string): string {\n if (!text) return text;\n const opens = text.match(/^ {0,3}```/gm);\n if (!opens || opens.length % 2 === 0) return text;\n return `${text}\\n\\`\\`\\``;\n}\n"],"names":[],"mappings":"AAKO,SAAS,wBAAwB,IAAsB,EAAA;AAC5D,EAAI,IAAA,CAAC,MAAa,OAAA,IAAA;AAClB,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,KAAA,CAAM,cAAc,CAAA;AACvC,EAAA,IAAI,CAAC,KAAS,IAAA,KAAA,CAAM,MAAS,GAAA,CAAA,KAAM,GAAU,OAAA,IAAA;AAC7C,EAAA,OAAO,GAAG,IAAI;AAAA,MAAA,CAAA;AAChB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const GEAR_LINE_RE = /^[ \t]*[⚙🔧\u{1F6E0}]️?[ \t]+(.+?)[ \t]*$/u;
|
|
2
|
+
const BARE_MCP_LINE_RE = /^[ \t]*(mcp__[^\s].*?)[ \t]*$/;
|
|
3
|
+
const TOOL_LABELS = [[/^tool[_-]?search$/i, "Searching tools"], [/^web[_-]?search$/i, "Searching the web"], [/^web[_-]?scrape$/i, "Reading a page"], [/^web[_-]?batch[_-]?scrape$/i, "Reading pages"], [/^reddit[_-]?search$/i, "Searching Reddit"], [/^x[_-]?search$/i, "Searching X"], [/^youtube[_-]?search$/i, "Searching YouTube"], [/^academic[_-]?search$/i, "Searching papers"], [/^(yantra[_-]?)?github[_-]?search$/i, "Searching GitHub"], [/^bash$/i, "Running a command"], [/^(str_replace_editor|edit|write)$/i, "Editing files"], [/^read$/i, "Reading files"]];
|
|
4
|
+
const CONNECTOR_LABELS = [[/image[_-]?gen/i, "Generating image"], [/video[_-]?gen/i, "Generating video"], [/(audio|tts|speech|voice)/i, "Generating audio"], [/search/i, "Searching"]];
|
|
5
|
+
function prettifySlug(slug) {
|
|
6
|
+
const words = slug.replace(/^yantra[_-]/i, "").replace(/[_-]+/g, " ").trim();
|
|
7
|
+
return words ? words.charAt(0).toUpperCase() + words.slice(1) : slug;
|
|
8
|
+
}
|
|
9
|
+
function humanizeToolLine(body) {
|
|
10
|
+
var _a, _b, _c, _d;
|
|
11
|
+
const trimmed = body.trim();
|
|
12
|
+
const dashSplit = trimmed.split(/\s+[—–-]\s+/);
|
|
13
|
+
const head = (_b = (_a = dashSplit[0]) == null ? void 0 : _a.trim()) != null ? _b : trimmed;
|
|
14
|
+
const detailRaw = dashSplit.length > 1 ? dashSplit.slice(1).join(" \u2014 ").trim() : void 0;
|
|
15
|
+
const bareTool = head.replace(/^mcp__[^_]+__/i, "").replace(/^mcp__/i, "");
|
|
16
|
+
if (/^execute_action$/i.test(bareTool) && detailRaw) {
|
|
17
|
+
const connector = (_d = (_c = detailRaw.split("/")[0]) == null ? void 0 : _c.trim()) != null ? _d : detailRaw;
|
|
18
|
+
for (const [re, label2] of CONNECTOR_LABELS) {
|
|
19
|
+
if (re.test(connector)) return {
|
|
20
|
+
label: label2,
|
|
21
|
+
detail: prettifySlug(connector)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
label: `Running ${prettifySlug(connector)}`,
|
|
26
|
+
detail: detailRaw
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
for (const [re, label2] of TOOL_LABELS) {
|
|
30
|
+
if (re.test(bareTool)) return {
|
|
31
|
+
label: label2,
|
|
32
|
+
detail: detailRaw
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const spaced = bareTool.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
36
|
+
const label = spaced ? `Running ${spaced.toLowerCase()}` : "Working";
|
|
37
|
+
return {
|
|
38
|
+
label,
|
|
39
|
+
detail: detailRaw
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function parseToolActivity(content, active = false) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (!content) return {
|
|
45
|
+
steps: [],
|
|
46
|
+
text: content != null ? content : ""
|
|
47
|
+
};
|
|
48
|
+
const steps = [];
|
|
49
|
+
const kept = [];
|
|
50
|
+
for (const line of content.split("\n")) {
|
|
51
|
+
const gear = GEAR_LINE_RE.exec(line);
|
|
52
|
+
const mcp = gear ? null : BARE_MCP_LINE_RE.exec(line);
|
|
53
|
+
const body = (_a = gear == null ? void 0 : gear[1]) != null ? _a : mcp == null ? void 0 : mcp[1];
|
|
54
|
+
if (body) {
|
|
55
|
+
const {
|
|
56
|
+
label,
|
|
57
|
+
detail
|
|
58
|
+
} = humanizeToolLine(body);
|
|
59
|
+
steps.push({
|
|
60
|
+
id: `tool-${steps.length}`,
|
|
61
|
+
label,
|
|
62
|
+
detail,
|
|
63
|
+
status: "done"
|
|
64
|
+
});
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
kept.push(line);
|
|
68
|
+
}
|
|
69
|
+
const text = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
70
|
+
if (active && steps.length > 0) {
|
|
71
|
+
steps[steps.length - 1].status = "running";
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
steps,
|
|
75
|
+
text
|
|
76
|
+
};
|
|
77
|
+
}export{humanizeToolLine,parseToolActivity};//# sourceMappingURL=toolActivity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolActivity.js","sources":["../../../src/features/chat/toolActivity.ts"],"sourcesContent":["/**\n * Tool-activity parsing for the polished status timeline (mobile).\n *\n * A port of the web's `features/chat/toolActivity`, copied rather than imported:\n * mobile is a separate bundle and shares no code with the web shell. It is pure\n * string logic with no DOM or React dependency, so the two are kept in step by\n * having the same tests rather than by a shared module.\n *\n *\n * The cdecli/agent narrates tool use into the streamed assistant text as bare\n * rows, e.g.:\n *\n * ⚙ ToolSearch\n * ⚙ mcp__cdecli__execute_action — yantra-image-generation/Image\n *\n * Rendered raw, these read as debug noise. We parse them out of the prose into\n * structured steps that {@link ./ToolTimeline} renders as an animated,\n * collapsible timeline, and hand back the cleaned prose so the bubble shows only\n * the real answer.\n *\n * Parsing is deliberately conservative: a line only counts as tool activity when\n * it leads with the gear/wrench glyph the agent prefixes, or is a standalone\n * `mcp__…` invocation. Ordinary prose never matches, so a miss degrades to\n * \"leave the text as-is\" rather than eating real content.\n */\n\nexport interface ToolStep {\n /** Stable within a single parse pass — index-based, so identical tools don't collide. */\n id: string;\n /** Humanized present-tense label, e.g. \"Generating image\". */\n label: string;\n /** Optional detail, e.g. the connector slug or raw tool token. */\n detail?: string;\n /** 'running' only ever applies to the LAST step of an in-flight turn. */\n status: 'running' | 'done';\n}\n\nexport interface ParsedToolActivity {\n steps: ToolStep[];\n /** Prose with every tool-activity line removed. */\n text: string;\n}\n\n// A tool-activity line: optional indent, a gear/wrench glyph (with optional\n// emoji variation selector), then the tool token + optional \"— detail\". The `m`\n// flag scopes ^/$ to each line; `u` so the glyph classes match correctly.\nconst GEAR_LINE_RE = /^[ \\t]*[⚙🔧\\u{1F6E0}]️?[ \\t]+(.+?)[ \\t]*$/u;\n// A bare MCP invocation on its own line — the agent sometimes omits the glyph.\n// `mcp__` is vanishingly unlikely in real prose, so this is safe to strip.\nconst BARE_MCP_LINE_RE = /^[ \\t]*(mcp__[^\\s].*?)[ \\t]*$/;\n\n/** Known tool tokens → present-tense labels. Anything unmapped falls back to a humanized token. */\nconst TOOL_LABELS: Array<[RegExp, string]> = [\n [/^tool[_-]?search$/i, 'Searching tools'],\n [/^web[_-]?search$/i, 'Searching the web'],\n [/^web[_-]?scrape$/i, 'Reading a page'],\n [/^web[_-]?batch[_-]?scrape$/i, 'Reading pages'],\n [/^reddit[_-]?search$/i, 'Searching Reddit'],\n [/^x[_-]?search$/i, 'Searching X'],\n [/^youtube[_-]?search$/i, 'Searching YouTube'],\n [/^academic[_-]?search$/i, 'Searching papers'],\n [/^(yantra[_-]?)?github[_-]?search$/i, 'Searching GitHub'],\n [/^bash$/i, 'Running a command'],\n [/^(str_replace_editor|edit|write)$/i, 'Editing files'],\n [/^read$/i, 'Reading files'],\n];\n\n/** Connector slug → verb phrase for `execute_action — <connector>/<action>` rows. */\nconst CONNECTOR_LABELS: Array<[RegExp, string]> = [\n [/image[_-]?gen/i, 'Generating image'],\n [/video[_-]?gen/i, 'Generating video'],\n [/(audio|tts|speech|voice)/i, 'Generating audio'],\n [/search/i, 'Searching'],\n];\n\n/** Title-case a slug/token: \"yantra-image-generation\" → \"Yantra image generation\". */\nfunction prettifySlug(slug: string): string {\n const words = slug\n .replace(/^yantra[_-]/i, '')\n .replace(/[_-]+/g, ' ')\n .trim();\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : slug;\n}\n\n/**\n * Turn a raw tool row body into a { label, detail }. Handles the two shapes we\n * see: a bare tool name (\"ToolSearch\") and an MCP execute_action carrying a\n * \"connector/action\" detail after an em/en dash.\n */\nexport function humanizeToolLine(body: string): { label: string; detail?: string } {\n const trimmed = body.trim();\n\n // `mcp__cdecli__execute_action — yantra-image-generation/Image`\n const dashSplit = trimmed.split(/\\s+[—–-]\\s+/);\n const head = dashSplit[0]?.trim() ?? trimmed;\n const detailRaw = dashSplit.length > 1 ? dashSplit.slice(1).join(' — ').trim() : undefined;\n\n // Strip an `mcp__<server>__` prefix off the head token.\n const bareTool = head.replace(/^mcp__[^_]+__/i, '').replace(/^mcp__/i, '');\n\n // execute_action rows: the meaning is in the connector detail, not the verb.\n if (/^execute_action$/i.test(bareTool) && detailRaw) {\n const connector = detailRaw.split('/')[0]?.trim() ?? detailRaw;\n for (const [re, label] of CONNECTOR_LABELS) {\n if (re.test(connector)) return { label, detail: prettifySlug(connector) };\n }\n return { label: `Running ${prettifySlug(connector)}`, detail: detailRaw };\n }\n\n for (const [re, label] of TOOL_LABELS) {\n if (re.test(bareTool)) return { label, detail: detailRaw };\n }\n\n // Generic fallback: prettify the token (camelCase / snake_case → spaced).\n const spaced = bareTool\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim();\n // Lowercase the WHOLE token, not just its first character: the split above\n // turns \"someNewTool\" into \"some New Tool\", and lowercasing only the head\n // left the label reading \"Running some New Tool\" mid-sentence.\n const label = spaced ? `Running ${spaced.toLowerCase()}` : 'Working';\n return { label, detail: detailRaw };\n}\n\n/**\n * Extract tool-activity rows from streamed/persisted assistant content.\n *\n * @param content raw assistant text\n * @param active when true the turn is still streaming, so the LAST step is\n * marked 'running'; otherwise every step is 'done'.\n */\nexport function parseToolActivity(content: string, active = false): ParsedToolActivity {\n if (!content) return { steps: [], text: content ?? '' };\n\n const steps: ToolStep[] = [];\n const kept: string[] = [];\n\n for (const line of content.split('\\n')) {\n const gear = GEAR_LINE_RE.exec(line);\n const mcp = gear ? null : BARE_MCP_LINE_RE.exec(line);\n const body = gear?.[1] ?? mcp?.[1];\n if (body) {\n const { label, detail } = humanizeToolLine(body);\n steps.push({ id: `tool-${steps.length}`, label, detail, status: 'done' });\n continue;\n }\n kept.push(line);\n }\n\n // Collapse the blank lines the removed rows leave behind (3+ newlines → 2).\n const text = kept\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n if (active && steps.length > 0) {\n steps[steps.length - 1].status = 'running';\n }\n\n return { steps, text };\n}\n"],"names":["label"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function collapseDuplicateUserRows(rows) {
|
|
2
|
+
const out = [];
|
|
3
|
+
for (const row of rows) {
|
|
4
|
+
const last = out[out.length - 1];
|
|
5
|
+
const trimmed = row.content.trim();
|
|
6
|
+
if (row.role === "user" && (last == null ? void 0 : last.role) === "user" && last.content.trim() === trimmed && trimmed) {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
out.push(row);
|
|
10
|
+
}
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
function groupConsecutiveRoleRows(rows) {
|
|
14
|
+
const groups = [];
|
|
15
|
+
for (const row of rows) {
|
|
16
|
+
const last = groups[groups.length - 1];
|
|
17
|
+
if (last && last.role === row.role) {
|
|
18
|
+
last.items.push(row);
|
|
19
|
+
last.id = `${last.items[0].id}..${row.id}`;
|
|
20
|
+
} else {
|
|
21
|
+
groups.push({
|
|
22
|
+
id: row.id,
|
|
23
|
+
role: row.role,
|
|
24
|
+
items: [row]
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return groups;
|
|
29
|
+
}export{collapseDuplicateUserRows,groupConsecutiveRoleRows};//# sourceMappingURL=transcriptGroups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcriptGroups.js","sources":["../../../src/features/chat/transcriptGroups.ts"],"sourcesContent":["/**\n * Consecutive same-role turns share one visual cluster, matching web\n * (stacked bubbles, not one concatenated blob). ASK_USER-only assistant rows\n * are stripped first, so a card answer sits under the original prompt as its\n * own bubble in the same right-aligned stack.\n */\n\nexport type RoleRow = {\n id: string;\n role: string;\n content: string;\n};\n\nexport type RoleGroup<T extends RoleRow> = {\n id: string;\n role: string;\n items: T[];\n};\n\n/** Drop an immediately-repeated user bubble (web planMessages). */\nexport function collapseDuplicateUserRows<T extends RoleRow>(rows: readonly T[]): T[] {\n const out: T[] = [];\n for (const row of rows) {\n const last = out[out.length - 1];\n const trimmed = row.content.trim();\n if (row.role === 'user' && last?.role === 'user' && last.content.trim() === trimmed && trimmed) {\n continue;\n }\n out.push(row);\n }\n return out;\n}\n\nexport function groupConsecutiveRoleRows<T extends RoleRow>(rows: readonly T[]): Array<RoleGroup<T>> {\n const groups: Array<RoleGroup<T>> = [];\n for (const row of rows) {\n const last = groups[groups.length - 1];\n if (last && last.role === row.role) {\n last.items.push(row);\n last.id = `${last.items[0].id}..${row.id}`;\n } else {\n groups.push({ id: row.id, role: row.role, items: [row] });\n }\n }\n return groups;\n}\n\n/** Visible user-group copy, one block — follow-ups append to the previous send. */\nexport function joinGroupedTexts(texts: readonly string[]): string {\n return texts\n .map((t) => t.trim())\n .filter(Boolean)\n .join('\\n\\n');\n}\n"],"names":[],"mappings":"AAmBO,SAAS,0BAA6C,IAAyB,EAAA;AACpF,EAAA,MAAM,MAAW,EAAC;AAClB,EAAA,KAAA,MAAW,OAAO,IAAM,EAAA;AACtB,IAAA,MAAM,IAAO,GAAA,GAAA,CAAI,GAAI,CAAA,MAAA,GAAS,CAAC,CAAA;AAC/B,IAAM,MAAA,OAAA,GAAU,GAAI,CAAA,OAAA,CAAQ,IAAK,EAAA;AACjC,IAAI,IAAA,GAAA,CAAI,IAAS,KAAA,MAAA,IAAA,CAAU,IAAM,IAAA,IAAA,GAAA,MAAA,GAAA,IAAA,CAAA,IAAA,MAAS,MAAU,IAAA,IAAA,CAAK,OAAQ,CAAA,IAAA,EAAW,KAAA,OAAA,IAAW,OAAS,EAAA;AAC9F,MAAA;AAAA;AAEF,IAAA,GAAA,CAAI,KAAK,GAAG,CAAA;AAAA;AAEd,EAAO,OAAA,GAAA;AACT;AACO,SAAS,yBAA4C,IAAyC,EAAA;AACnG,EAAA,MAAM,SAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,OAAO,IAAM,EAAA;AACtB,IAAA,MAAM,IAAO,GAAA,MAAA,CAAO,MAAO,CAAA,MAAA,GAAS,CAAC,CAAA;AACrC,IAAA,IAAI,IAAQ,IAAA,IAAA,CAAK,IAAS,KAAA,GAAA,CAAI,IAAM,EAAA;AAClC,MAAK,IAAA,CAAA,KAAA,CAAM,KAAK,GAAG,CAAA;AACnB,MAAK,IAAA,CAAA,EAAA,GAAK,GAAG,IAAK,CAAA,KAAA,CAAM,CAAC,CAAE,CAAA,EAAE,CAAK,EAAA,EAAA,GAAA,CAAI,EAAE,CAAA,CAAA;AAAA,KACnC,MAAA;AACL,MAAA,MAAA,CAAO,IAAK,CAAA;AAAA,QACV,IAAI,GAAI,CAAA,EAAA;AAAA,QACR,MAAM,GAAI,CAAA,IAAA;AAAA,QACV,KAAA,EAAO,CAAC,GAAG;AAAA,OACZ,CAAA;AAAA;AACH;AAEF,EAAO,OAAA,MAAA;AACT"}
|
|
@@ -80,6 +80,11 @@ async function gqlFetch(graphqlUrl, idToken, query, variables) {
|
|
|
80
80
|
}
|
|
81
81
|
return await res.json();
|
|
82
82
|
}
|
|
83
|
+
const REVOKE_SECRET_API_TOKEN = `
|
|
84
|
+
mutation RevokeSecretApiToken($id: ID!) {
|
|
85
|
+
revokeSecretApiToken(id: $id)
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
83
88
|
const DEV_TESTING_PROJECT_UUID = "9a8ac704-1040-4836-9b72-48b771ca91b1";
|
|
84
89
|
const OBJECT_ID_HEX = /^[a-fA-F0-9]{24}$/;
|
|
85
90
|
const PROJECT_UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
@@ -140,7 +145,7 @@ function assertMintableProjectId(projectId) {
|
|
|
140
145
|
}
|
|
141
146
|
}
|
|
142
147
|
async function mintSurfaceSystemToken(input) {
|
|
143
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
148
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
|
|
144
149
|
const idToken = await readAuth0IdToken();
|
|
145
150
|
if (!idToken) {
|
|
146
151
|
throw new Error("No Auth0 id_token in storage \u2014 sign in to the mobile app first.");
|
|
@@ -175,6 +180,15 @@ async function mintSurfaceSystemToken(input) {
|
|
|
175
180
|
throw new Error("Missing environmentTagId \u2014 cannot mint system token.");
|
|
176
181
|
}
|
|
177
182
|
assertMintableProjectId(projectId);
|
|
183
|
+
if (input.forceRemint) {
|
|
184
|
+
const existing = await gqlFetch(graphqlUrl, idToken, GET_USER_SYSTEM_TOKEN);
|
|
185
|
+
const existingId = (_f = (_e = (_d = existing.data) == null ? void 0 : _d.getUserSystemToken) == null ? void 0 : _e.id) != null ? _f : null;
|
|
186
|
+
if (existingId) {
|
|
187
|
+
await gqlFetch(graphqlUrl, idToken, REVOKE_SECRET_API_TOKEN, {
|
|
188
|
+
id: existingId
|
|
189
|
+
}).catch(() => void 0);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
178
192
|
try {
|
|
179
193
|
const obtained = await gqlFetch(graphqlUrl, idToken, OBTAIN_USER_SYSTEM_TOKEN, {
|
|
180
194
|
input: {
|
|
@@ -185,8 +199,8 @@ async function mintSurfaceSystemToken(input) {
|
|
|
185
199
|
algorithm: "HS256"
|
|
186
200
|
}
|
|
187
201
|
});
|
|
188
|
-
const token2 = (
|
|
189
|
-
if (token2 && !((
|
|
202
|
+
const token2 = (_i = (_h = (_g = obtained.data) == null ? void 0 : _g.obtainUserSystemToken) == null ? void 0 : _h.token) == null ? void 0 : _i.trim();
|
|
203
|
+
if (token2 && !((_j = obtained.errors) == null ? void 0 : _j.length)) {
|
|
190
204
|
if (__DEV__) {
|
|
191
205
|
console.log("[WebBuilder] obtained system token length=", token2.length);
|
|
192
206
|
}
|
|
@@ -195,8 +209,8 @@ async function mintSurfaceSystemToken(input) {
|
|
|
195
209
|
backend: graphqlUrl
|
|
196
210
|
};
|
|
197
211
|
}
|
|
198
|
-
if ((
|
|
199
|
-
throw new Error(((
|
|
212
|
+
if ((_k = obtained.errors) == null ? void 0 : _k.length) {
|
|
213
|
+
throw new Error(((_l = obtained.errors[0]) == null ? void 0 : _l.message) || "obtainUserSystemToken failed");
|
|
200
214
|
}
|
|
201
215
|
} catch (err) {
|
|
202
216
|
if (__DEV__) {
|
|
@@ -213,10 +227,10 @@ async function mintSurfaceSystemToken(input) {
|
|
|
213
227
|
}
|
|
214
228
|
}
|
|
215
229
|
const getResult = await gqlFetch(graphqlUrl, idToken, GET_USER_SYSTEM_TOKEN);
|
|
216
|
-
if ((
|
|
217
|
-
throw new Error(((
|
|
230
|
+
if ((_m = getResult.errors) == null ? void 0 : _m.length) {
|
|
231
|
+
throw new Error(((_n = getResult.errors[0]) == null ? void 0 : _n.message) || "GetUserSystemToken failed");
|
|
218
232
|
}
|
|
219
|
-
let tokenId = (
|
|
233
|
+
let tokenId = (_q = (_p = (_o = getResult.data) == null ? void 0 : _o.getUserSystemToken) == null ? void 0 : _p.id) != null ? _q : null;
|
|
220
234
|
if (!tokenId) {
|
|
221
235
|
const createResult = await gqlFetch(graphqlUrl, idToken, CREATE_SECRET_API_TOKEN, {
|
|
222
236
|
input: {
|
|
@@ -229,18 +243,18 @@ async function mintSurfaceSystemToken(input) {
|
|
|
229
243
|
algorithm: "HS256"
|
|
230
244
|
}
|
|
231
245
|
});
|
|
232
|
-
const createErr = ((
|
|
246
|
+
const createErr = ((_s = (_r = createResult.errors) == null ? void 0 : _r[0]) == null ? void 0 : _s.message) || "";
|
|
233
247
|
if (createErr && !/already have a system token/i.test(createErr)) {
|
|
234
248
|
if (/12 bytes|24 hex/i.test(createErr)) {
|
|
235
249
|
throw new Error(`Project "${projectId}" is not valid on this backend. Pick/create a real project in the app, then retry.`);
|
|
236
250
|
}
|
|
237
251
|
throw new Error(createErr);
|
|
238
252
|
}
|
|
239
|
-
if ((
|
|
253
|
+
if ((_u = (_t = createResult.data) == null ? void 0 : _t.createSecretApiToken) == null ? void 0 : _u.id) {
|
|
240
254
|
tokenId = createResult.data.createSecretApiToken.id;
|
|
241
255
|
} else {
|
|
242
256
|
const refetch = await gqlFetch(graphqlUrl, idToken, GET_USER_SYSTEM_TOKEN);
|
|
243
|
-
tokenId = (
|
|
257
|
+
tokenId = (_x = (_w = (_v = refetch.data) == null ? void 0 : _v.getUserSystemToken) == null ? void 0 : _w.id) != null ? _x : null;
|
|
244
258
|
}
|
|
245
259
|
}
|
|
246
260
|
if (!tokenId) {
|
|
@@ -249,10 +263,10 @@ async function mintSurfaceSystemToken(input) {
|
|
|
249
263
|
const reveal = await gqlFetch(graphqlUrl, idToken, REVEAL_SECRET_API_TOKEN, {
|
|
250
264
|
id: tokenId
|
|
251
265
|
});
|
|
252
|
-
if ((
|
|
253
|
-
throw new Error(((
|
|
266
|
+
if ((_y = reveal.errors) == null ? void 0 : _y.length) {
|
|
267
|
+
throw new Error(((_z = reveal.errors[0]) == null ? void 0 : _z.message) || "RevealSecretApiToken failed");
|
|
254
268
|
}
|
|
255
|
-
const token = (
|
|
269
|
+
const token = (_B = (_A = reveal.data) == null ? void 0 : _A.revealSecretApiToken) == null ? void 0 : _B.trim();
|
|
256
270
|
if (!token) {
|
|
257
271
|
throw new Error("RevealSecretApiToken returned empty token");
|
|
258
272
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintSurfaceSystemToken.js","sources":["../../src/hooks/mintSurfaceSystemToken.ts"],"sourcesContent":["import { AuthStrategy, HttpHeaders } from 'common';\nimport { readAuth0IdToken } from '../bridge/readAuth0Session';\nimport { config } from '../config/env-config';\n\nconst OBTAIN_USER_SYSTEM_TOKEN = `\n mutation ObtainUserSystemToken($input: ObtainUserSystemTokenInput!) {\n obtainUserSystemToken(input: $input) {\n token\n }\n }\n`;\n\nconst GET_USER_SYSTEM_TOKEN = `\n query GetUserSystemToken {\n getUserSystemToken {\n id\n expiresAt\n isSystemToken\n }\n }\n`;\n\nconst GET_USER_ORGANIZATIONS = `\n query GetUserOrganizations {\n getUserOrganizations {\n name\n }\n }\n`;\n\nconst GET_PROJECTS = `\n query GetProjects($orgName: String!) {\n getProjects(orgName: $orgName) {\n data {\n id\n }\n }\n }\n`;\n\nconst GET_ENVIRONMENT_TAGS = `\n query GetEnvironmentTags($projectId: ID) {\n getEnvironmentTags(projectId: $projectId) {\n id\n }\n }\n`;\n\nconst CREATE_SECRET_API_TOKEN = `\n mutation CreateSecretApiToken($input: CreateSecretApiTokenInput!) {\n createSecretApiToken(input: $input) {\n id\n expiresAt\n }\n }\n`;\n\nconst REVEAL_SECRET_API_TOKEN = `\n mutation RevealSecretApiToken($id: ID!) {\n revealSecretApiToken(id: $id)\n }\n`;\n\ntype GqlResult<T> = {\n data?: T;\n errors?: Array<{ message?: string }>;\n};\n\nfunction normalizeGraphqlUrl(url: string): string {\n return url.trim().replace(/\\/$/, '');\n}\n\n/** App GRAPHQL_URL from env (optional override for device LAN rewrite). */\nexport function resolveSurfaceCatalogBackend(graphqlUrl?: string): string {\n const raw = graphqlUrl?.trim() || config.GRAPHQL_URL;\n if (!raw?.trim()) {\n throw new Error('GRAPHQL_URL is not configured');\n }\n return normalizeGraphqlUrl(raw);\n}\n\nexport { isCanvasSurfaceUrl, resolveSurfaceAuthGraphqlUrl } from './resolveSurfaceAuthGraphqlUrl';\nexport type { SurfaceAuthUrlConfig } from './resolveSurfaceAuthGraphqlUrl';\n\nasync function gqlFetch<T>(\n graphqlUrl: string,\n idToken: string,\n query: string,\n variables?: Record<string, unknown>,\n): Promise<GqlResult<T>> {\n // Staging JWT middleware only treats Bearer as mobile/SPA when\n // `ismobile` (or `isspa`) is set — without it we get HTTP 401 Unauthorized.\n // Match Apollo mobile authHeadersLink + Auth0Client.commonFetchRequestHeaders.\n const res = await fetch(graphqlUrl, {\n method: 'POST',\n headers: {\n [HttpHeaders.CONTENT_TYPE]: 'application/json',\n [HttpHeaders.AUTHORIZATION]: `Bearer ${idToken}`,\n [HttpHeaders.IS_MOBILE]: 'true',\n [HttpHeaders.AUTH_STRATEGY]: AuthStrategy.Auth0,\n },\n body: JSON.stringify({ query, variables }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`GraphQL HTTP ${res.status}: ${text.slice(0, 200)}`);\n }\n return (await res.json()) as GqlResult<T>;\n}\n\nexport type MintSurfaceTokenInput = {\n /** App GRAPHQL_URL (e.g. device-rewritten). Defaults to env GRAPHQL_URL. */\n graphqlUrl?: string;\n orgName?: string | null;\n projectId?: string | null;\n tagId?: string | null;\n /**\n * Resolve org/project/env on `graphqlUrl` instead of using the mobile\n * app's local ids. Required when minting against a different cluster\n * than GRAPHQL_URL (canvas index lives on yantra-app-v1).\n */\n discoverScope?: boolean;\n};\n\nexport type MintSurfaceTokenResult = {\n token: string;\n /** Exact backend URL string to stamp into cdecli_token_meta. */\n backend: string;\n};\n\n/**\n * Reveal (or obtain) a system token on GRAPHQL_URL.\n */\n/** Local-dev testing project — must never mint against this on staging/prod. */\nconst DEV_TESTING_PROJECT_UUID = '9a8ac704-1040-4836-9b72-48b771ca91b1';\n\nconst OBJECT_ID_HEX = /^[a-fA-F0-9]{24}$/;\nconst PROJECT_UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;\n\nasync function discoverMintScope(\n graphqlUrl: string,\n idToken: string,\n): Promise<{ orgName: string; projectId: string; environmentTagId: string }> {\n const orgs = await gqlFetch<{ getUserOrganizations?: Array<{ name?: string | null } | null> | null }>(\n graphqlUrl,\n idToken,\n GET_USER_ORGANIZATIONS,\n );\n if (orgs.errors?.length) {\n throw new Error(orgs.errors[0]?.message || 'getUserOrganizations failed');\n }\n const orgName = orgs.data?.getUserOrganizations?.find((o) => o?.name?.trim())?.name?.trim() || '';\n if (!orgName) {\n throw new Error(\n 'No organization on the canvas backend. Sign in once in the canvas harness (Chrome on localhost:5175), then retry from the app.',\n );\n }\n\n const projects = await gqlFetch<{ getProjects?: { data?: Array<{ id?: string | null } | null> | null } | null }>(\n graphqlUrl,\n idToken,\n GET_PROJECTS,\n { orgName },\n );\n if (projects.errors?.length) {\n throw new Error(projects.errors[0]?.message || 'getProjects failed');\n }\n const projectId = projects.data?.getProjects?.data?.find((p) => p?.id?.trim())?.id?.trim() || '';\n if (!projectId) {\n throw new Error(`No project on the canvas backend for org \"${orgName}\".`);\n }\n\n const tags = await gqlFetch<{ getEnvironmentTags?: Array<{ id?: string | null } | null> | null }>(\n graphqlUrl,\n idToken,\n GET_ENVIRONMENT_TAGS,\n { projectId },\n );\n if (tags.errors?.length) {\n throw new Error(tags.errors[0]?.message || 'getEnvironmentTags failed');\n }\n const environmentTagId = tags.data?.getEnvironmentTags?.find((t) => t?.id?.trim())?.id?.trim() || '';\n if (!environmentTagId) {\n throw new Error(`No environment tag on the canvas backend for project \"${projectId}\".`);\n }\n\n return { orgName, projectId, environmentTagId };\n}\n\nfunction assertMintableProjectId(projectId: string): void {\n if (projectId === 'default' || !projectId.trim()) {\n throw new Error('Missing projectId — wait for org/project bootstrap, then retry.');\n }\n if (!__DEV__ && projectId === DEV_TESTING_PROJECT_UUID) {\n throw new Error(\n 'Invalid projectId (dev testing UUID). Open Home so a real project can be created, then retry.',\n );\n }\n if (!OBJECT_ID_HEX.test(projectId) && !PROJECT_UUID.test(projectId)) {\n throw new Error(`Invalid projectId format for system token mint: ${projectId.slice(0, 48)}`);\n }\n}\n\nexport async function mintSurfaceSystemToken(input: MintSurfaceTokenInput): Promise<MintSurfaceTokenResult> {\n const idToken = await readAuth0IdToken();\n if (!idToken) {\n throw new Error('No Auth0 id_token in storage — sign in to the mobile app first.');\n }\n\n const graphqlUrl = resolveSurfaceCatalogBackend(input.graphqlUrl);\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] minting system token via', graphqlUrl, input.discoverScope ? '(discover scope)' : '');\n }\n\n let orgName = input.orgName?.trim() || '';\n let projectId = input.projectId?.trim() || '';\n let environmentTagId = input.tagId?.trim() || '';\n\n if (input.discoverScope) {\n const scope = await discoverMintScope(graphqlUrl, idToken);\n orgName = scope.orgName;\n projectId = scope.projectId;\n environmentTagId = scope.environmentTagId;\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] discovered canvas scope', { orgName, projectId, environmentTagId });\n }\n }\n\n if (!orgName) {\n throw new Error('Missing orgName — wait for org bootstrap, then retry.');\n }\n if (!projectId) {\n throw new Error('Missing projectId — wait for org/project bootstrap, then retry.');\n }\n if (!environmentTagId) {\n throw new Error('Missing environmentTagId — cannot mint system token.');\n }\n assertMintableProjectId(projectId);\n\n // Canonical get-or-create (resolves project UUID → Mongo id server-side).\n try {\n const obtained = await gqlFetch<{ obtainUserSystemToken?: { token?: string } | null }>(\n graphqlUrl,\n idToken,\n OBTAIN_USER_SYSTEM_TOKEN,\n {\n input: {\n projectId,\n environmentTagId,\n orgName,\n renewBufferSeconds: 7 * 24 * 60 * 60,\n algorithm: 'HS256',\n },\n },\n );\n const token = obtained.data?.obtainUserSystemToken?.token?.trim();\n if (token && !obtained.errors?.length) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] obtained system token length=', token.length);\n }\n return { token, backend: graphqlUrl };\n }\n if (obtained.errors?.length) {\n throw new Error(obtained.errors[0]?.message || 'obtainUserSystemToken failed');\n }\n } catch (err) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] obtainUserSystemToken failed, falling back to reveal:', err);\n }\n // Fall through to get/create/reveal only when obtain is unavailable.\n const msg = err instanceof Error ? err.message : String(err);\n if (/12 bytes|24 hex|Project not found/i.test(msg)) {\n throw new Error(\n `Project \"${projectId}\" is not valid on this backend. Pick/create a real project in the app, then retry.`,\n );\n }\n // Continue to legacy path for older backends without obtainUserSystemToken.\n if (!/Unknown field|Cannot query field|obtainUserSystemToken/i.test(msg)) {\n // Non-schema errors from obtain should surface (auth, project, etc.).\n if (/Unauthorized|401|Project not found|Invalid project/i.test(msg)) {\n throw err instanceof Error ? err : new Error(msg);\n }\n }\n }\n\n const getResult = await gqlFetch<{ getUserSystemToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n GET_USER_SYSTEM_TOKEN,\n );\n if (getResult.errors?.length) {\n throw new Error(getResult.errors[0]?.message || 'GetUserSystemToken failed');\n }\n\n let tokenId = getResult.data?.getUserSystemToken?.id ?? null;\n\n if (!tokenId) {\n const createResult = await gqlFetch<{ createSecretApiToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n CREATE_SECRET_API_TOKEN,\n {\n input: {\n name: 'System Token',\n expiryInSeconds: 31536000,\n isSystemToken: true,\n environmentTagId,\n orgName,\n projectId,\n algorithm: 'HS256',\n },\n },\n );\n\n const createErr = createResult.errors?.[0]?.message || '';\n if (createErr && !/already have a system token/i.test(createErr)) {\n if (/12 bytes|24 hex/i.test(createErr)) {\n throw new Error(\n `Project \"${projectId}\" is not valid on this backend. Pick/create a real project in the app, then retry.`,\n );\n }\n throw new Error(createErr);\n }\n\n if (createResult.data?.createSecretApiToken?.id) {\n tokenId = createResult.data.createSecretApiToken.id;\n } else {\n const refetch = await gqlFetch<{ getUserSystemToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n GET_USER_SYSTEM_TOKEN,\n );\n tokenId = refetch.data?.getUserSystemToken?.id ?? null;\n }\n }\n\n if (!tokenId) {\n throw new Error('No system token id on GraphQL backend — cannot reveal.');\n }\n\n const reveal = await gqlFetch<{ revealSecretApiToken?: string | null }>(\n graphqlUrl,\n idToken,\n REVEAL_SECRET_API_TOKEN,\n { id: tokenId },\n );\n if (reveal.errors?.length) {\n throw new Error(reveal.errors[0]?.message || 'RevealSecretApiToken failed');\n }\n\n const token = reveal.data?.revealSecretApiToken?.trim();\n if (!token) {\n throw new Error('RevealSecretApiToken returned empty token');\n }\n\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] minted system token length=', token.length);\n }\n return { token, backend: graphqlUrl };\n}\n\nexport function appendSurfaceAuthParams(baseUrl: string, token: string, state: string): string {\n try {\n const url = new URL(baseUrl);\n url.searchParams.set('token', token);\n url.searchParams.set('code', token);\n url.searchParams.set('state', state);\n return url.toString();\n } catch {\n const sep = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${sep}token=${encodeURIComponent(token)}&code=${encodeURIComponent(token)}&state=${encodeURIComponent(state)}`;\n }\n}\n\nfunction tokenFingerprint(token: string): string {\n const sig = token.split('.')[2] ?? token;\n return sig.slice(-24);\n}\n\n/** Shared WebView boot script: token + meta + fetch shims for surface-kit auth. */\nfunction buildSurfaceHandoffScript(token: string, backend: string, state: string, withGateRecovery: boolean): string {\n const safeToken = JSON.stringify(token);\n const safeBackend = JSON.stringify(backend);\n const safeState = JSON.stringify(state);\n const fp = JSON.stringify(tokenFingerprint(token));\n const recovery = withGateRecovery\n ? `\n function tryRecover() {\n stamp();\n var gate = document.querySelector('[data-surface-login]');\n if (!gate) return;\n if (sessionStorage.getItem('__yantra_wb_token_reload')) return;\n sessionStorage.setItem('__yantra_wb_token_reload', '1');\n var u = new URL(window.location.href);\n u.searchParams.set('token', t);\n u.searchParams.set('code', t);\n u.searchParams.set('state', state);\n window.location.replace(u.toString());\n }\n tryRecover();\n var i = 0;\n var timer = setInterval(function () {\n i += 1;\n tryRecover();\n if (i >= 40 || !document.querySelector('[data-surface-login]')) clearInterval(timer);\n }, 250);\n`\n : `\n var n = 0;\n var id = setInterval(function () {\n stamp();\n n += 1;\n if (n >= 80) clearInterval(id);\n }, 50);\n`;\n\n return `\n(function () {\n try {\n var t = ${safeToken};\n var backend = ${safeBackend};\n var state = ${safeState};\n var fp = ${fp};\n var PROBE_Q = 'query { getUserAccount { id } }';\n\n if (!window.__yantraWbFetchPatched) {\n window.__yantraWbFetchPatched = true;\n var origFetch = window.fetch.bind(window);\n window.fetch = function (input, init) {\n try {\n var url = typeof input === 'string' ? input : (input && input.url) ? String(input.url) : '';\n // Force surface-kit resolveCatalogBackend() to our GRAPHQL_URL (not remote agent → ideback).\n if (url.indexOf('/v1/auth/context') !== -1) {\n return Promise.resolve(new Response(\n JSON.stringify({ backendGraphqlUrl: backend }),\n { status: 200, headers: { 'Content-Type': 'application/json' } }\n ));\n }\n var body = init && typeof init.body === 'string' ? init.body : '';\n if (body && body.indexOf('getUserAccount') !== -1) {\n var parsed = JSON.parse(body);\n var q = parsed && typeof parsed.query === 'string' ? parsed.query.replace(/\\\\s+/g, ' ').trim() : '';\n if (q === PROBE_Q) {\n return Promise.resolve(new Response(\n JSON.stringify({ data: { getUserAccount: { id: 'mobile-webview-handoff' } } }),\n { status: 200, headers: { 'Content-Type': 'application/json' } }\n ));\n }\n }\n } catch (e0) {}\n return origFetch(input, init);\n };\n }\n\n function stamp() {\n try {\n sessionStorage.setItem('cdecli_oauth_state', state);\n localStorage.setItem('cdecli_token', t);\n sessionStorage.setItem('cdecli_token', t);\n localStorage.setItem('cdecli_system_token', t);\n localStorage.setItem('cdecli_token_meta', JSON.stringify({\n backend: backend,\n verifiedAt: Date.now(),\n fp: fp\n }));\n } catch (e1) {}\n }\n stamp();\n ${recovery}\n } catch (e) {}\n true;\n})();\ntrue;\n`;\n}\n\nexport function buildCdecliTokenInjection(token: string, backend: string, state: string): string {\n return buildSurfaceHandoffScript(token, backend, state, false);\n}\n\nexport function buildSurfaceGateRecoveryScript(token: string, backend: string, state: string): string {\n return buildSurfaceHandoffScript(token, backend, state, true);\n}\n"],"names":["_a","token"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mintSurfaceSystemToken.js","sources":["../../src/hooks/mintSurfaceSystemToken.ts"],"sourcesContent":["import { AuthStrategy, HttpHeaders } from 'common';\nimport { readAuth0IdToken } from '../bridge/readAuth0Session';\nimport { config } from '../config/env-config';\n\nconst OBTAIN_USER_SYSTEM_TOKEN = `\n mutation ObtainUserSystemToken($input: ObtainUserSystemTokenInput!) {\n obtainUserSystemToken(input: $input) {\n token\n }\n }\n`;\n\nconst GET_USER_SYSTEM_TOKEN = `\n query GetUserSystemToken {\n getUserSystemToken {\n id\n expiresAt\n isSystemToken\n }\n }\n`;\n\nconst GET_USER_ORGANIZATIONS = `\n query GetUserOrganizations {\n getUserOrganizations {\n name\n }\n }\n`;\n\nconst GET_PROJECTS = `\n query GetProjects($orgName: String!) {\n getProjects(orgName: $orgName) {\n data {\n id\n }\n }\n }\n`;\n\nconst GET_ENVIRONMENT_TAGS = `\n query GetEnvironmentTags($projectId: ID) {\n getEnvironmentTags(projectId: $projectId) {\n id\n }\n }\n`;\n\nconst CREATE_SECRET_API_TOKEN = `\n mutation CreateSecretApiToken($input: CreateSecretApiTokenInput!) {\n createSecretApiToken(input: $input) {\n id\n expiresAt\n }\n }\n`;\n\nconst REVEAL_SECRET_API_TOKEN = `\n mutation RevealSecretApiToken($id: ID!) {\n revealSecretApiToken(id: $id)\n }\n`;\n\ntype GqlResult<T> = {\n data?: T;\n errors?: Array<{ message?: string }>;\n};\n\nfunction normalizeGraphqlUrl(url: string): string {\n return url.trim().replace(/\\/$/, '');\n}\n\n/** App GRAPHQL_URL from env (optional override for device LAN rewrite). */\nexport function resolveSurfaceCatalogBackend(graphqlUrl?: string): string {\n const raw = graphqlUrl?.trim() || config.GRAPHQL_URL;\n if (!raw?.trim()) {\n throw new Error('GRAPHQL_URL is not configured');\n }\n return normalizeGraphqlUrl(raw);\n}\n\nexport { isCanvasSurfaceUrl, resolveSurfaceAuthGraphqlUrl } from './resolveSurfaceAuthGraphqlUrl';\nexport type { SurfaceAuthUrlConfig } from './resolveSurfaceAuthGraphqlUrl';\n\nasync function gqlFetch<T>(\n graphqlUrl: string,\n idToken: string,\n query: string,\n variables?: Record<string, unknown>,\n): Promise<GqlResult<T>> {\n // Staging JWT middleware only treats Bearer as mobile/SPA when\n // `ismobile` (or `isspa`) is set — without it we get HTTP 401 Unauthorized.\n // Match Apollo mobile authHeadersLink + Auth0Client.commonFetchRequestHeaders.\n const res = await fetch(graphqlUrl, {\n method: 'POST',\n headers: {\n [HttpHeaders.CONTENT_TYPE]: 'application/json',\n [HttpHeaders.AUTHORIZATION]: `Bearer ${idToken}`,\n [HttpHeaders.IS_MOBILE]: 'true',\n [HttpHeaders.AUTH_STRATEGY]: AuthStrategy.Auth0,\n },\n body: JSON.stringify({ query, variables }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`GraphQL HTTP ${res.status}: ${text.slice(0, 200)}`);\n }\n return (await res.json()) as GqlResult<T>;\n}\n\nconst REVOKE_SECRET_API_TOKEN = `\n mutation RevokeSecretApiToken($id: ID!) {\n revokeSecretApiToken(id: $id)\n }\n`;\n\nexport type MintSurfaceTokenInput = {\n /** App GRAPHQL_URL (e.g. device-rewritten). Defaults to env GRAPHQL_URL. */\n graphqlUrl?: string;\n orgName?: string | null;\n projectId?: string | null;\n tagId?: string | null;\n /**\n * Resolve org/project/env on `graphqlUrl` instead of using the mobile\n * app's local ids. Required when minting against a different cluster\n * than GRAPHQL_URL (canvas index lives on yantra-app-v1).\n */\n discoverScope?: boolean;\n /** Revoke the existing system-token row before obtain/create (dead HS256 signature). */\n forceRemint?: boolean;\n};\n\nexport type MintSurfaceTokenResult = {\n token: string;\n /** Exact backend URL string to stamp into cdecli_token_meta. */\n backend: string;\n};\n\n/**\n * Reveal (or obtain) a system token on GRAPHQL_URL.\n */\n/** Local-dev testing project — must never mint against this on staging/prod. */\nconst DEV_TESTING_PROJECT_UUID = '9a8ac704-1040-4836-9b72-48b771ca91b1';\n\nconst OBJECT_ID_HEX = /^[a-fA-F0-9]{24}$/;\nconst PROJECT_UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;\n\nasync function discoverMintScope(\n graphqlUrl: string,\n idToken: string,\n): Promise<{ orgName: string; projectId: string; environmentTagId: string }> {\n const orgs = await gqlFetch<{ getUserOrganizations?: Array<{ name?: string | null } | null> | null }>(\n graphqlUrl,\n idToken,\n GET_USER_ORGANIZATIONS,\n );\n if (orgs.errors?.length) {\n throw new Error(orgs.errors[0]?.message || 'getUserOrganizations failed');\n }\n const orgName = orgs.data?.getUserOrganizations?.find((o) => o?.name?.trim())?.name?.trim() || '';\n if (!orgName) {\n throw new Error(\n 'No organization on the canvas backend. Sign in once in the canvas harness (Chrome on localhost:5175), then retry from the app.',\n );\n }\n\n const projects = await gqlFetch<{ getProjects?: { data?: Array<{ id?: string | null } | null> | null } | null }>(\n graphqlUrl,\n idToken,\n GET_PROJECTS,\n { orgName },\n );\n if (projects.errors?.length) {\n throw new Error(projects.errors[0]?.message || 'getProjects failed');\n }\n const projectId = projects.data?.getProjects?.data?.find((p) => p?.id?.trim())?.id?.trim() || '';\n if (!projectId) {\n throw new Error(`No project on the canvas backend for org \"${orgName}\".`);\n }\n\n const tags = await gqlFetch<{ getEnvironmentTags?: Array<{ id?: string | null } | null> | null }>(\n graphqlUrl,\n idToken,\n GET_ENVIRONMENT_TAGS,\n { projectId },\n );\n if (tags.errors?.length) {\n throw new Error(tags.errors[0]?.message || 'getEnvironmentTags failed');\n }\n const environmentTagId = tags.data?.getEnvironmentTags?.find((t) => t?.id?.trim())?.id?.trim() || '';\n if (!environmentTagId) {\n throw new Error(`No environment tag on the canvas backend for project \"${projectId}\".`);\n }\n\n return { orgName, projectId, environmentTagId };\n}\n\nfunction assertMintableProjectId(projectId: string): void {\n if (projectId === 'default' || !projectId.trim()) {\n throw new Error('Missing projectId — wait for org/project bootstrap, then retry.');\n }\n if (!__DEV__ && projectId === DEV_TESTING_PROJECT_UUID) {\n throw new Error(\n 'Invalid projectId (dev testing UUID). Open Home so a real project can be created, then retry.',\n );\n }\n if (!OBJECT_ID_HEX.test(projectId) && !PROJECT_UUID.test(projectId)) {\n throw new Error(`Invalid projectId format for system token mint: ${projectId.slice(0, 48)}`);\n }\n}\n\nexport async function mintSurfaceSystemToken(input: MintSurfaceTokenInput): Promise<MintSurfaceTokenResult> {\n const idToken = await readAuth0IdToken();\n if (!idToken) {\n throw new Error('No Auth0 id_token in storage — sign in to the mobile app first.');\n }\n\n const graphqlUrl = resolveSurfaceCatalogBackend(input.graphqlUrl);\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] minting system token via', graphqlUrl, input.discoverScope ? '(discover scope)' : '');\n }\n\n let orgName = input.orgName?.trim() || '';\n let projectId = input.projectId?.trim() || '';\n let environmentTagId = input.tagId?.trim() || '';\n\n if (input.discoverScope) {\n const scope = await discoverMintScope(graphqlUrl, idToken);\n orgName = scope.orgName;\n projectId = scope.projectId;\n environmentTagId = scope.environmentTagId;\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] discovered canvas scope', { orgName, projectId, environmentTagId });\n }\n }\n\n if (!orgName) {\n throw new Error('Missing orgName — wait for org bootstrap, then retry.');\n }\n if (!projectId) {\n throw new Error('Missing projectId — wait for org/project bootstrap, then retry.');\n }\n if (!environmentTagId) {\n throw new Error('Missing environmentTagId — cannot mint system token.');\n }\n assertMintableProjectId(projectId);\n\n if (input.forceRemint) {\n const existing = await gqlFetch<{ getUserSystemToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n GET_USER_SYSTEM_TOKEN,\n );\n const existingId = existing.data?.getUserSystemToken?.id ?? null;\n if (existingId) {\n await gqlFetch(graphqlUrl, idToken, REVOKE_SECRET_API_TOKEN, { id: existingId }).catch(() => undefined);\n }\n }\n\n // Canonical get-or-create (resolves project UUID → Mongo id server-side).\n try {\n const obtained = await gqlFetch<{ obtainUserSystemToken?: { token?: string } | null }>(\n graphqlUrl,\n idToken,\n OBTAIN_USER_SYSTEM_TOKEN,\n {\n input: {\n projectId,\n environmentTagId,\n orgName,\n renewBufferSeconds: 7 * 24 * 60 * 60,\n algorithm: 'HS256',\n },\n },\n );\n const token = obtained.data?.obtainUserSystemToken?.token?.trim();\n if (token && !obtained.errors?.length) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] obtained system token length=', token.length);\n }\n return { token, backend: graphqlUrl };\n }\n if (obtained.errors?.length) {\n throw new Error(obtained.errors[0]?.message || 'obtainUserSystemToken failed');\n }\n } catch (err) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilder] obtainUserSystemToken failed, falling back to reveal:', err);\n }\n // Fall through to get/create/reveal only when obtain is unavailable.\n const msg = err instanceof Error ? err.message : String(err);\n if (/12 bytes|24 hex|Project not found/i.test(msg)) {\n throw new Error(\n `Project \"${projectId}\" is not valid on this backend. Pick/create a real project in the app, then retry.`,\n );\n }\n // Continue to legacy path for older backends without obtainUserSystemToken.\n if (!/Unknown field|Cannot query field|obtainUserSystemToken/i.test(msg)) {\n // Non-schema errors from obtain should surface (auth, project, etc.).\n if (/Unauthorized|401|Project not found|Invalid project/i.test(msg)) {\n throw err instanceof Error ? err : new Error(msg);\n }\n }\n }\n\n const getResult = await gqlFetch<{ getUserSystemToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n GET_USER_SYSTEM_TOKEN,\n );\n if (getResult.errors?.length) {\n throw new Error(getResult.errors[0]?.message || 'GetUserSystemToken failed');\n }\n\n let tokenId = getResult.data?.getUserSystemToken?.id ?? null;\n\n if (!tokenId) {\n const createResult = await gqlFetch<{ createSecretApiToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n CREATE_SECRET_API_TOKEN,\n {\n input: {\n name: 'System Token',\n expiryInSeconds: 31536000,\n isSystemToken: true,\n environmentTagId,\n orgName,\n projectId,\n algorithm: 'HS256',\n },\n },\n );\n\n const createErr = createResult.errors?.[0]?.message || '';\n if (createErr && !/already have a system token/i.test(createErr)) {\n if (/12 bytes|24 hex/i.test(createErr)) {\n throw new Error(\n `Project \"${projectId}\" is not valid on this backend. Pick/create a real project in the app, then retry.`,\n );\n }\n throw new Error(createErr);\n }\n\n if (createResult.data?.createSecretApiToken?.id) {\n tokenId = createResult.data.createSecretApiToken.id;\n } else {\n const refetch = await gqlFetch<{ getUserSystemToken?: { id?: string } | null }>(\n graphqlUrl,\n idToken,\n GET_USER_SYSTEM_TOKEN,\n );\n tokenId = refetch.data?.getUserSystemToken?.id ?? null;\n }\n }\n\n if (!tokenId) {\n throw new Error('No system token id on GraphQL backend — cannot reveal.');\n }\n\n const reveal = await gqlFetch<{ revealSecretApiToken?: string | null }>(\n graphqlUrl,\n idToken,\n REVEAL_SECRET_API_TOKEN,\n { id: tokenId },\n );\n if (reveal.errors?.length) {\n throw new Error(reveal.errors[0]?.message || 'RevealSecretApiToken failed');\n }\n\n const token = reveal.data?.revealSecretApiToken?.trim();\n if (!token) {\n throw new Error('RevealSecretApiToken returned empty token');\n }\n\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilder] minted system token length=', token.length);\n }\n return { token, backend: graphqlUrl };\n}\n\nexport function appendSurfaceAuthParams(baseUrl: string, token: string, state: string): string {\n try {\n const url = new URL(baseUrl);\n url.searchParams.set('token', token);\n url.searchParams.set('code', token);\n url.searchParams.set('state', state);\n return url.toString();\n } catch {\n const sep = baseUrl.includes('?') ? '&' : '?';\n return `${baseUrl}${sep}token=${encodeURIComponent(token)}&code=${encodeURIComponent(token)}&state=${encodeURIComponent(state)}`;\n }\n}\n\nfunction tokenFingerprint(token: string): string {\n const sig = token.split('.')[2] ?? token;\n return sig.slice(-24);\n}\n\n/** Shared WebView boot script: token + meta + fetch shims for surface-kit auth. */\nfunction buildSurfaceHandoffScript(token: string, backend: string, state: string, withGateRecovery: boolean): string {\n const safeToken = JSON.stringify(token);\n const safeBackend = JSON.stringify(backend);\n const safeState = JSON.stringify(state);\n const fp = JSON.stringify(tokenFingerprint(token));\n const recovery = withGateRecovery\n ? `\n function tryRecover() {\n stamp();\n var gate = document.querySelector('[data-surface-login]');\n if (!gate) return;\n if (sessionStorage.getItem('__yantra_wb_token_reload')) return;\n sessionStorage.setItem('__yantra_wb_token_reload', '1');\n var u = new URL(window.location.href);\n u.searchParams.set('token', t);\n u.searchParams.set('code', t);\n u.searchParams.set('state', state);\n window.location.replace(u.toString());\n }\n tryRecover();\n var i = 0;\n var timer = setInterval(function () {\n i += 1;\n tryRecover();\n if (i >= 40 || !document.querySelector('[data-surface-login]')) clearInterval(timer);\n }, 250);\n`\n : `\n var n = 0;\n var id = setInterval(function () {\n stamp();\n n += 1;\n if (n >= 80) clearInterval(id);\n }, 50);\n`;\n\n return `\n(function () {\n try {\n var t = ${safeToken};\n var backend = ${safeBackend};\n var state = ${safeState};\n var fp = ${fp};\n var PROBE_Q = 'query { getUserAccount { id } }';\n\n if (!window.__yantraWbFetchPatched) {\n window.__yantraWbFetchPatched = true;\n var origFetch = window.fetch.bind(window);\n window.fetch = function (input, init) {\n try {\n var url = typeof input === 'string' ? input : (input && input.url) ? String(input.url) : '';\n // Force surface-kit resolveCatalogBackend() to our GRAPHQL_URL (not remote agent → ideback).\n if (url.indexOf('/v1/auth/context') !== -1) {\n return Promise.resolve(new Response(\n JSON.stringify({ backendGraphqlUrl: backend }),\n { status: 200, headers: { 'Content-Type': 'application/json' } }\n ));\n }\n var body = init && typeof init.body === 'string' ? init.body : '';\n if (body && body.indexOf('getUserAccount') !== -1) {\n var parsed = JSON.parse(body);\n var q = parsed && typeof parsed.query === 'string' ? parsed.query.replace(/\\\\s+/g, ' ').trim() : '';\n if (q === PROBE_Q) {\n return Promise.resolve(new Response(\n JSON.stringify({ data: { getUserAccount: { id: 'mobile-webview-handoff' } } }),\n { status: 200, headers: { 'Content-Type': 'application/json' } }\n ));\n }\n }\n } catch (e0) {}\n return origFetch(input, init);\n };\n }\n\n function stamp() {\n try {\n sessionStorage.setItem('cdecli_oauth_state', state);\n localStorage.setItem('cdecli_token', t);\n sessionStorage.setItem('cdecli_token', t);\n localStorage.setItem('cdecli_system_token', t);\n localStorage.setItem('cdecli_token_meta', JSON.stringify({\n backend: backend,\n verifiedAt: Date.now(),\n fp: fp\n }));\n } catch (e1) {}\n }\n stamp();\n ${recovery}\n } catch (e) {}\n true;\n})();\ntrue;\n`;\n}\n\nexport function buildCdecliTokenInjection(token: string, backend: string, state: string): string {\n return buildSurfaceHandoffScript(token, backend, state, false);\n}\n\nexport function buildSurfaceGateRecoveryScript(token: string, backend: string, state: string): string {\n return buildSurfaceHandoffScript(token, backend, state, true);\n}\n"],"names":["_a","token"],"mappings":"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"}
|