@gpzhang2001/sharpkit-proxy 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Buffer"],"sources":["../src/replay.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\n * Pure HTTP replay helpers, ported from strix tools/proxy/caido_api.py:\n * raw request parsing/rebuilding with framing-header hygiene (:173-218),\n * response parsing (:220-258), request-line parsing (:260-279), URL\n * composition (:281-292), and field modifications (:294-331). Total pure\n * functions — exhaustively unit-testable.\n * @module @gpzhang2001/sharpkit-proxy/replay\n */\n\n/** Parsed components of a raw HTTP request text. */\nexport interface RawRequestComponents {\n readonly method: string\n readonly urlPath: string\n readonly headers: Record<string, string>\n readonly body: string\n}\n\n/** A connection target for Caido's replay dispatch. */\nexport interface ConnectionInfo {\n readonly host: string\n readonly port: number\n readonly tls: boolean\n readonly sni?: string\n}\n\n/** Parsed summary of a raw HTTP response (strix list_requests shape). */\nexport interface RawResponseParts {\n readonly statusCode: number\n readonly length: number\n readonly headers: Record<string, string>\n readonly body: string\n readonly bodyTruncated: boolean\n}\n\n/** strix clips replay response bodies at 8192 chars (caido_api.py:222). */\nconst RESPONSE_BODY_MAX_CHARS = 8192\n\n/** Framing headers that must never survive into a modified replay (strix :175). */\nconst FRAMING_HEADERS = new Set(['content-length', 'transfer-encoding'])\n\n/**\n * Parse a raw HTTP request text into components (strix `parse_raw_request`).\n * @param rawContent - the raw request text.\n * @returns the parsed components.\n * @throws when the request line is malformed.\n */\nexport function parseRawRequest(rawContent: string): RawRequestComponents {\n const lines = rawContent.split('\\n')\n const requestLine = (lines[0] ?? '').trim().split(' ')\n if (requestLine.length < 2) throw new Error('Invalid request line format')\n const headers: Record<string, string> = {}\n let bodyStart = 0\n for (let index = 1; index < lines.length; index++) {\n const line = lines[index] ?? ''\n if (line.trim() === '') {\n bodyStart = index + 1\n break\n }\n const separator = line.indexOf(':')\n if (separator !== -1) headers[line.slice(0, separator).trim()] = line.slice(separator + 1).trim()\n }\n const body = bodyStart < lines.length ? lines.slice(bodyStart).join('\\n').trim() : ''\n return { method: requestLine[0] ?? '', urlPath: requestLine[1] ?? '', headers, body }\n}\n\n/**\n * Compose the full URL from the original request's connection facts, the\n * parsed components, and an optional explicit url override (strix\n * `full_url_from_components`).\n * @param original - the stored request's host/tls facts.\n * @param components - parsed raw request components.\n * @param modifications - the patch dict.\n * @returns the absolute target URL.\n */\nexport function fullUrlFromComponents(\n original: { readonly host: string; readonly tls: boolean },\n components: RawRequestComponents,\n modifications: Readonly<Record<string, unknown>>,\n): string {\n const override = modifications['url']\n if (typeof override === 'string' && override !== '') return override\n const hostHeader = components.headers['Host'] ?? original.host\n const scheme = original.tls ? 'https' : 'http'\n return `${scheme}://${hostHeader}${components.urlPath}`\n}\n\n/** Parse a query string into a first-value map (Node parity of parse_qs). */\nfunction parseQuery(query: string): Record<string, string> {\n const params: Record<string, string> = {}\n for (const pair of query.split('&')) {\n if (pair === '') continue\n const eq = pair.indexOf('=')\n const key = eq === -1 ? pair : pair.slice(0, eq)\n const value = eq === -1 ? '' : pair.slice(eq + 1)\n params[decodeURIComponent(key)] = decodeURIComponent(value)\n }\n return params\n}\n\n/** Serialize a query map back to a string (Node parity of urlencode). */\nfunction encodeQuery(params: Readonly<Record<string, string>>): string {\n return Object.entries(params)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&')\n}\n\n/**\n * Overlay the patch dict onto parsed components (strix `apply_modifications`):\n * params merge into the query string, headers/cookies merge, body replaces.\n * @param components - parsed raw request components.\n * @param modifications - the patch dict (url/params/headers/body/cookies).\n * @param fullUrl - the composed final URL.\n * @returns the modified components keyed like strix.\n */\nexport function applyModifications(\n components: RawRequestComponents,\n modifications: Readonly<Record<string, unknown>>,\n fullUrl: string,\n): { readonly method: string; readonly url: string; readonly headers: Record<string, string>; readonly body: string } {\n const headers = { ...components.headers }\n let body = components.body\n let finalUrl = fullUrl\n\n const params = modifications['params']\n if (params !== undefined && params !== null && typeof params === 'object') {\n const question = finalUrl.indexOf('?')\n const existing = question === -1 ? {} : parseQuery(finalUrl.slice(question + 1))\n for (const [key, value] of Object.entries(params as Record<string, unknown>)) {\n existing[key] = String(value)\n }\n const base = question === -1 ? finalUrl : finalUrl.slice(0, question)\n finalUrl = `${base}?${encodeQuery(existing)}`\n }\n const headerPatch = modifications['headers']\n if (headerPatch !== undefined && headerPatch !== null && typeof headerPatch === 'object') {\n for (const [key, value] of Object.entries(headerPatch as Record<string, unknown>)) {\n headers[key] = String(value)\n }\n }\n const bodyPatch = modifications['body']\n if (typeof bodyPatch === 'string') body = bodyPatch\n const cookiePatch = modifications['cookies']\n if (cookiePatch !== undefined && cookiePatch !== null && typeof cookiePatch === 'object') {\n const cookies: Record<string, string> = {}\n const existingCookie = headers['Cookie']\n if (existingCookie !== undefined) {\n for (const cookie of existingCookie.split(';')) {\n const eq = cookie.indexOf('=')\n if (eq !== -1) cookies[cookie.slice(0, eq).trim()] = cookie.slice(eq + 1).trim()\n }\n }\n for (const [key, value] of Object.entries(cookiePatch as Record<string, unknown>)) {\n cookies[key] = String(value)\n }\n headers['Cookie'] = Object.entries(cookies).map(([key, value]) => `${key}=${value}`).join('; ')\n }\n\n return { method: components.method, url: finalUrl, headers, body }\n}\n\n/**\n * Rebuild a raw HTTP/1.1 request with connection facts (strix\n * `build_raw_request`): Host/UA defaults, framing headers dropped,\n * Content-Length recomputed from the actual body.\n * @param parts - method/url/headers/body of the replay.\n * @returns the connection target and encoded raw request bytes.\n */\nexport function buildRawRequest(parts: {\n readonly method: string\n readonly url: string\n readonly headers: Record<string, string>\n readonly body: string\n}): { readonly connection: ConnectionInfo; readonly raw: Uint8Array } {\n let parsed: URL\n try {\n parsed = new URL(parts.url)\n } catch {\n throw new Error(`Invalid URL: ${parts.url}`)\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') throw new Error(`Invalid URL: ${parts.url}`)\n const tls = parsed.protocol === 'https:'\n const port = parsed.port !== '' ? Number(parsed.port) : tls ? 443 : 80\n const path = `${parsed.pathname}${parsed.search}`\n\n const headers: Record<string, string> = { ...parts.headers }\n if (headers['Host'] === undefined) headers['Host'] = parsed.host\n if (headers['User-Agent'] === undefined) {\n headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'\n }\n for (const key of Object.keys(headers)) {\n if (FRAMING_HEADERS.has(key.toLowerCase())) delete headers[key]\n }\n if (parts.body !== '') headers['Content-Length'] = String(Buffer.byteLength(parts.body, 'utf8'))\n\n const lines = [`${parts.method.toUpperCase()} ${path} HTTP/1.1`]\n for (const [key, value] of Object.entries(headers)) lines.push(`${key}: ${value}`)\n const raw = Buffer.from(`${lines.join('\\r\\n')}\\r\\n\\r\\n${parts.body}`, 'utf8')\n return { connection: { host: parsed.hostname, port, tls }, raw }\n}\n\n/**\n * Parse a raw HTTP response into the list_requests summary shape (strix\n * `parse_raw_response`); null when missing/unparseable. Body clipped at 8192\n * chars with a truncation flag.\n * @param rawBytes - the raw response bytes.\n * @returns the parsed parts, or null.\n */\nexport function parseRawResponse(rawBytes: Uint8Array | null | undefined): RawResponseParts | null {\n if (rawBytes === null || rawBytes === undefined || rawBytes.byteLength === 0) return null\n const text = Buffer.from(rawBytes).toString('latin1')\n const separator = text.indexOf('\\r\\n\\r\\n')\n if (separator === -1) return null\n const head = text.slice(0, separator)\n const lines = head.split('\\r\\n')\n const statusParts = (lines[0] ?? '').split(' ')\n if (statusParts.length < 2 || !/^\\d+$/.test(statusParts[1] ?? '')) return null\n const headers: Record<string, string> = {}\n for (const line of lines.slice(1)) {\n const colon = line.indexOf(':')\n if (colon === -1) continue\n headers[line.slice(0, colon).trim()] = line.slice(colon + 1).trim()\n }\n const bodyBytes = Buffer.from(text.slice(separator + 4), 'latin1')\n let body = bodyBytes.toString('utf8')\n const truncated = body.length > RESPONSE_BODY_MAX_CHARS\n if (truncated) body = body.slice(0, RESPONSE_BODY_MAX_CHARS)\n return { statusCode: Number(statusParts[1]), length: bodyBytes.byteLength, headers, body, bodyTruncated: truncated }\n}\n","/**\n * Caido HTTP/GraphQL client — TS port of the CLIENT half of strix\n * tools/proxy/caido_api.py against the HOST-side published endpoint (global\n * fetch + Bearer token from the sandbox session's bootstrap). Documents are\n * trimmed, schema-valid subsets of the caido_sdk_client generated operations\n * (Requests/Request/ReplayEntry/StartReplayTask/sitemap trio). The replay\n * flow adapts the SDK's subscription wait into bounded polling of the entry\n * (finished when a response or an error appears; 30s strix dispatch budget).\n * @module @gpzhang2001/sharpkit-proxy/client\n */\n\nimport { Buffer } from 'node:buffer'\nimport { buildRawRequest, fullUrlFromComponents, applyModifications, parseRawRequest, parseRawResponse, type RawResponseParts } from './replay.ts'\n\n/** Which half of a captured exchange to surface (strix RequestPart). */\nexport type RequestPart = 'request' | 'response'\n\n/** Sort keys accepted by list_requests (strix SortBy). */\nexport type SortBy = 'timestamp' | 'host' | 'method' | 'path' | 'status_code' | 'response_time' | 'response_size' | 'source'\n\n/** strix `_REQ_FIELD_MAP` resolved to Caido's RequestResponseOrderBy enums. */\nconst SORT_ENUMS: Record<SortBy, string> = {\n timestamp: 'CREATED_AT',\n host: 'HOST',\n method: 'METHOD',\n path: 'PATH',\n source: 'SOURCE',\n status_code: 'RESP_STATUS_CODE',\n response_time: 'RESP_ROUNDTRIP_TIME',\n response_size: 'RESP_LENGTH',\n}\n\n/** The one Caido port the sandbox publishes (protocol constant). */\nexport const CAIDO_PORT = 48080\n\n/** Compact Requests query (subset of the SDK's generated document). */\nconst REQUESTS_DOC = `query Requests($first: Int, $after: String, $filter: HTTPQLInput, $order: RequestResponseOrderInput, $scopeId: ID, $includeRequestRaw: Boolean!, $includeResponseRaw: Boolean!) {\n requests(first: $first, after: $after, filter: $filter, order: $order, scopeId: $scopeId) {\n edges { cursor node {\n id host port method path query isTls createdAt\n raw @include(if: $includeRequestRaw)\n response { id statusCode roundtripTime length createdAt raw @include(if: $includeResponseRaw) }\n } }\n pageInfo { hasNextPage hasPreviousPage startCursor endCursor }\n }\n}`\n\n/** Compact Request query (both raws always requested — SDK parity note). */\nconst REQUEST_DOC = `query Request($id: ID!, $includeRequestRaw: Boolean!, $includeResponseRaw: Boolean!) {\n request(id: $id) {\n id host port method path query isTls createdAt\n raw @include(if: $includeRequestRaw)\n response { id statusCode roundtripTime length createdAt raw @include(if: $includeResponseRaw) }\n }\n}`\n\n/** Empty replay session create (avoids the double history row the raw-create seeds). */\nconst CREATE_REPLAY_SESSION_DOC = `mutation CreateReplaySession($input: CreateReplaySessionInput!) {\n createReplaySession(input: $input) { session { id } error { __typename } }\n}`\n\n/** Replay dispatch (strix `replay_send_raw` via the SDK's StartReplayTask). */\nconst START_REPLAY_TASK_DOC = `mutation StartReplayTask($sessionId: ID!, $input: StartReplayTaskInput!) {\n startReplayTask(sessionId: $sessionId, input: $input) { error { __typename } task { id replayEntry { id } } }\n}`\n\n/** Replay entry poll — finished when request.response or error appears. */\nconst REPLAY_ENTRY_DOC = `query ReplayEntry($id: ID!, $includeReplayRaw: Boolean!, $includeRequestRaw: Boolean!, $includeResponseRaw: Boolean!) {\n replayEntry(id: $id) {\n id error\n request { id method path response { id statusCode length roundtripTime raw @include(if: $includeResponseRaw) } }\n }\n}`\n\n/** Scope management (strix caido_api.py scope_* via the SDK's ScopeFull set). */\nconst SCOPES_DOC = `query Scopes { scopes { id name allowlist denylist indexed } }`\n\nconst SCOPE_DOC = `query Scope($id: ID!) { scope(id: $id) { id name allowlist denylist indexed } }`\n\nconst CREATE_SCOPE_DOC = `mutation CreateScope($input: CreateScopeInput!) { createScope(input: $input) { error { __typename } scope { id name allowlist denylist indexed } } }`\n\nconst UPDATE_SCOPE_DOC = `mutation UpdateScope($id: ID!, $input: UpdateScopeInput!) { updateScope(id: $id, input: $input) { error { __typename } scope { id name allowlist denylist indexed } } }`\n\nconst DELETE_SCOPE_DOC = `mutation DeleteScope($id: ID!) { deleteScope(id: $id) { deletedId } }`\n\n/** Sitemap queries (verbatim field sets from strix caido_api.py:555-592). */\nconst SITEMAP_ROOTS_DOC = `query GetSitemapRoots($scopeId: ID) {\n sitemapRootEntries(scopeId: $scopeId) {\n edges { node {\n id kind label hasDescendants\n metadata { ... on SitemapEntryMetadataDomain { isTls port } }\n request { method path response { statusCode } }\n } }\n count { value }\n }\n}`\n\nconst SITEMAP_DESCENDANTS_DOC = `query GetSitemapDescendants($parentId: ID!, $depth: SitemapDescendantsDepth!) {\n sitemapDescendantEntries(parentId: $parentId, depth: $depth) {\n edges { node {\n id kind label hasDescendants\n request { method path response { statusCode } }\n } }\n count { value }\n }\n}`\n\nconst SITEMAP_ENTRY_DOC = `query GetSitemapEntry($id: ID!) {\n sitemapEntry(id: $id) {\n id kind label hasDescendants\n metadata { ... on SitemapEntryMetadataDomain { isTls port } }\n request { method path response { statusCode length roundtripTime } }\n requests(first: 30, order: {by: CREATED_AT, ordering: DESC}) {\n edges { node { method path response { statusCode length } } }\n count { value }\n }\n }\n}`\n\n/** Fetch contract (global fetch shape) for the GraphQL endpoint. */\nexport interface CaidoFetchFn {\n (url: string, init: { readonly method: 'POST'; readonly headers: Readonly<Record<string, string>>; readonly body: string; readonly signal: AbortSignal }): Promise<{ readonly status: number; readonly text: () => Promise<string> }>\n}\n\n/** One captured request entry projected for the model (strix shape). */\nexport interface RequestListEntry {\n readonly cursor: string\n readonly request: {\n readonly id: string\n readonly host: string\n readonly port: number\n readonly method: string\n readonly path: string\n readonly query: string | null\n readonly tls: boolean\n readonly createdAt: string\n }\n readonly response: { readonly id: string; readonly statusCode: number | null; readonly length: number | null; readonly createdAt: string | null } | null\n}\n\n/** PageInfo projection (strix page_info). */\nexport interface CaidoPageInfo {\n readonly hasNextPage: boolean\n readonly hasPreviousPage: boolean\n readonly startCursor: string | null\n readonly endCursor: string | null\n}\n\n/** The raw halves of one stored request. */\nexport interface StoredRequest {\n readonly id: string\n readonly host: string\n readonly port: number\n readonly method: string\n readonly tls: boolean\n readonly requestRaw: string | null\n readonly responseRaw: string | null\n}\n\n/** Replay outcome (strix `_format_replay_tool_result` inputs). */\nexport interface ReplayOutcome {\n readonly sessionId: string\n readonly status: string\n readonly elapsedMs: number\n readonly error?: string\n readonly response: RawResponseParts | null\n}\n\n/** Endpoint coordinates handed over by the sandbox session's bootstrap. */\nexport interface CaidoClientOptions {\n readonly baseUrl: string\n readonly token: string\n readonly fetchFn?: CaidoFetchFn\n}\n\n/** Minimal GraphQL POST with bearer auth and error normalization. */\nasync function graphql<T>(\n options: CaidoClientOptions,\n doc: string,\n variables: Record<string, unknown>,\n signal: AbortSignal,\n): Promise<T> {\n const fetchFn = options.fetchFn ?? fetch\n const response = await fetchFn(`${options.baseUrl}/graphql`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${options.token}` },\n body: JSON.stringify({ query: doc, variables }),\n signal,\n })\n const text = await response.text()\n if (response.status !== 200) throw new Error(`caido graphql HTTP ${response.status}: ${text.slice(0, 200)}`)\n let payload: unknown\n try {\n payload = JSON.parse(text)\n } catch (error) {\n throw new Error(`caido graphql unparseable response: ${String(error)}`)\n }\n const record = payload as { readonly data?: unknown; readonly errors?: unknown }\n if (record.errors !== undefined && record.errors !== null) {\n throw new Error(`caido graphql errors: ${JSON.stringify(record.errors).slice(0, 300)}`)\n }\n if (typeof record.data !== 'object' || record.data === null) {\n throw new Error('caido graphql carried no data')\n }\n return record.data as T\n}\n\n/** Project one raw requests-connection edge (strix list_requests mapping). */\nfunction projectEdge(edge: unknown): RequestListEntry {\n const node = (edge as { node: Record<string, unknown> }).node\n const response = node.response as Record<string, unknown> | null\n return {\n cursor: String((edge as { cursor: unknown }).cursor),\n request: {\n id: String(node.id),\n host: String(node.host),\n port: Number(node.port),\n method: String(node.method),\n path: String(node.path),\n query: node.query === null || node.query === undefined ? null : String(node.query),\n tls: node.isTls === true,\n createdAt: new Date(Number(node.createdAt)).toISOString(),\n },\n response: response === null || response === undefined ? null : {\n id: String(response.id),\n statusCode: response.statusCode === null || response.statusCode === undefined ? null : Number(response.statusCode),\n length: response.length === null || response.length === undefined ? null : Number(response.length),\n createdAt: response.createdAt === null || response.createdAt === undefined ? null : new Date(Number(response.createdAt)).toISOString(),\n },\n }\n}\n\n/**\n * The Caido client: five operations behind the five proxy tools. All methods\n * take an AbortSignal (tool exec.signal parity).\n */\nexport class CaidoClient {\n private readonly options: CaidoClientOptions\n\n constructor(options: CaidoClientOptions) {\n this.options = options\n }\n\n /** List captured requests with HTTPQL filter/cursor/sort/scope (strix list_requests_with_client). */\n async listRequests(options: {\n readonly httpqlFilter?: string | undefined\n readonly first?: number | undefined\n readonly after?: string | undefined\n readonly sortBy?: SortBy | undefined\n readonly sortOrder?: 'asc' | 'desc' | undefined\n readonly scopeId?: string | undefined\n }, signal: AbortSignal): Promise<{ readonly entries: RequestListEntry[]; readonly pageInfo: CaidoPageInfo }> {\n const data = await graphql<{ requests: { edges: unknown[]; pageInfo: Record<string, unknown> } }>(\n this.options,\n REQUESTS_DOC,\n {\n first: options.first ?? 50,\n ...(options.after !== undefined && options.after !== '' ? { after: options.after } : {}),\n ...(options.httpqlFilter !== undefined && options.httpqlFilter !== '' ? { filter: { code: options.httpqlFilter } } : {}),\n order: { by: SORT_ENUMS[options.sortBy ?? 'timestamp'], ordering: (options.sortOrder ?? 'desc') === 'asc' ? 'ASC' : 'DESC' },\n ...(options.scopeId !== undefined && options.scopeId !== '' ? { scopeId: options.scopeId } : {}),\n includeRequestRaw: false,\n includeResponseRaw: false,\n },\n signal,\n )\n return {\n entries: data.requests.edges.map(projectEdge),\n pageInfo: {\n hasNextPage: data.requests.pageInfo.hasNextPage === true,\n hasPreviousPage: data.requests.pageInfo.hasPreviousPage === true,\n startCursor: data.requests.pageInfo.startCursor === null || data.requests.pageInfo.startCursor === undefined ? null : String(data.requests.pageInfo.startCursor),\n endCursor: data.requests.pageInfo.endCursor === null || data.requests.pageInfo.endCursor === undefined ? null : String(data.requests.pageInfo.endCursor),\n },\n }\n }\n\n /** Fetch one request with both raw halves (strix get_request_with_client parity: always request both). */\n async getRequest(requestId: string, signal: AbortSignal): Promise<StoredRequest | null> {\n const data = await graphql<{ request: Record<string, unknown> | null }>(\n this.options,\n REQUEST_DOC,\n { id: requestId, includeRequestRaw: true, includeResponseRaw: true },\n signal,\n )\n const request = data.request\n if (request === null || request === undefined) return null\n return {\n id: String(request.id),\n host: String(request.host),\n port: Number(request.port),\n method: String(request.method),\n tls: request.isTls === true,\n requestRaw: request.raw === null || request.raw === undefined ? null : Buffer.from(String(request.raw), 'base64').toString('utf8'),\n responseRaw: (request.response as Record<string, unknown> | null | undefined)?.raw === null\n || (request.response as Record<string, unknown> | null | undefined)?.raw === undefined\n ? null\n : Buffer.from(String((request.response as Record<string, unknown>).raw), 'base64').toString('utf8'),\n }\n }\n\n /**\n * Replay one stored request with optional field patches (strix\n * `repeat_request` + `replay_send_raw`): fetch raw → parse → patch →\n * rebuild → create empty session → startReplayTask → poll the entry.\n * @param requestId - the stored request id.\n * @param modifications - patch dict (url/params/headers/body/cookies).\n * @param budget - total dispatch deadline (strix 30s) + poll interval.\n */\n async replayRequest(\n requestId: string,\n modifications: Readonly<Record<string, unknown>> | undefined,\n signal: AbortSignal,\n budget: { readonly dispatchTimeoutMs: number; readonly pollIntervalMs: number },\n ): Promise<ReplayOutcome | null> {\n const stored = await this.getRequest(requestId, signal)\n if (stored === null || stored.requestRaw === null) return null\n const components = parseRawRequest(stored.requestRaw)\n const fullUrl = fullUrlFromComponents({ host: stored.host, tls: stored.tls }, components, modifications ?? {})\n const modified = applyModifications(components, modifications ?? {}, fullUrl)\n const built = buildRawRequest(modified)\n\n const session = await graphql<{ createReplaySession: { session: { id: string } | null; error: unknown } }>(\n this.options,\n CREATE_REPLAY_SESSION_DOC,\n { input: {} },\n signal,\n )\n const createdSession = session.createReplaySession.session\n if (createdSession === null || createdSession === undefined) throw new Error('createReplaySession returned no session')\n\n const started = Date.now()\n const start = await graphql<{ startReplayTask: { error: unknown; task: { id: string; replayEntry: { id: string } | null } | null } }>(\n this.options,\n START_REPLAY_TASK_DOC,\n {\n sessionId: createdSession.id,\n input: {\n connection: { host: built.connection.host, port: built.connection.port, isTLS: built.connection.tls, SNI: null },\n raw: Buffer.from(built.raw).toString('base64'),\n settings: { connectionClose: false, updateContentLength: true, placeholders: [] },\n },\n },\n signal,\n )\n const task = start.startReplayTask.task\n if (start.startReplayTask.error !== null && start.startReplayTask.error !== undefined) {\n throw new Error(`startReplayTask failed: ${JSON.stringify(start.startReplayTask.error).slice(0, 200)}`)\n }\n if (task === null || task === undefined || task.replayEntry === null || task.replayEntry === undefined) {\n throw new Error('startReplayTask returned no task/entry')\n }\n\n // Bounded poll (SDK waits on a subscription; polling keeps us HTTP-only).\n for (;;) {\n const entry = await graphql<{ replayEntry: Record<string, unknown> | null }>(\n this.options,\n REPLAY_ENTRY_DOC,\n { id: task.replayEntry.id, includeReplayRaw: false, includeRequestRaw: false, includeResponseRaw: true },\n signal,\n )\n const node = entry.replayEntry\n if (node !== null && node !== undefined) {\n const errorText = node.error === null || node.error === undefined ? undefined : String(node.error)\n const request = node.request as { response?: Record<string, unknown> | null } | null | undefined\n const responseNode = request?.response ?? null\n if (responseNode !== null && responseNode !== undefined) {\n const rawBase64 = responseNode.raw\n const rawBytes = rawBase64 === null || rawBase64 === undefined ? null : Buffer.from(String(rawBase64), 'base64')\n return {\n sessionId: createdSession.id,\n status: 'DONE',\n elapsedMs: Date.now() - started,\n ...(errorText !== undefined ? { error: errorText } : {}),\n response: parseRawResponse(rawBytes),\n }\n }\n if (errorText !== undefined) {\n return { sessionId: createdSession.id, status: 'ERROR', elapsedMs: Date.now() - started, error: errorText, response: null }\n }\n }\n if (Date.now() - started > budget.dispatchTimeoutMs) {\n return {\n sessionId: createdSession.id,\n status: 'ERROR',\n elapsedMs: Date.now() - started,\n error: `Caido replay dispatch did not complete within ${String(Math.round(budget.dispatchTimeoutMs / 1000))}s — the target may be unroutable from the sandbox, or Caido's outbound HTTP client is stalled; check the target host/port and retry`,\n response: null,\n }\n }\n await new Promise(resolve => setTimeout(resolve, budget.pollIntervalMs))\n }\n }\n\n /** Sitemap roots or descendants (strix list_sitemap_with_client). */\n async listSitemap(options: {\n readonly scopeId?: string | undefined\n readonly parentId?: string | undefined\n readonly depth?: 'DIRECT' | 'ALL' | undefined\n }, signal: AbortSignal): Promise<unknown> {\n if (options.parentId !== undefined && options.parentId !== '') {\n return graphql(this.options, SITEMAP_DESCENDANTS_DOC, { parentId: options.parentId, depth: options.depth ?? 'DIRECT' }, signal)\n }\n return graphql(this.options, SITEMAP_ROOTS_DOC, options.scopeId !== undefined && options.scopeId !== '' ? { scopeId: options.scopeId } : {}, signal)\n }\n\n /** One sitemap entry with its 30 most recent requests (strix view_sitemap_entry_with_client). */\n async viewSitemapEntry(entryId: string, signal: AbortSignal): Promise<unknown> {\n return graphql(this.options, SITEMAP_ENTRY_DOC, { id: entryId }, signal)\n }\n\n /** All Caido scopes (strix scope_list). */\n async scopeList(signal: AbortSignal): Promise<unknown> {\n return graphql(this.options, SCOPES_DOC, {}, signal)\n }\n\n /** One scope by id (strix scope_get). */\n async scopeGet(scopeId: string, signal: AbortSignal): Promise<unknown> {\n return graphql(this.options, SCOPE_DOC, { id: scopeId }, signal)\n }\n\n /** Create a scope; empty lists allow-all/deny-none (strix scope_create). */\n async scopeCreate(name: string, allowlist: string[], denylist: string[], signal: AbortSignal): Promise<unknown> {\n return graphql(this.options, CREATE_SCOPE_DOC, { input: { name, allowlist, denylist } }, signal)\n }\n\n /** Update a scope; allow/deny lists FULLY REPLACE the previous values (strix parity). */\n async scopeUpdate(scopeId: string, name: string, allowlist: string[], denylist: string[], signal: AbortSignal): Promise<unknown> {\n return graphql(this.options, UPDATE_SCOPE_DOC, { id: scopeId, input: { name, allowlist, denylist } }, signal)\n }\n\n /** Delete a scope (strix scope_delete). */\n async scopeDelete(scopeId: string, signal: AbortSignal): Promise<unknown> {\n return graphql(this.options, DELETE_SCOPE_DOC, { id: scopeId }, signal)\n }\n}\n","/**\n * Caido proxy tools — TS port of strix tools/proxy/tools.py (schemas and\n * output shaping verbatim; the client half lives in client.ts, replay pure\n * helpers in replay.ts). Five tools: list_requests / view_request /\n * repeat_request / list_sitemap / view_sitemap_entry. The client resolves\n * lazily from the sandbox session's Caido bootstrap (concurrent with scan\n * start; the first tool call pays the login wait — strix lazy parity).\n * @module @gpzhang2001/sharpkit-proxy\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\nimport type Schema from '@deepseek-ai/schemastery'\nimport z from '@deepseek-ai/schemastery'\nimport { defineTool } from '@deepseek-ai/dsh-tools'\nimport { CaidoClient, type SortBy } from './client.ts'\n\n/** Deployment-tunable configuration. */\nexport interface Config {\n /** Sandbox session cache key shared with the other tool packages. */\n readonly scanId?: string\n /** list_requests page size default (strix first=50). */\n readonly listPageSize?: number\n /** Replay dispatch deadline (strix 30s). */\n readonly replayTimeoutMs?: number\n /** Client-level per-call timeout (strix @function_tool timeout=60/120). */\n readonly caidoTimeoutMs?: number\n /** Ask-approval gate on repeat_request (fail-closed without an approval service). */\n readonly requireApproval?: boolean\n /** Authorized target hosts/values; repeat_request refuses hosts outside this list (exact or dot-suffix subdomain). */\n readonly authorizedTargets?: string[]\n}\n\nexport const name = 'pentest-tool-proxy'\n\nexport const inject = ['tools', 'pentestSandbox']\n\nexport const Config: Schema<Config> = z.object({\n scanId: z.string().default('pentest'),\n listPageSize: z.number().default(50),\n replayTimeoutMs: z.number().default(30_000),\n caidoTimeoutMs: z.number().default(60_000),\n requireApproval: z.boolean().default(true),\n authorizedTargets: z.array(z.string()),\n})\n\n/**\n * Whether a repeat target host is inside the authorized list. Entries may be\n * bare hosts (`example.com`), wildcard subdomains (`*.example.com`), or full\n * URLs (hostname taken); a candidate matches on exact host or a dot-suffix\n * subdomain. An empty list allows everything (fail-open; warned once).\n * @param host - the replay target hostname.\n * @param authorized - the configured target entries.\n */\nexport function targetHostAllowed(host: string, authorized: readonly string[]): boolean {\n if (authorized.length === 0) return true\n const candidate = host.toLowerCase()\n return authorized.some(entry => {\n let allowed = entry.trim().toLowerCase()\n if (allowed === '') return false\n if (allowed.includes('://')) {\n try {\n allowed = new URL(allowed).hostname\n } catch {\n // keep the raw entry\n }\n }\n allowed = allowed.replace(/^\\*\\./, '').replace(/\\/.*$/, '')\n return allowed !== '' && (candidate === allowed || candidate.endsWith(`.${allowed}`))\n })\n}\n\n/**\n * Resolve the replay target hostname: an explicit url modification wins;\n * otherwise the stored request's host.\n */\nexport function resolveRepeatTargetHost(storedHost: string, modifications: Readonly<Record<string, unknown>> | undefined): string {\n const override = modifications?.['url']\n if (typeof override === 'string' && override !== '') {\n try {\n return new URL(override).hostname\n } catch {\n // fall through to the stored host\n }\n }\n return storedHost\n}\n\n/** Sitemap page size (strix parity: 30 entries per page). */\nexport const SITEMAP_PAGE_SIZE = 30\n\n/**\n * Slice one sitemap connection payload to a 1-indexed page of edges (the\n * total count is preserved). Payloads without a recognized connection pass\n * through untouched.\n */\nexport function pageSitemapPayload(payload: Record<string, unknown>, page: number): Record<string, unknown> {\n for (const key of ['sitemapRootEntries', 'sitemapDescendantEntries']) {\n const connection = payload[key]\n if (typeof connection !== 'object' || connection === null) continue\n const edges = (connection as { edges?: unknown }).edges\n if (!Array.isArray(edges)) continue\n const start = Math.max(0, (page - 1) * SITEMAP_PAGE_SIZE)\n const sliced = edges.slice(start, start + SITEMAP_PAGE_SIZE)\n return { ...payload, [key]: { ...(connection as Record<string, unknown>), edges: sliced, page, page_size: SITEMAP_PAGE_SIZE, has_more: start + SITEMAP_PAGE_SIZE < edges.length } }\n }\n return payload\n}\n\n/** strix view_request search hits: ≤20 matches with ±40 chars of context. */\ninterface SearchHit {\n readonly match: string\n readonly position: number\n readonly before: string\n readonly after: string\n}\n\n/**\n * Compact regex hits over raw content (strix `_format_search_hits`).\n * @param content - the raw text.\n * @param pattern - the model-supplied regex.\n * @returns the hits payload, or an error entry when the regex is invalid.\n */\nexport function formatSearchHits(content: string, pattern: string): { readonly hits: SearchHit[]; readonly totalHits: number; readonly error?: string } {\n let regex: RegExp\n try {\n regex = new RegExp(pattern, 'g')\n } catch (error) {\n return { hits: [], totalHits: 0, error: `Invalid regex: ${String(error)}` }\n }\n const hits: SearchHit[] = []\n for (const match of content.matchAll(regex)) {\n const start = match.index ?? 0\n const end = start + match[0].length\n hits.push({ match: match[0], position: start, before: content.slice(Math.max(0, start - 40), start), after: content.slice(end, end + 40) })\n if (hits.length >= 20) break\n }\n return { hits, totalHits: hits.length }\n}\n\n/**\n * Line-paginated raw content page (strix `_format_text_page`).\n * @param content - the raw text.\n * @param page - 1-indexed page number.\n * @param pageSize - lines per page.\n */\nexport function formatTextPage(content: string, page: number, pageSize: number): {\n readonly content: string\n readonly page: number\n readonly pageSize: number\n readonly totalLines: number\n readonly hasMore: boolean\n} {\n const lines = content.split('\\n')\n const start = Math.max(0, (page - 1) * pageSize)\n const end = start + pageSize\n return { content: lines.slice(start, end).join('\\n'), page, pageSize, totalLines: lines.length, hasMore: end < lines.length }\n}\n\n/** Strip undefined values so an object satisfies the JsonValue index contract. */\nfunction structuredToPlain(value: Record<string, unknown>): { [key: string]: JsonValueLike } {\n const plain: { [key: string]: JsonValueLike } = JSON.parse(JSON.stringify(value)) as { [key: string]: JsonValueLike }\n return plain\n}\n\n/** Local structural twin of the tool-runtime JsonValue (type-only import). */\ntype JsonValueLike = string | number | boolean | null | JsonValueLike[] | { [key: string]: JsonValueLike }\n\ninterface ToolRunContextLike {\n readonly signal: AbortSignal\n}\n\n/** Unwrap the GraphQL envelope for one scope row. */\nfunction plainScope(envelope: unknown): Record<string, unknown> {\n const record = envelope as Record<string, unknown>\n for (const key of ['scope', 'createScope', 'updateScope']) {\n const inner = record[key]\n if (typeof inner === 'object' && inner !== null) {\n const scope = (inner as Record<string, unknown>)['scope']\n if (typeof scope === 'object' && scope !== null) return scope as Record<string, unknown>\n }\n }\n return record\n}\n\n/** Unwrap a scopes list envelope. */\nfunction plainScopes(rows: unknown[]): Record<string, unknown>[] {\n return rows.filter((row): row is Record<string, unknown> => typeof row === 'object' && row !== null)\n}\n\n/** Canonical value of view_request (oneOf the two modes + error). */\ntype ViewRequestValue = {\n readonly kind: 'hits'\n readonly hits: SearchHit[]\n readonly total_hits: number\n} | {\n readonly kind: 'page'\n readonly content: string\n readonly page: number\n readonly page_size: number\n readonly total_lines: number\n readonly has_more: boolean\n} | {\n readonly kind: 'error'\n readonly error: string\n}\n\nexport function apply(ctx: Context, config: Config = {}): void {\n const scanId = config.scanId ?? 'pentest'\n const listPageSize = config.listPageSize ?? 50\n const replayTimeoutMs = config.replayTimeoutMs ?? 30_000\n const caidoTimeoutMs = config.caidoTimeoutMs ?? 60_000\n let clientPromise: Promise<CaidoClient> | undefined\n let warnedNoAllowlist = false\n\n /** Authorized targets: Config first, else the preset's scan targets. Empty = fail-open (warned once). */\n const authorizedTargets = (): string[] => {\n if (config.authorizedTargets !== undefined) return config.authorizedTargets\n const preset = ctx.get('pentestPreset') as { authorizedTargets?: Array<{ value: string }> } | undefined\n const values = preset?.authorizedTargets?.map(target => target.value) ?? []\n if (values.length === 0 && !warnedNoAllowlist) {\n warnedNoAllowlist = true\n ctx.logger.warn('pentest-proxy: no authorizedTargets configured; repeat_request target enforcement is inactive (fail-open)')\n }\n return values\n }\n\n /** Lazy client: resolves the session's Caido bootstrap on first use (strix parity). */\n const client = (signal: AbortSignal): Promise<CaidoClient> => {\n // A failed bootstrap stays failed (strix caido_handle parity: every caller\n // sees the same degraded state); the wording is stable so the model gets\n // consistent guidance instead of the raw exception.\n clientPromise ??= (async () => {\n const session = await ctx.pentestSandbox.createSession({ scanId })\n const endpoint = await session.caidoEndpoint()\n return new CaidoClient({ baseUrl: endpoint.baseUrl, token: endpoint.token })\n })().catch(error => {\n throw new Error(`Caido client not available in run context: ${String(error instanceof Error ? error.message : error)}`)\n })\n const settled = clientPromise\n if (settled === undefined) throw new Error('unreachable: client promise just assigned')\n const timeout = new Promise<never>((_resolve, reject) => {\n signal.addEventListener('abort', () => reject(new Error('caido call aborted')), { once: true })\n const timer = setTimeout(() => reject(new Error(`caido call timed out after ${String(caidoTimeoutMs)}ms`)), caidoTimeoutMs)\n void settled.then(() => clearTimeout(timer), () => clearTimeout(timer))\n })\n return Promise.race([settled, timeout])\n }\n\n if (config.requireApproval !== false) {\n void ctx.on('tools/pre-execute', async (exec, next) => {\n if (exec.name === 'repeat_request') return { kind: 'ask' as const, reason: 'pentest: replay a captured request against the target' }\n return next()\n })\n }\n\n ctx.tools.register(defineTool({\n name: 'list_requests',\n description: `List captured HTTP requests from the Caido proxy with HTTPQL filtering. HTTPQL: integer fields (resp.code, req.port, id, roundtrip) use eq/gt/gte/lt/lte/ne e.g. 'resp.code.gte:400'; text fields (req.method, req.host, req.path, req.query, req.ext, req.raw) use regex/cont/eq e.g. 'req.path.cont:\"/api/\"'; dates use gt/lt with ISO e.g. 'req.created_at.gt:\"2024-01-01T00:00:00Z\"'; combine with AND/OR; no NOT — use ne/ncont/nregex. String values MUST be quoted, integers MUST NOT. A bare quoted string searches req.raw and resp.raw. Pagination: pass page_info.end_cursor as after.`,\n parameters: {\n httpql_filter: { type: 'string', description: 'Caido HTTPQL query (optional).' },\n first: { type: 'integer', description: `Entries per page (default ${String(listPageSize)}).` },\n after: { type: 'string', description: \"Cursor from a previous response's page_info.end_cursor.\" },\n sort_by: { type: 'string', enum: ['timestamp', 'host', 'method', 'path', 'status_code', 'response_time', 'response_size', 'source'], description: 'Sort key (default timestamp).' },\n sort_order: { type: 'string', enum: ['asc', 'desc'], description: 'Sort order (default desc).' },\n scope_id: { type: 'string', description: 'Restrict to a Caido scope.' },\n },\n output: {\n schema: {\n type: 'object',\n properties: {\n success: { type: 'boolean', required: true },\n entries: { type: 'array', items: { type: 'object', properties: {}, additionalProperties: true } },\n page_info: { type: 'object', properties: {}, additionalProperties: true },\n error: { type: 'string' },\n },\n additionalProperties: false,\n },\n render: (_args, value) => {\n const result = value as { success: boolean; entries: unknown[]; error?: string }\n if (!result.success) return [{ type: 'text', text: `list_requests failed: ${result.error ?? 'unknown'}` }]\n return [{ type: 'text', text: `${String(result.entries.length)} entries (cursor pagination via page_info)` }]\n },\n },\n execute: async (args, exec) => {\n try {\n const caido = await client(exec.signal)\n const connection = await caido.listRequests({\n httpqlFilter: args.httpql_filter,\n first: args.first ?? listPageSize,\n after: args.after,\n sortBy: args.sort_by as SortBy | undefined,\n sortOrder: args.sort_order,\n scopeId: args.scope_id,\n }, exec.signal)\n return {\n success: true,\n entries: connection.entries.map(entry => ({\n cursor: entry.cursor,\n request: {\n id: entry.request.id,\n host: entry.request.host,\n port: entry.request.port,\n method: entry.request.method,\n path: entry.request.path,\n query: entry.request.query,\n is_tls: entry.request.tls,\n created_at: entry.request.createdAt,\n },\n response: entry.response === null ? null : {\n id: entry.response.id,\n status_code: entry.response.statusCode,\n length: entry.response.length,\n created_at: entry.response.createdAt,\n },\n })),\n page_info: {\n has_next_page: connection.pageInfo.hasNextPage,\n has_previous_page: connection.pageInfo.hasPreviousPage,\n start_cursor: connection.pageInfo.startCursor,\n end_cursor: connection.pageInfo.endCursor,\n },\n }\n } catch (error) {\n return { success: false, entries: [], page_info: {}, error: String(error instanceof Error ? error.message : error) }\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'view_request',\n description: `View a captured request or its response raw content, optionally regex-searched. With search_pattern: up to 20 compact hits with before/after context (hunting reflections, leaked URLs, hidden parameters). Without: full content line-paginated (page, page_size). Patterns like '/api/[a-zA-Z0-9._/-]+' (endpoints), 'https?://[^\\\\s<>\"]+' (URLs), '[?&][a-zA-Z0-9_]+=([^&\\\\s]+)' (query params).`,\n parameters: {\n request_id: { type: 'string', required: true, description: 'Request ID from list_requests.' },\n part: { type: 'string', enum: ['request', 'response'], description: 'Which raw half to view (default request).' },\n search_pattern: { type: 'string', description: 'Optional regex; switches to compact hits mode.' },\n page: { type: 'integer', description: '1-indexed page (only without search_pattern).' },\n page_size: { type: 'integer', description: 'Lines per page (default 50).' },\n },\n output: {\n schema: {\n type: 'object',\n properties: {\n kind: { type: 'string', required: true, enum: ['hits', 'page', 'error'] },\n hits: { type: 'array', items: { type: 'object', properties: {}, additionalProperties: true } },\n total_hits: { type: 'integer' },\n content: { type: 'string' },\n page: { type: 'integer' },\n page_size: { type: 'integer' },\n total_lines: { type: 'integer' },\n has_more: { type: 'boolean' },\n error: { type: 'string' },\n },\n additionalProperties: false,\n },\n render: (_args, value) => {\n const result = value as ViewRequestValue\n if (result.kind === 'error') return [{ type: 'text', text: `view_request failed: ${result.error}` }]\n if (result.kind === 'hits') return [{ type: 'text', text: `${String(result.total_hits)} regex hit(s)` }]\n return [{ type: 'text', text: `page ${String(result.page)}/${String(Math.ceil(result.total_lines / Math.max(1, result.page_size)))} of ${String(result.total_lines)} lines` }]\n },\n },\n execute: async (args, exec) => {\n try {\n const caido = await client(exec.signal)\n const stored = await caido.getRequest(args.request_id, exec.signal)\n if (stored === null) return { kind: 'error' as const, error: `Request ${args.request_id} not found` }\n const raw = args.part === 'response' ? stored.responseRaw : stored.requestRaw\n if (raw === null) return { kind: 'error' as const, error: `No raw ${args.part === 'response' ? 'response' : 'request'} for ${args.request_id}` }\n if (args.search_pattern !== undefined && args.search_pattern !== '') {\n const hits = formatSearchHits(raw, args.search_pattern)\n if (hits.error !== undefined) return { kind: 'error' as const, error: hits.error }\n return {\n kind: 'hits' as const,\n hits: hits.hits.map(hit => ({ match: hit.match, position: hit.position, before: hit.before, after: hit.after })),\n total_hits: hits.totalHits,\n }\n }\n const textPage = formatTextPage(raw, args.page ?? 1, args.page_size ?? 50)\n return {\n kind: 'page' as const,\n content: textPage.content,\n page: textPage.page,\n page_size: textPage.pageSize,\n total_lines: textPage.totalLines,\n has_more: textPage.hasMore,\n }\n } catch (error) {\n return { kind: 'error' as const, error: String(error instanceof Error ? error.message : error) }\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'repeat_request',\n description: `Repeat a captured request, optionally patching fields — the browse→capture→modify→test flow. modifications keys: url (replace), params (query additions), headers (additions), body (replace), cookies (additions). Inherits everything else from the original.`,\n parameters: {\n request_id: { type: 'string', required: true, description: 'ID of the original request (from list_requests).' },\n modifications: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Replace the URL.' },\n params: { type: 'object', properties: {}, additionalProperties: true, description: 'Query-string keys to add/update.' },\n headers: { type: 'object', properties: {}, additionalProperties: true, description: 'Headers to add/update.' },\n body: { type: 'string', description: 'Replace the body.' },\n cookies: { type: 'object', properties: {}, additionalProperties: true, description: 'Cookies to add/update.' },\n },\n additionalProperties: false,\n description: 'Patch dict overlaying the original request.',\n },\n },\n output: {\n schema: {\n type: 'object',\n properties: {\n success: { type: 'boolean', required: true },\n status: { type: 'string' },\n session_id: { type: 'string' },\n elapsed_ms: { type: 'integer' },\n response: { type: 'object', properties: {}, additionalProperties: true },\n error: { type: 'string' },\n },\n additionalProperties: false,\n },\n render: (_args, value) => {\n const result = value as { success: boolean; status?: string; error?: string; response?: { status_code?: number } | null }\n if (!result.success) return [{ type: 'text', text: `repeat_request failed: ${result.error ?? result.status ?? 'unknown'}` }]\n return [{ type: 'text', text: `replay ${result.status ?? 'DONE'}${result.response?.status_code === undefined ? '' : ` → HTTP ${String(result.response.status_code)}`}` }]\n },\n },\n execute: async (args, exec) => {\n try {\n const caido = await client(exec.signal)\n const stored = await caido.getRequest(args.request_id, exec.signal)\n if (stored === null) return { success: false, status: 'ERROR', error: `Request ${args.request_id} not found` }\n // Scope enforcement (beyond strix parity): the replay target must be\n // inside the authorized target list before anything is dispatched.\n const allowlist = authorizedTargets()\n const targetHost = resolveRepeatTargetHost(stored.host, args.modifications as Readonly<Record<string, unknown>> | undefined)\n if (!targetHostAllowed(targetHost, allowlist)) {\n return { success: false, status: 'ERROR', error: `repeat_request refused: target host '${targetHost}' is outside this scan's authorized targets` }\n }\n const replay = await caido.replayRequest(args.request_id, args.modifications, exec.signal, { dispatchTimeoutMs: replayTimeoutMs, pollIntervalMs: 500 })\n if (replay === null) return { success: false, status: 'ERROR', error: `Request ${args.request_id} not found` }\n return {\n success: replay.status === 'DONE',\n status: replay.status,\n session_id: replay.sessionId,\n elapsed_ms: replay.elapsedMs,\n response: replay.response === null ? {} : {\n status_code: replay.response.statusCode,\n length: replay.response.length,\n headers: replay.response.headers,\n body: replay.response.body,\n body_truncated: replay.response.bodyTruncated,\n },\n ...(replay.error !== undefined ? { error: replay.error } : {}),\n }\n } catch (error) {\n return { success: false, status: 'ERROR', error: String(error instanceof Error ? error.message : error) }\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'list_sitemap',\n description: `Browse Caido's hierarchical sitemap: DOMAIN → DIRECTORY → REQUEST → REQUEST_BODY/REQUEST_QUERY. Start with no parent_id for root domains (optionally scope-filtered); drill in by passing an entry's id as parent_id (depth DIRECT or ALL). Pair with view_sitemap_entry.`,\n parameters: {\n scope_id: { type: 'string', description: 'Limit roots to a Caido scope (only without parent_id).' },\n parent_id: { type: 'string', description: 'Entry ID to expand; omit for root domains.' },\n depth: { type: 'string', enum: ['DIRECT', 'ALL'], description: 'DIRECT children or the full subtree (default DIRECT).' },\n page: { type: 'integer', description: '1-indexed page (30 entries per page, strix parity).' },\n },\n output: {\n schema: {\n type: 'object',\n properties: {\n success: { type: 'boolean', required: true },\n payload: { type: 'object', properties: {}, additionalProperties: true },\n error: { type: 'string' },\n },\n additionalProperties: false,\n },\n render: (_args, value) => {\n const result = value as { success: boolean; error?: string }\n return [{ type: 'text', text: result.success ? 'sitemap payload returned' : `list_sitemap failed: ${result.error ?? 'unknown'}` }]\n },\n },\n execute: async (args, exec) => {\n try {\n const caido = await client(exec.signal)\n const payload = await caido.listSitemap({ scopeId: args.scope_id, parentId: args.parent_id, depth: args.depth }, exec.signal) as Record<string, unknown>\n return { success: true as const, payload: structuredToPlain(pageSitemapPayload(payload, args.page ?? 1)) }\n } catch (error) {\n return { success: false as const, payload: {}, error: String(error instanceof Error ? error.message : error) }\n }\n },\n }))\n\n ctx.tools.register(defineTool({\n name: 'scope_rules',\n description: \"Manage Caido scope rules: get/list/create/update/delete. Glob patterns (*, ?, [abc], [a-z], [^abc]); an EMPTY allowlist ALLOWS ALL; the denylist overrides the allowlist. Scopes feed list_requests' scope_id.\",\n parameters: {\n action: { type: 'string', required: true, enum: ['get', 'list', 'create', 'update', 'delete'], description: 'Scope action.' },\n allowlist: { type: 'array', items: { type: 'string' }, description: 'Allow glob patterns (create/update).' },\n denylist: { type: 'array', items: { type: 'string' }, description: 'Deny glob patterns; overrides the allowlist (create/update).' },\n scope_id: { type: 'string', description: 'Target scope id (get/update/delete).' },\n scope_name: { type: 'string', description: 'Scope name (create/update).' },\n },\n output: {\n schema: {\n type: 'object',\n properties: {\n success: { type: 'boolean', required: true },\n scopes: { type: 'array', items: { type: 'object', properties: {}, additionalProperties: true } },\n scope: { type: 'object', properties: {}, additionalProperties: true },\n deleted: { type: 'string' },\n message: { type: 'string' },\n error: { type: 'string' },\n },\n additionalProperties: false,\n },\n render: (_args, value) => {\n const result = value as { success: boolean; error?: string }\n return [{ type: 'text', text: result.success ? 'scope action succeeded' : `scope_rules failed: ${result.error ?? 'unknown'}` }]\n },\n },\n execute: (async (rawArgs: never, rawExec: never) => {\n const args = rawArgs as never as { action: string; allowlist?: string[]; denylist?: string[]; scope_id?: string; scope_name?: string }\n const exec = rawExec as never as ToolRunContextLike\n try {\n const caido = await client(exec.signal)\n const allowlist = args.allowlist ?? []\n const denylist = args.denylist ?? []\n switch (args.action) {\n case 'list': {\n const payload = await caido.scopeList(exec.signal) as { scopes?: unknown[] }\n return { success: true, scopes: plainScopes(payload.scopes ?? []) }\n }\n case 'get': {\n if (args.scope_id === undefined || args.scope_id === '') return { success: false, error: \"Scope_id is required for action='get'\" }\n return { success: true, scope: plainScope(await caido.scopeGet(args.scope_id, exec.signal)) }\n }\n case 'create': {\n if (args.scope_name === undefined || args.scope_name === '') return { success: false, error: \"Scope_name is required for action='create'\" }\n return { success: true, scope: plainScope(await caido.scopeCreate(args.scope_name, allowlist, denylist, exec.signal)) }\n }\n case 'update': {\n if (args.scope_id === undefined || args.scope_id === '' || args.scope_name === undefined || args.scope_name === '') {\n return { success: false, error: \"Scope_id and scope_name are required for action='update'\" }\n }\n return { success: true, scope: plainScope(await caido.scopeUpdate(args.scope_id, args.scope_name, allowlist, denylist, exec.signal)) }\n }\n case 'delete': {\n if (args.scope_id === undefined || args.scope_id === '') return { success: false, error: \"Scope_id is required for action='delete'\" }\n const payload = await caido.scopeDelete(args.scope_id, exec.signal) as { deleteScope?: { deletedId?: string } }\n return { success: true, deleted: payload.deleteScope?.deletedId ?? args.scope_id, message: `Scope ${args.scope_id} deleted` }\n }\n default:\n return { success: false, error: `Unknown action: ${String(args.action)}` }\n }\n } catch (error) {\n return { success: false, error: `scope_rules failed: ${String(error instanceof Error ? error.message : error)}` }\n }\n }) as never,\n }))\n\n ctx.tools.register(defineTool({\n name: 'view_sitemap_entry',\n description: \"Full detail for a sitemap entry plus its most recent 30 related requests. Pick entry_id from list_sitemap.\",\n parameters: {\n entry_id: { type: 'string', required: true, description: 'ID from list_sitemap (or any nested entry).' },\n },\n output: {\n schema: {\n type: 'object',\n properties: {\n success: { type: 'boolean', required: true },\n payload: { type: 'object', properties: {}, additionalProperties: true },\n error: { type: 'string' },\n },\n additionalProperties: false,\n },\n render: (_args, value) => {\n const result = value as { success: boolean; error?: string }\n return [{ type: 'text', text: result.success ? 'sitemap entry payload returned' : `view_sitemap_entry failed: ${result.error ?? 'unknown'}` }]\n },\n },\n execute: async (args, exec) => {\n try {\n const caido = await client(exec.signal)\n const payload = await caido.viewSitemapEntry(args.entry_id, exec.signal) as Record<string, unknown>\n return { success: true as const, payload: structuredToPlain(payload) }\n } catch (error) {\n return { success: false as const, payload: {}, error: String(error instanceof Error ? error.message : error) }\n }\n },\n }))\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@gpzhang2001/sharpkit-proxy",
3
+ "description": "Caido proxy client + five traffic tools (list_requests/view_request/repeat_request/list_sitemap/view_sitemap_entry) over the sandbox session's lazy bootstrap",
4
+ "version": "0.2.1",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/gpzhang2001/sharpkit.git",
11
+ "directory": "packages/tool-proxy"
12
+ },
13
+ "type": "module",
14
+ "license": "Apache-2.0",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./lib/index.d.ts",
18
+ "default": "./lib/index.js"
19
+ },
20
+ "./src/*": "./src/*",
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "lib",
25
+ "src",
26
+ "LICENSE",
27
+ "THIRD_PARTY_NOTICES.md"
28
+ ],
29
+ "dependencies": {
30
+ "@deepseek-ai/schemastery": "3.18.2",
31
+ "@gpzhang2001/sharpkit-sandbox": "^0.2.1"
32
+ },
33
+ "peerDependencies": {
34
+ "@deepseek-ai/cordis": "^4.0.2",
35
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
36
+ "@gpzhang2001/sharpkit-sandbox": "^0.1.0"
37
+ },
38
+ "devDependencies": {
39
+ "@deepseek-ai/cordis": "4.0.2",
40
+ "@deepseek-ai/dsh-tools": "0.1.2-rc.1"
41
+ },
42
+ "main": "lib/index.js",
43
+ "types": "lib/index.d.ts",
44
+ "scripts": {
45
+ "build": "cp ../../LICENSE ../../THIRD_PARTY_NOTICES.md . && tsdown && mv -f lib/index.ts lib/index.d.ts && mv -f lib/index.ts.map lib/index.d.ts.map"
46
+ }
47
+ }