[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FADD3G9KT99J7BCA3RNJF8":3,"skill-same:01M6FADD3G9KT99J7BCA3RNJF8":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":59,"repositoryHtmlUrl":60,"repositoryHomepageUrl":61,"ownerHtmlUrl":62,"ownerBlogUrl":6,"ownerDescription":63,"updatedAt":64,"install":65,"resources":78},"01M6FADD3G9KT99J7BCA3RNJF8","exa-sdk-patterns",null,"Apply production-ready exa-js SDK patterns with type safety, singletons, and wrappers.\nUse when implementing Exa integrations, refactoring SDK usage,\nor establishing team coding standards for Exa.\nTrigger with phrases like \"exa SDK patterns\", \"exa best practices\",\n\"exa code patterns\", \"idiomatic exa\", \"exa wrapper\".","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fexa-sdk-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"exa sdk patterns","sdk","patterns","exa","read","code patterns","io","Wrapper","ready","edit","write","openclaw","coding","refactoring","team","Safety","Type Safety","coding standards","code","typescript","2026-11-10 10:12:30",false,"---\nname: exa-sdk-patterns\ndescription: |\n  Apply production-ready exa-js SDK patterns with type safety, singletons, and wrappers.\n  Use when implementing Exa integrations, refactoring SDK usage,\n  or establishing team coding standards for Exa.\n  Trigger with phrases like \"exa SDK patterns\", \"exa best practices\",\n  \"exa code patterns\", \"idiomatic exa\", \"exa wrapper\".\nallowed-tools: Read, Write, Edit\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\ncompatible-with: claude-code, codex, openclaw\ntags: [saas, exa, typescript, patterns]\n\n---\n# Exa SDK Patterns\n\n## Overview\nProduction-ready patterns for the `exa-js` SDK. Covers client singletons, typed wrappers, error handling, retry logic, and response validation for real Exa API methods.\n\n## Prerequisites\n- `exa-js` installed and `EXA_API_KEY` configured\n- TypeScript project with strict mode\n- Familiarity with async\u002Fawait and error handling\n\n## Instructions\n\n### Step 1: Client Singleton\n```typescript\n\u002F\u002F src\u002Fexa\u002Fclient.ts\nimport Exa from \"exa-js\";\n\nlet instance: Exa | null = null;\n\nexport function getExa(): Exa {\n  if (!instance) {\n    const apiKey = process.env.EXA_API_KEY;\n    if (!apiKey) {\n      throw new Error(\"EXA_API_KEY not set. Get one at https:\u002F\u002Fdashboard.exa.ai\");\n    }\n    instance = new Exa(apiKey);\n  }\n  return instance;\n}\n```\n\n### Step 2: Typed Search Wrapper\n```typescript\n\u002F\u002F src\u002Fexa\u002Fsearch.ts\nimport Exa from \"exa-js\";\nimport { getExa } from \".\u002Fclient\";\n\ninterface ExaSearchOptions {\n  type?: \"auto\" | \"neural\" | \"keyword\" | \"fast\" | \"instant\" | \"deep\" | \"deep-reasoning\";\n  numResults?: number;\n  includeDomains?: string[];\n  excludeDomains?: string[];\n  startPublishedDate?: string;\n  endPublishedDate?: string;\n  category?: \"company\" | \"research paper\" | \"news\" | \"tweet\" | \"personal site\" | \"financial report\" | \"people\";\n  includeText?: string[];\n  excludeText?: string[];\n}\n\ninterface ExaContentsOptions {\n  text?: boolean | { maxCharacters?: number; includeHtmlTags?: boolean };\n  highlights?: boolean | { maxCharacters?: number; query?: string };\n  summary?: boolean | { query?: string };\n  livecrawl?: \"always\" | \"preferred\" | \"fallback\" | \"never\";\n  livecrawlTimeout?: number;\n  subpages?: number;\n  subpageTarget?: string | string[];\n}\n\nexport async function exaSearch(query: string, opts: ExaSearchOptions = {}) {\n  const exa = getExa();\n  return exa.search(query, {\n    type: opts.type ?? \"auto\",\n    numResults: opts.numResults ?? 10,\n    ...opts,\n  });\n}\n\nexport async function exaSearchWithContents(\n  query: string,\n  searchOpts: ExaSearchOptions = {},\n  contentOpts: ExaContentsOptions = {}\n) {\n  const exa = getExa();\n  return exa.searchAndContents(query, {\n    type: searchOpts.type ?? \"auto\",\n    numResults: searchOpts.numResults ?? 10,\n    ...searchOpts,\n    ...contentOpts,\n  });\n}\n```\n\n### Step 3: Error Handling Wrapper\n```typescript\n\u002F\u002F src\u002Fexa\u002Fsafe.ts\ninterface ExaResult\u003CT> {\n  data: T | null;\n  error: ExaError | null;\n}\n\ninterface ExaError {\n  status: number;\n  message: string;\n  tag?: string;\n  requestId?: string;\n  retryable: boolean;\n}\n\nfunction classifyError(err: any): ExaError {\n  const status = err.status || err.response?.status || 500;\n  const retryable = status === 429 || status >= 500;\n  return {\n    status,\n    message: err.message || \"Unknown error\",\n    tag: err.error_tag || err.tag,\n    requestId: err.requestId || err.request_id,\n    retryable,\n  };\n}\n\nexport async function safeExaCall\u003CT>(\n  operation: () => Promise\u003CT>\n): Promise\u003CExaResult\u003CT>> {\n  try {\n    const data = await operation();\n    return { data, error: null };\n  } catch (err: any) {\n    const error = classifyError(err);\n    console.error(`[Exa Error] ${error.status}: ${error.message}`, {\n      tag: error.tag,\n      requestId: error.requestId,\n      retryable: error.retryable,\n    });\n    return { data: null, error };\n  }\n}\n\n\u002F\u002F Usage:\n\u002F\u002F const { data, error } = await safeExaCall(() =>\n\u002F\u002F   exa.searchAndContents(\"query\", { numResults: 5, text: true })\n\u002F\u002F );\n```\n\n### Step 4: Retry with Exponential Backoff\n```typescript\n\u002F\u002F src\u002Fexa\u002Fretry.ts\nexport async function withRetry\u003CT>(\n  operation: () => Promise\u003CT>,\n  config = { maxRetries: 3, baseDelayMs: 1000, maxDelayMs: 30000 }\n): Promise\u003CT> {\n  for (let attempt = 0; attempt \u003C= config.maxRetries; attempt++) {\n    try {\n      return await operation();\n    } catch (err: any) {\n      const status = err.status || err.response?.status || 0;\n\n      \u002F\u002F Only retry on rate limits (429) and server errors (5xx)\n      if (status !== 429 && (status \u003C 500 || status >= 600)) throw err;\n      if (attempt === config.maxRetries) throw err;\n\n      const delay = Math.min(\n        config.baseDelayMs * Math.pow(2, attempt) + Math.random() * 500,\n        config.maxDelayMs\n      );\n      console.log(`[Exa] Retry ${attempt + 1}\u002F${config.maxRetries} in ${delay.toFixed(0)}ms`);\n      await new Promise(r => setTimeout(r, delay));\n    }\n  }\n  throw new Error(\"Unreachable\");\n}\n\n\u002F\u002F Usage:\n\u002F\u002F const results = await withRetry(() =>\n\u002F\u002F   exa.searchAndContents(\"query\", { numResults: 5, text: true })\n\u002F\u002F );\n```\n\n### Step 5: Response Validation with Zod\n```typescript\n\u002F\u002F src\u002Fexa\u002Fvalidate.ts\nimport { z } from \"zod\";\n\nconst ExaResultSchema = z.object({\n  url: z.string().url(),\n  title: z.string().nullable(),\n  score: z.number(),\n  publishedDate: z.string().nullable().optional(),\n  text: z.string().optional(),\n  highlights: z.array(z.string()).optional(),\n  summary: z.string().optional(),\n});\n\nconst ExaSearchResponseSchema = z.object({\n  results: z.array(ExaResultSchema),\n  autopromptString: z.string().optional(),\n});\n\nexport function validateSearchResponse(response: unknown) {\n  return ExaSearchResponseSchema.parse(response);\n}\n```\n\n## Error Handling\n| Pattern | Use Case | Benefit |\n|---------|----------|---------|\n| Singleton | All API calls | Single client instance, consistent config |\n| Safe wrapper | Non-critical searches | Prevents uncaught exceptions |\n| Retry logic | Rate limits and 5xx | Automatic recovery from transient failures |\n| Zod validation | Response processing | Catches unexpected API response changes |\n| Typed options | IDE support | Autocomplete and compile-time checks |\n\n## Examples\n\n### Factory Pattern (Multi-tenant)\n```typescript\nconst clients = new Map\u003Cstring, Exa>();\n\nexport function getExaForTenant(tenantId: string): Exa {\n  if (!clients.has(tenantId)) {\n    const apiKey = getTenantApiKey(tenantId); \u002F\u002F from your config\u002Fvault\n    clients.set(tenantId, new Exa(apiKey));\n  }\n  return clients.get(tenantId)!;\n}\n```\n\n### Combined: Safe + Retry + Typed\n```typescript\nasync function resilientSearch(query: string) {\n  return safeExaCall(() =>\n    withRetry(() =>\n      exaSearchWithContents(\n        query,\n        { type: \"neural\", numResults: 5 },\n        { text: { maxCharacters: 2000 }, highlights: true }\n      )\n    )\n  );\n}\n```\n\n## Resources\n- [exa-js TypeScript SDK](https:\u002F\u002Fdocs.exa.ai\u002Fsdks\u002Ftypescript-sdk-specification)\n- [Exa Error Codes](https:\u002F\u002Fdocs.exa.ai\u002Freference\u002Ferror-codes)\n- [Zod Documentation](https:\u002F\u002Fzod.dev\u002F)\n\n## Next Steps\nApply patterns in `exa-core-workflow-a` for real-world search usage.\n\n","# Exa SDK Patterns\n\n## Overview\nProduction-ready patterns for the `exa-js` SDK. Covers client singletons, typed wrappers, error handling, retry logic, and response validation for real Exa API methods.\n\n## Prerequisites\n- `exa-js` installed and `EXA_API_KEY` configured\n- TypeScript project with strict mode\n- Familiarity with async\u002Fawait and error handling\n\n## Instructions\n\n### Step 1: Client Singleton\n```typescript\n\u002F\u002F src\u002Fexa\u002Fclient.ts\nimport Exa from \"exa-js\";\n\nlet instance: Exa | null = null;\n\nexport function getExa(): Exa {\n  if (!instance) {\n    const apiKey = process.env.EXA_API_KEY;\n    if (!apiKey) {\n      throw new Error(\"EXA_API_KEY not set. Get one at https:\u002F\u002Fdashboard.exa.ai\");\n    }\n    instance = new Exa(apiKey);\n  }\n  return instance;\n}\n```\n\n### Step 2: Typed Search Wrapper\n```typescript\n\u002F\u002F src\u002Fexa\u002Fsearch.ts\nimport Exa from \"exa-js\";\nimport { getExa } from \".\u002Fclient\";\n\ninterface ExaSearchOptions {\n  type?: \"auto\" | \"neural\" | \"keyword\" | \"fast\" | \"instant\" | \"deep\" | \"deep-reasoning\";\n  numResults?: number;\n  includeDomains?: string[];\n  excludeDomains?: string[];\n  startPublishedDate?: string;\n  endPublishedDate?: string;\n  category?: \"company\" | \"research paper\" | \"news\" | \"tweet\" | \"personal site\" | \"financial report\" | \"people\";\n  includeText?: string[];\n  excludeText?: string[];\n}\n\ninterface ExaContentsOptions {\n  text?: boolean | { maxCharacters?: number; includeHtmlTags?: boolean };\n  highlights?: boolean | { maxCharacters?: number; query?: string };\n  summary?: boolean | { query?: string };\n  livecrawl?: \"always\" | \"preferred\" | \"fallback\" | \"never\";\n  livecrawlTimeout?: number;\n  subpages?: number;\n  subpageTarget?: string | string[];\n}\n\nexport async function exaSearch(query: string, opts: ExaSearchOptions = {}) {\n  const exa = getExa();\n  return exa.search(query, {\n    type: opts.type ?? \"auto\",\n    numResults: opts.numResults ?? 10,\n    ...opts,\n  });\n}\n\nexport async function exaSearchWithContents(\n  query: string,\n  searchOpts: ExaSearchOptions = {},\n  contentOpts: ExaContentsOptions = {}\n) {\n  const exa = getExa();\n  return exa.searchAndContents(query, {\n    type: searchOpts.type ?? \"auto\",\n    numResults: searchOpts.numResults ?? 10,\n    ...searchOpts,\n    ...contentOpts,\n  });\n}\n```\n\n### Step 3: Error Handling Wrapper\n```typescript\n\u002F\u002F src\u002Fexa\u002Fsafe.ts\ninterface ExaResult\u003CT> {\n  data: T | null;\n  error: ExaError | null;\n}\n\ninterface ExaError {\n  status: number;\n  message: string;\n  tag?: string;\n  requestId?: string;\n  retryable: boolean;\n}\n\nfunction classifyError(err: any): ExaError {\n  const status = err.status || err.response?.status || 500;\n  const retryable = status === 429 || status >= 500;\n  return {\n    status,\n    message: err.message || \"Unknown error\",\n    tag: err.error_tag || err.tag,\n    requestId: err.requestId || err.request_id,\n    retryable,\n  };\n}\n\nexport async function safeExaCall\u003CT>(\n  operation: () => Promise\u003CT>\n): Promise\u003CExaResult\u003CT>> {\n  try {\n    const data = await operation();\n    return { data, error: null };\n  } catch (err: any) {\n    const error = classifyError(err);\n    console.error(`[Exa Error] ${error.status}: ${error.message}`, {\n      tag: error.tag,\n      requestId: error.requestId,\n      retryable: error.retryable,\n    });\n    return { data: null, error };\n  }\n}\n\n\u002F\u002F Usage:\n\u002F\u002F const { data, error } = await safeExaCall(() =>\n\u002F\u002F   exa.searchAndContents(\"query\", { numResults: 5, text: true })\n\u002F\u002F );\n```\n\n### Step 4: Retry with Exponential Backoff\n```typescript\n\u002F\u002F src\u002Fexa\u002Fretry.ts\nexport async function withRetry\u003CT>(\n  operation: () => Promise\u003CT>,\n  config = { maxRetries: 3, baseDelayMs: 1000, maxDelayMs: 30000 }\n): Promise\u003CT> {\n  for (let attempt = 0; attempt \u003C= config.maxRetries; attempt++) {\n    try {\n      return await operation();\n    } catch (err: any) {\n      const status = err.status || err.response?.status || 0;\n\n      \u002F\u002F Only retry on rate limits (429) and server errors (5xx)\n      if (status !== 429 && (status \u003C 500 || status >= 600)) throw err;\n      if (attempt === config.maxRetries) throw err;\n\n      const delay = Math.min(\n        config.baseDelayMs * Math.pow(2, attempt) + Math.random() * 500,\n        config.maxDelayMs\n      );\n      console.log(`[Exa] Retry ${attempt + 1}\u002F${config.maxRetries} in ${delay.toFixed(0)}ms`);\n      await new Promise(r => setTimeout(r, delay));\n    }\n  }\n  throw new Error(\"Unreachable\");\n}\n\n\u002F\u002F Usage:\n\u002F\u002F const results = await withRetry(() =>\n\u002F\u002F   exa.searchAndContents(\"query\", { numResults: 5, text: true })\n\u002F\u002F );\n```\n\n### Step 5: Response Validation with Zod\n```typescript\n\u002F\u002F src\u002Fexa\u002Fvalidate.ts\nimport { z } from \"zod\";\n\nconst ExaResultSchema = z.object({\n  url: z.string().url(),\n  title: z.string().nullable(),\n  score: z.number(),\n  publishedDate: z.string().nullable().optional(),\n  text: z.string().optional(),\n  highlights: z.array(z.string()).optional(),\n  summary: z.string().optional(),\n});\n\nconst ExaSearchResponseSchema = z.object({\n  results: z.array(ExaResultSchema),\n  autopromptString: z.string().optional(),\n});\n\nexport function validateSearchResponse(response: unknown) {\n  return ExaSearchResponseSchema.parse(response);\n}\n```\n\n## Error Handling\n| Pattern | Use Case | Benefit |\n|---------|----------|---------|\n| Singleton | All API calls | Single client instance, consistent config |\n| Safe wrapper | Non-critical searches | Prevents uncaught exceptions |\n| Retry logic | Rate limits and 5xx | Automatic recovery from transient failures |\n| Zod validation | Response processing | Catches unexpected API response changes |\n| Typed options | IDE support | Autocomplete and compile-time checks |\n\n## Examples\n\n### Factory Pattern (Multi-tenant)\n```typescript\nconst clients = new Map\u003Cstring, Exa>();\n\nexport function getExaForTenant(tenantId: string): Exa {\n  if (!clients.has(tenantId)) {\n    const apiKey = getTenantApiKey(tenantId); \u002F\u002F from your config\u002Fvault\n    clients.set(tenantId, new Exa(apiKey));\n  }\n  return clients.get(tenantId)!;\n}\n```\n\n### Combined: Safe + Retry + Typed\n```typescript\nasync function resilientSearch(query: string) {\n  return safeExaCall(() =>\n    withRetry(() =>\n      exaSearchWithContents(\n        query,\n        { type: \"neural\", numResults: 5 },\n        { text: { maxCharacters: 2000 }, highlights: true }\n      )\n    )\n  );\n}\n```\n\n## Resources\n- [exa-js TypeScript SDK](https:\u002F\u002Fdocs.exa.ai\u002Fsdks\u002Ftypescript-sdk-specification)\n- [Exa Error Codes](https:\u002F\u002Fdocs.exa.ai\u002Freference\u002Ferror-codes)\n- [Zod Documentation](https:\u002F\u002Fzod.dev\u002F)\n\n## Next Steps\nApply patterns in `exa-core-workflow-a` for real-world search usage.\n\n",{"name":5,"tags":49,"author":51,"license":15,"version":52,"description":53,"allowed-tools":54,"compatible-with":55},[50,27,43,26],"saas","Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Apply production-ready exa-js SDK patterns with type safety, singletons, and wrappers.\nUse when implementing Exa integrations, refactoring SDK usage,\nor establishing team coding standards for Exa.\nTrigger with phrases like \"exa SDK patterns\", \"exa best practices\",\n\"exa code patterns\", \"idiomatic exa\", \"exa wrapper\".\n","Read, Write, Edit","claude-code, codex, openclaw","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fexa-sdk-patterns",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":66,"prompt":76,"zipAvailable":77},[67,70,73],{"tool":68,"command":69},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill exa-sdk-patterns",{"tool":71,"command":72},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill exa-sdk-patterns",{"tool":74,"command":75},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill exa-sdk-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fjeremylongshore\u002Fclaude-code-plugins-plus-skills\u002Fexa-sdk-patterns\u002FSKILL.md",true,[],[80,94,104,112,118,125],{"skillNo":81,"name":82,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":90,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[85],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[91,92,93],"model","model hierarchy","model hierarchy skill",{"skillNo":95,"name":96,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":100,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[99],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},[101,102,103],"MCP","zoom","zoom mcp",{"skillNo":105,"name":106,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[25,110,111,102],"zoom apps sdk","apps",{"skillNo":113,"name":114,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":117,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[114],{"skillNo":119,"name":120,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":124,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[123],{"categoryNo":86,"categoryName":87,"taxonomyType":88,"taxonomyTypeDesc":89},[120],{"skillNo":126,"name":127,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":130,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[127]]