MCPcopy
hub / github.com/garrytan/gstack / handleReadCommand

Function handleReadCommand

browse/src/read-commands.ts:211–667  ·  view source on GitHub ↗
(
  command: string,
  args: string[],
  session: TabSession,
  bm?: BrowserManager,
)

Source from the content-addressed store, hash-verified

209}
210
211export async function handleReadCommand(
212 command: string,
213 args: string[],
214 session: TabSession,
215 bm?: BrowserManager,
216): Promise<string> {
217 const page = session.getPage();
218 // Frame-aware target for content extraction
219 const target = session.getActiveFrameOrPage();
220
221 switch (command) {
222 case 'text': {
223 return getCleanText(target);
224 }
225
226 case 'html': {
227 const selector = args[0];
228 if (selector) {
229 const resolved = await session.resolveRef(selector);
230 if ('locator' in resolved) {
231 return stripLoneSurrogates(await resolved.locator.innerHTML({ timeout: 5000 }));
232 }
233 return stripLoneSurrogates(await target.locator(resolved.selector).innerHTML({ timeout: 5000 }));
234 }
235 // page.content() is page-only; use evaluate for frame compat
236 const doctype = await target.evaluate(() => {
237 const dt = document.doctype;
238 return dt ? `<!DOCTYPE ${dt.name}>` : '';
239 });
240 const html = await target.evaluate(() => document.documentElement.outerHTML);
241 return stripLoneSurrogates(doctype ? `${doctype}\n${html}` : html);
242 }
243
244 case 'links': {
245 const links = await target.evaluate(() =>
246 [...document.querySelectorAll('a[href]')].map(a => ({
247 text: a.textContent?.trim().slice(0, 120) || '',
248 href: (a as HTMLAnchorElement).href,
249 })).filter(l => l.text && l.href)
250 );
251 return links.map(l => `${l.text} → ${l.href}`).join('\n');
252 }
253
254 case 'forms': {
255 const forms = await target.evaluate(() => {
256 return [...document.querySelectorAll('form')].map((form, i) => {
257 const fields = [...form.querySelectorAll('input, select, textarea')].map(el => {
258 const input = el as HTMLInputElement;
259 return {
260 tag: el.tagName.toLowerCase(),
261 type: input.type || undefined,
262 name: input.name || undefined,
263 id: input.id || undefined,
264 placeholder: input.placeholder || undefined,
265 required: input.required || undefined,
266 value: input.type === 'password'
267 || (input.name && /(^|[_.-])(token|secret|key|password|credential|auth|jwt|session|csrf|sid)($|[_.-])|api.?key/i.test(input.name))
268 || (input.id && /(^|[_.-])(token|secret|key|password|credential|auth|jwt|session|csrf|sid)($|[_.-])|api.?key/i.test(input.id))

Callers 6

snapshot.test.tsFile · 0.90
commands.test.tsFile · 0.90
handleMetaCommandFunction · 0.70

Calls 15

stripLoneSurrogatesFunction · 0.90
validateReadPathFunction · 0.90
getModificationHistoryFunction · 0.90
formatInspectorResultFunction · 0.90
inspectElementFunction · 0.90
getCleanTextFunction · 0.85
parseOutArgsFunction · 0.85
assertJsOriginAllowedFunction · 0.85
wrapForEvaluateFunction · 0.85
resultToStringFunction · 0.85
writeEvalResultFunction · 0.85
getCaptureListenerFunction · 0.85

Tested by

no test coverage detected