{"record":{"id":"c5c8940a4be76d84","repo":"jackwener/OpenCLI","slug":"must-be-a-kimi-chat-id-or-https-www-kimi-com-cha","errorCode":null,"errorMessage":"must be a Kimi chat id or https://www.kimi.com/chat/<id> URL","messagePattern":"must be a Kimi chat id or https://www\\.kimi\\.com/chat/<id> URL","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/kimi/chat.js","lineNumber":29,"sourceCode":"    KIMI_DOMAIN,\n    KIMI_URL,\n    IS_VISIBLE_JS,\n    ensureOnKimi,\n    parseChatId,\n    clickBySvgNameScript,\n} from './_utils.js';\n\nconst CHAT_COLUMNS = ['Field', 'Value', 'Status', 'Url', 'Index', 'Title', 'ChatId', 'Role', 'Text', 'Length', 'ClipboardClicked', 'Reaction', 'WaitedSeconds', 'ReplyPreview'];\n\n// Helper: if --conv passed, navigate to that chat URL and wait briefly\n// for messages to mount. Otherwise just ensure we're on kimi.com.\nasync function maybeNavigateConv(page, convArg) {\n    if (!convArg) {\n        await ensureOnKimi(page);\n        return;\n    }\n    const id = parseChatId(convArg);\n    if (!id) throw new ArgumentError('conv', 'must be a Kimi chat id or https://www.kimi.com/chat/<id> URL');\n    // CRITICAL: Kimi's React app only triggers the messages fetch when the\n    // URL has ?chat_enter_method=history (or other valid entry methods).\n    // Plain /chat/<id> loads the conversation TITLE but leaves the message\n    // container empty (clientHeight=0). Append the query param.\n    await page.goto(`${KIMI_URL}chat/${id}?chat_enter_method=history`);\n    await page.wait(2);\n    // Poll up to 15s for .chat-content-list items to appear.\n    for (let i = 0; i < 15; i++) {\n        const ok = await page.evaluate(`(() => {\n      const list = document.querySelector('.chat-content-list') || document.querySelector('.message-list');\n      if (!list) return false;\n      // Check for actual chat-content-item rows (the new container) OR any direct children (older container)\n      return list.querySelectorAll('.chat-content-item, .segment').length > 0 || list.children.length > 0;\n    })()`);\n        if (ok) return;\n        await page.wait(1);\n    }\n}","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/kimi/chat.js#L11-L47","documentation":"maybeNavigateConv validates the `conv` argument by running it through parseChatId, which accepts either a bare Kimi chat id or a https://www.kimi.com/chat/<id> URL. If parsing fails it throws ArgumentError, since the command cannot know which conversation to open. Note the library additionally appends ?chat_enter_method=history because Kimi's React app only fetches messages for valid entry methods.","triggerScenarios":"Passing conv as a typo'd id, an empty/whitespace string, a different site's URL (e.g. chatgpt.com/chat/...), a URL missing /chat/ prefix, or a full URL with extra path segments that parseChatId cannot extract.","commonSituations":"Copying a Kimi share URL in a different format than /chat/<id>; pasting a conversation id from another AI site; shell quoting stripping characters from the id; passing a title instead of an id from a previous listing.","solutions":["Copy the id directly from the kimi history listing command output (ChatId column) instead of typing it","Use the full https://www.kimi.com/chat/<id> URL copied from the browser address bar","Trim whitespace and remove trailing slashes/query params that break parsing","Extend parseChatId if your Kimi URLs use a different path pattern"],"exampleFix":"// before\nawait kimiChat({ conv: 'kimi chat abc123' }); // ArgumentError\n// after\nconst conv = 'https://www.kimi.com/chat/abc123'; // or bare 'abc123'\nif (!parseChatId(conv)) throw new Error('bad conv: ' + conv);\nawait kimiChat({ conv });","handlingStrategy":"validation","validationCode":"function isKimiConvArg(arg) {\n  if (typeof arg !== 'string') return false;\n  if (/^[A-Za-z0-9_-]+$/.test(arg)) return true; // bare id\n  return /^https:\\/\\/www\\.kimi\\.com\\/chat\\/[A-Za-z0-9_-]+\\/?$/.test(arg);\n}\nif (!isKimiConvArg(conv)) throw new Error('conv must be a Kimi chat id or kimi.com/chat/<id> URL');","typeGuard":"function parseKimiChatIdSafe(arg) {\n  if (typeof arg !== 'string' || !arg.trim()) return null;\n  const m = arg.match(/kimi\\.com\\/chat\\/([A-Za-z0-9_-]+)/) || arg.match(/^([A-Za-z0-9_-]+)$/);\n  return m ? m[1] : null;\n}","tryCatchPattern":"try {\n  await kimiChat({ conv });\n} catch (e) {\n  if (e instanceof ArgumentError && /Kimi chat id/.test(e.message)) {\n    const fixed = conv?.match(/([A-Za-z0-9_-]{6,})/)?.[1];\n    if (fixed) return kimiChat({ conv: fixed });\n  }\n  throw e;\n}","preventionTips":["Copy ChatId from `kimi history` output rather than typing it","Strip trailing slashes and query strings from pasted URLs","Reject non-kimi.com URLs before calling the command"],"tags":["kimi","argument-validation","url-parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}