workos 0.5.4 → 0.7.0

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.
Files changed (107) hide show
  1. package/README.md +51 -15
  2. package/dist/bin.js +151 -0
  3. package/dist/bin.js.map +1 -1
  4. package/dist/cli.config.d.ts +1 -0
  5. package/dist/cli.config.js +1 -0
  6. package/dist/cli.config.js.map +1 -1
  7. package/dist/commands/doctor.d.ts +1 -0
  8. package/dist/commands/doctor.js +1 -0
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/env.d.ts +9 -0
  11. package/dist/commands/env.js +188 -0
  12. package/dist/commands/env.js.map +1 -0
  13. package/dist/commands/organization.d.ts +18 -0
  14. package/dist/commands/organization.js +142 -0
  15. package/dist/commands/organization.js.map +1 -0
  16. package/dist/commands/user.d.ts +19 -0
  17. package/dist/commands/user.js +128 -0
  18. package/dist/commands/user.js.map +1 -0
  19. package/dist/dashboard/components/CompletionView.js +5 -1
  20. package/dist/dashboard/components/CompletionView.js.map +1 -1
  21. package/dist/doctor/agent-prompt.d.ts +9 -0
  22. package/dist/doctor/agent-prompt.js +67 -0
  23. package/dist/doctor/agent-prompt.js.map +1 -0
  24. package/dist/doctor/checks/ai-analysis.d.ts +9 -0
  25. package/dist/doctor/checks/ai-analysis.js +122 -0
  26. package/dist/doctor/checks/ai-analysis.js.map +1 -0
  27. package/dist/doctor/checks/auth-patterns.d.ts +2 -0
  28. package/dist/doctor/checks/auth-patterns.js +530 -0
  29. package/dist/doctor/checks/auth-patterns.js.map +1 -0
  30. package/dist/doctor/checks/environment.js +22 -4
  31. package/dist/doctor/checks/environment.js.map +1 -1
  32. package/dist/doctor/checks/framework.js +27 -8
  33. package/dist/doctor/checks/framework.js.map +1 -1
  34. package/dist/doctor/checks/language.d.ts +6 -0
  35. package/dist/doctor/checks/language.js +104 -0
  36. package/dist/doctor/checks/language.js.map +1 -0
  37. package/dist/doctor/checks/sdk.js +113 -22
  38. package/dist/doctor/checks/sdk.js.map +1 -1
  39. package/dist/doctor/index.js +26 -3
  40. package/dist/doctor/index.js.map +1 -1
  41. package/dist/doctor/issues.js +22 -1
  42. package/dist/doctor/issues.js.map +1 -1
  43. package/dist/doctor/output.js +85 -18
  44. package/dist/doctor/output.js.map +1 -1
  45. package/dist/doctor/types.d.ts +38 -0
  46. package/dist/doctor/types.js.map +1 -1
  47. package/dist/lib/adapters/cli-adapter.js +4 -14
  48. package/dist/lib/adapters/cli-adapter.js.map +1 -1
  49. package/dist/lib/adapters/dashboard-adapter.js +3 -16
  50. package/dist/lib/adapters/dashboard-adapter.js.map +1 -1
  51. package/dist/lib/agent-interface.d.ts +12 -3
  52. package/dist/lib/agent-interface.js +56 -15
  53. package/dist/lib/agent-interface.js.map +1 -1
  54. package/dist/lib/agent-runner.js +29 -27
  55. package/dist/lib/agent-runner.js.map +1 -1
  56. package/dist/lib/api-key.d.ts +13 -0
  57. package/dist/lib/api-key.js +26 -0
  58. package/dist/lib/api-key.js.map +1 -0
  59. package/dist/lib/config-store.d.ts +27 -0
  60. package/dist/lib/config-store.js +142 -0
  61. package/dist/lib/config-store.js.map +1 -0
  62. package/dist/lib/credential-store.d.ts +4 -0
  63. package/dist/lib/credential-store.js +47 -11
  64. package/dist/lib/credential-store.js.map +1 -1
  65. package/dist/lib/credentials.d.ts +1 -1
  66. package/dist/lib/credentials.js +1 -1
  67. package/dist/lib/credentials.js.map +1 -1
  68. package/dist/lib/events.d.ts +11 -0
  69. package/dist/lib/events.js.map +1 -1
  70. package/dist/lib/run-with-core.js +23 -2
  71. package/dist/lib/run-with-core.js.map +1 -1
  72. package/dist/lib/settings.d.ts +1 -0
  73. package/dist/lib/settings.js.map +1 -1
  74. package/dist/lib/validation/build-validator.d.ts +12 -0
  75. package/dist/lib/validation/build-validator.js +35 -5
  76. package/dist/lib/validation/build-validator.js.map +1 -1
  77. package/dist/lib/validation/index.d.ts +3 -2
  78. package/dist/lib/validation/index.js +2 -1
  79. package/dist/lib/validation/index.js.map +1 -1
  80. package/dist/lib/validation/quick-checks.d.ts +19 -0
  81. package/dist/lib/validation/quick-checks.js +190 -0
  82. package/dist/lib/validation/quick-checks.js.map +1 -0
  83. package/dist/lib/validation/types.d.ts +15 -0
  84. package/dist/lib/validation/types.js.map +1 -1
  85. package/dist/lib/validation/validator.d.ts +8 -1
  86. package/dist/lib/validation/validator.js +19 -11
  87. package/dist/lib/validation/validator.js.map +1 -1
  88. package/dist/lib/workos-api.d.ts +30 -0
  89. package/dist/lib/workos-api.js +69 -0
  90. package/dist/lib/workos-api.js.map +1 -0
  91. package/dist/utils/cli-symbols.d.ts +1 -1
  92. package/dist/utils/lock-art.d.ts +4 -0
  93. package/dist/utils/lock-art.js +73 -0
  94. package/dist/utils/lock-art.js.map +1 -0
  95. package/dist/utils/package-json.d.ts +1 -0
  96. package/dist/utils/package-json.js +11 -0
  97. package/dist/utils/package-json.js.map +1 -1
  98. package/dist/utils/summary-box.d.ts +18 -0
  99. package/dist/utils/summary-box.js +148 -0
  100. package/dist/utils/summary-box.js.map +1 -0
  101. package/dist/utils/table.d.ts +5 -0
  102. package/dist/utils/table.js +18 -0
  103. package/dist/utils/table.js.map +1 -0
  104. package/dist/utils/types.d.ts +6 -0
  105. package/dist/utils/types.js.map +1 -1
  106. package/package.json +1 -1
  107. package/skills/workos-authkit-nextjs/SKILL.md +5 -5
@@ -0,0 +1,67 @@
1
+ export function buildDoctorPrompt(context) {
2
+ const { language, framework, sdk, environment, existingIssues } = context;
3
+ const projectContext = [
4
+ `- Language: ${language.name}`,
5
+ framework.name
6
+ ? `- Framework: ${framework.name} ${framework.version ?? ''}${framework.variant ? ` (${framework.variant})` : ''}`
7
+ : null,
8
+ sdk.name ? `- SDK: ${sdk.name}${sdk.version ? ` v${sdk.version}` : ''}` : '- SDK: Not installed',
9
+ `- Environment: ${environment.apiKeyType ?? 'Unknown'}`,
10
+ environment.baseUrl ? `- Base URL: ${environment.baseUrl}` : null,
11
+ ]
12
+ .filter(Boolean)
13
+ .join('\n');
14
+ const existingIssuesList = existingIssues.length > 0
15
+ ? existingIssues.map((i) => `- [${i.severity}] ${i.code}: ${i.message}`).join('\n')
16
+ : 'None detected.';
17
+ return `You are a WorkOS integration analyst. Analyze this project and identify potential issues with the WorkOS integration.
18
+
19
+ ## Project Context
20
+ ${projectContext}
21
+
22
+ ## WorkOS SDK Knowledge (IMPORTANT — do not contradict this)
23
+ - \`@workos-inc/node\` and \`@workos/node\` work in ANY JavaScript runtime (Node.js, browsers, React Native, Expo, Cloudflare Workers, Deno, Bun). Despite the name, they have NO Node.js-specific API dependencies (no \`node:crypto\`, no \`node:fs\`, etc.).
24
+ - \`@workos-inc/node\` supports PKCE (Proof Key for Code Exchange) for client-side authentication flows. Using it in Expo, React Native, or browser SPAs is the CORRECT and recommended approach.
25
+ - AuthKit SDKs (\`@workos/authkit-nextjs\`, \`@workos/authkit-react-router\`, \`@workos/authkit-react\`, \`@workos/authkit-tanstack-react-start\`, etc.) are framework-specific wrappers around the core SDK that add session management, middleware, and auth providers.
26
+ - Legacy scope \`@workos-inc/*\` and new scope \`@workos/*\` are the same SDKs — the org is migrating package names.
27
+ - For non-JS languages: \`workos-python\`, \`workos-ruby\`, \`workos-go\`, \`workos-java\`, \`workos-php\`, \`WorkOS.net\` are server-side SDKs.
28
+ - Do NOT flag \`@workos-inc/node\` as incompatible with client-side, mobile, or non-Node environments. It is designed for universal JavaScript use.
29
+
30
+ ## Already Detected Issues
31
+ ${existingIssuesList}
32
+
33
+ ## Your Task
34
+ 1. Analyze the project's WorkOS integration based on the context above
35
+ 2. Check for framework-specific anti-patterns
36
+ 3. Verify the integration follows WorkOS best practices
37
+ 4. Identify potential runtime issues
38
+
39
+ ## Output Format
40
+ Return your analysis as a JSON object wrapped in a markdown code block:
41
+ \`\`\`json
42
+ {
43
+ "findings": [
44
+ {
45
+ "severity": "error | warning | info",
46
+ "title": "Short description",
47
+ "detail": "What's wrong and why it matters",
48
+ "remediation": "How to fix it",
49
+ "filePath": "path/to/relevant/file"
50
+ }
51
+ ],
52
+ "summary": "One paragraph summary of the integration health"
53
+ }
54
+ \`\`\`
55
+
56
+ ## Rules
57
+ - Do NOT repeat issues already detected (listed above)
58
+ - Do NOT contradict the SDK Knowledge section above. If you think an SDK is incompatible with a runtime, re-read that section first.
59
+ - Only report issues you are confident about. Do NOT speculate about potential problems that might exist — report problems that DO exist based on the project context.
60
+ - Focus on framework-specific patterns the static checks can't catch
61
+ - Be specific — reference actual file paths and line patterns
62
+ - Keep findings actionable — every finding must have a remediation
63
+ - Limit to 3-5 most important findings. Fewer high-quality findings beat many speculative ones.
64
+ - If the integration looks good, return an empty findings array and say so in the summary. Do NOT invent problems.
65
+ - The filePath field is optional — only include it if you found a specific file`;
66
+ }
67
+ //# sourceMappingURL=agent-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-prompt.js","sourceRoot":"","sources":["../../src/doctor/agent-prompt.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,iBAAiB,CAAC,OAAwB;IACxD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAE1E,MAAM,cAAc,GAAG;QACrB,eAAe,QAAQ,CAAC,IAAI,EAAE;QAC9B,SAAS,CAAC,IAAI;YACZ,CAAC,CAAC,gBAAgB,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,OAAO,IAAI,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAClH,CAAC,CAAC,IAAI;QACR,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;QAChG,kBAAkB,WAAW,CAAC,UAAU,IAAI,SAAS,EAAE;QACvD,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI;KAClE;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,kBAAkB,GACtB,cAAc,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACnF,CAAC,CAAC,gBAAgB,CAAC;IAEvB,OAAO;;;EAGP,cAAc;;;;;;;;;;;EAWd,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFAkC4D,CAAC;AACjF,CAAC","sourcesContent":["import type { LanguageInfo, FrameworkInfo, SdkInfo, EnvironmentInfo, Issue } from './types.js';\n\nexport interface AnalysisContext {\n language: LanguageInfo;\n framework: FrameworkInfo;\n sdk: SdkInfo;\n environment: EnvironmentInfo;\n existingIssues: Issue[];\n}\n\nexport function buildDoctorPrompt(context: AnalysisContext): string {\n const { language, framework, sdk, environment, existingIssues } = context;\n\n const projectContext = [\n `- Language: ${language.name}`,\n framework.name\n ? `- Framework: ${framework.name} ${framework.version ?? ''}${framework.variant ? ` (${framework.variant})` : ''}`\n : null,\n sdk.name ? `- SDK: ${sdk.name}${sdk.version ? ` v${sdk.version}` : ''}` : '- SDK: Not installed',\n `- Environment: ${environment.apiKeyType ?? 'Unknown'}`,\n environment.baseUrl ? `- Base URL: ${environment.baseUrl}` : null,\n ]\n .filter(Boolean)\n .join('\\n');\n\n const existingIssuesList =\n existingIssues.length > 0\n ? existingIssues.map((i) => `- [${i.severity}] ${i.code}: ${i.message}`).join('\\n')\n : 'None detected.';\n\n return `You are a WorkOS integration analyst. Analyze this project and identify potential issues with the WorkOS integration.\n\n## Project Context\n${projectContext}\n\n## WorkOS SDK Knowledge (IMPORTANT — do not contradict this)\n- \\`@workos-inc/node\\` and \\`@workos/node\\` work in ANY JavaScript runtime (Node.js, browsers, React Native, Expo, Cloudflare Workers, Deno, Bun). Despite the name, they have NO Node.js-specific API dependencies (no \\`node:crypto\\`, no \\`node:fs\\`, etc.).\n- \\`@workos-inc/node\\` supports PKCE (Proof Key for Code Exchange) for client-side authentication flows. Using it in Expo, React Native, or browser SPAs is the CORRECT and recommended approach.\n- AuthKit SDKs (\\`@workos/authkit-nextjs\\`, \\`@workos/authkit-react-router\\`, \\`@workos/authkit-react\\`, \\`@workos/authkit-tanstack-react-start\\`, etc.) are framework-specific wrappers around the core SDK that add session management, middleware, and auth providers.\n- Legacy scope \\`@workos-inc/*\\` and new scope \\`@workos/*\\` are the same SDKs — the org is migrating package names.\n- For non-JS languages: \\`workos-python\\`, \\`workos-ruby\\`, \\`workos-go\\`, \\`workos-java\\`, \\`workos-php\\`, \\`WorkOS.net\\` are server-side SDKs.\n- Do NOT flag \\`@workos-inc/node\\` as incompatible with client-side, mobile, or non-Node environments. It is designed for universal JavaScript use.\n\n## Already Detected Issues\n${existingIssuesList}\n\n## Your Task\n1. Analyze the project's WorkOS integration based on the context above\n2. Check for framework-specific anti-patterns\n3. Verify the integration follows WorkOS best practices\n4. Identify potential runtime issues\n\n## Output Format\nReturn your analysis as a JSON object wrapped in a markdown code block:\n\\`\\`\\`json\n{\n \"findings\": [\n {\n \"severity\": \"error | warning | info\",\n \"title\": \"Short description\",\n \"detail\": \"What's wrong and why it matters\",\n \"remediation\": \"How to fix it\",\n \"filePath\": \"path/to/relevant/file\"\n }\n ],\n \"summary\": \"One paragraph summary of the integration health\"\n}\n\\`\\`\\`\n\n## Rules\n- Do NOT repeat issues already detected (listed above)\n- Do NOT contradict the SDK Knowledge section above. If you think an SDK is incompatible with a runtime, re-read that section first.\n- Only report issues you are confident about. Do NOT speculate about potential problems that might exist — report problems that DO exist based on the project context.\n- Focus on framework-specific patterns the static checks can't catch\n- Be specific — reference actual file paths and line patterns\n- Keep findings actionable — every finding must have a remediation\n- Limit to 3-5 most important findings. Fewer high-quality findings beat many speculative ones.\n- If the integration looks good, return an empty findings array and say so in the summary. Do NOT invent problems.\n- The filePath field is optional — only include it if you found a specific file`;\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { type AnalysisContext } from '../agent-prompt.js';
2
+ import type { AiAnalysis, AiFinding } from '../types.js';
3
+ export declare function parseAiResponse(text: string): {
4
+ findings: AiFinding[];
5
+ summary: string;
6
+ };
7
+ export declare function checkAiAnalysis(context: AnalysisContext, options: {
8
+ skipAi?: boolean;
9
+ }): Promise<AiAnalysis>;
@@ -0,0 +1,122 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { getLlmGatewayUrl, getAuthkitDomain, getCliAuthClientId, getConfig } from '../../lib/settings.js';
3
+ import { getCredentials, isTokenExpired, updateTokens, diagnoseCredentials } from '../../lib/credentials.js';
4
+ import { refreshAccessToken } from '../../lib/token-refresh-client.js';
5
+ import { buildDoctorPrompt } from '../agent-prompt.js';
6
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
7
+ function startSpinner(message) {
8
+ let i = 0;
9
+ const interval = setInterval(() => {
10
+ process.stderr.write(`\r ${SPINNER_FRAMES[i++ % SPINNER_FRAMES.length]} ${message}`);
11
+ }, 80);
12
+ return {
13
+ stop: () => {
14
+ clearInterval(interval);
15
+ process.stderr.write(`\r${' '.repeat(message.length + 6)}\r`);
16
+ },
17
+ };
18
+ }
19
+ export function parseAiResponse(text) {
20
+ const codeBlockMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
21
+ const jsonStr = codeBlockMatch ? codeBlockMatch[1] : text;
22
+ try {
23
+ const parsed = JSON.parse(jsonStr.trim());
24
+ const findings = Array.isArray(parsed.findings)
25
+ ? parsed.findings.map((f) => ({
26
+ severity: (['error', 'warning', 'info'].includes(f.severity) ? f.severity : 'info'),
27
+ title: String(f.title ?? ''),
28
+ detail: String(f.detail ?? ''),
29
+ remediation: String(f.remediation ?? ''),
30
+ filePath: f.filePath ? String(f.filePath) : undefined,
31
+ }))
32
+ : [];
33
+ return { findings, summary: String(parsed.summary ?? '') };
34
+ }
35
+ catch {
36
+ const jsonMatch = text.match(/\{[\s\S]*"findings"[\s\S]*\}/);
37
+ if (jsonMatch) {
38
+ try {
39
+ const parsed = JSON.parse(jsonMatch[0]);
40
+ return {
41
+ findings: Array.isArray(parsed.findings) ? parsed.findings : [],
42
+ summary: String(parsed.summary ?? ''),
43
+ };
44
+ }
45
+ catch {
46
+ // give up
47
+ }
48
+ }
49
+ return { findings: [], summary: text.slice(0, 500) };
50
+ }
51
+ }
52
+ async function callModel(prompt, model) {
53
+ let creds = getCredentials();
54
+ if (!creds)
55
+ throw new Error('Not authenticated');
56
+ if (isTokenExpired(creds)) {
57
+ if (!creds.refreshToken)
58
+ throw new Error('Session expired — run `workos login` to re-authenticate');
59
+ const result = await refreshAccessToken(getAuthkitDomain(), getCliAuthClientId());
60
+ if (!result.success || !result.accessToken || !result.expiresAt) {
61
+ throw new Error('Session expired — run `workos login` to re-authenticate');
62
+ }
63
+ updateTokens(result.accessToken, result.expiresAt, result.refreshToken);
64
+ creds = getCredentials();
65
+ }
66
+ const client = new Anthropic({
67
+ baseURL: getLlmGatewayUrl(),
68
+ apiKey: 'gateway',
69
+ defaultHeaders: { Authorization: `Bearer ${creds.accessToken}` },
70
+ });
71
+ const response = await client.messages.create({
72
+ model,
73
+ max_tokens: 2048,
74
+ messages: [{ role: 'user', content: prompt }],
75
+ });
76
+ const text = response.content[0];
77
+ if (text.type === 'text')
78
+ return text.text;
79
+ throw new Error('Unexpected response format');
80
+ }
81
+ export async function checkAiAnalysis(context, options) {
82
+ const model = getConfig().doctorModel;
83
+ const skippedResult = (reason) => ({
84
+ findings: [],
85
+ summary: '',
86
+ model,
87
+ durationMs: 0,
88
+ skipped: true,
89
+ skipReason: reason,
90
+ });
91
+ if (options.skipAi) {
92
+ return skippedResult('Skipped (--skip-ai flag)');
93
+ }
94
+ const creds = getCredentials();
95
+ if (!creds) {
96
+ const diag = diagnoseCredentials();
97
+ process.stderr.write('\n [credential-debug]\n');
98
+ for (const line of diag) {
99
+ process.stderr.write(` ${line}\n`);
100
+ }
101
+ process.stderr.write('\n');
102
+ return skippedResult('Not authenticated — run `workos login` for AI-powered analysis');
103
+ }
104
+ const startTime = Date.now();
105
+ const spinner = startSpinner('Analyzing project with AI...');
106
+ try {
107
+ const prompt = buildDoctorPrompt(context);
108
+ const responseText = await callModel(prompt, model);
109
+ const durationMs = Date.now() - startTime;
110
+ const { findings, summary } = parseAiResponse(responseText);
111
+ return { findings, summary, model, durationMs };
112
+ }
113
+ catch (error) {
114
+ const durationMs = Date.now() - startTime;
115
+ const errMsg = error instanceof Error ? error.message : 'Unknown error';
116
+ return { ...skippedResult(`Analysis failed: ${errMsg}`), durationMs };
117
+ }
118
+ finally {
119
+ spinner.stop();
120
+ }
121
+ }
122
+ //# sourceMappingURL=ai-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-analysis.js","sourceRoot":"","sources":["../../../src/doctor/checks/ai-analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import Anthropic from '@anthropic-ai/sdk';\nimport { getLlmGatewayUrl, getAuthkitDomain, getCliAuthClientId, getConfig } from '../../lib/settings.js';\nimport { getCredentials, isTokenExpired, updateTokens, diagnoseCredentials } from '../../lib/credentials.js';\nimport { refreshAccessToken } from '../../lib/token-refresh-client.js';\nimport { buildDoctorPrompt, type AnalysisContext } from '../agent-prompt.js';\nimport type { AiAnalysis, AiFinding } from '../types.js';\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nfunction startSpinner(message: string): { stop: () => void } {\n let i = 0;\n const interval = setInterval(() => {\n process.stderr.write(`\\r ${SPINNER_FRAMES[i++ % SPINNER_FRAMES.length]} ${message}`);\n }, 80);\n return {\n stop: () => {\n clearInterval(interval);\n process.stderr.write(`\\r${' '.repeat(message.length + 6)}\\r`);\n },\n };\n}\n\nexport function parseAiResponse(text: string): { findings: AiFinding[]; summary: string } {\n const codeBlockMatch = text.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?\\s*```/);\n const jsonStr = codeBlockMatch ? codeBlockMatch[1] : text;\n\n try {\n const parsed = JSON.parse(jsonStr.trim());\n const findings = Array.isArray(parsed.findings)\n ? parsed.findings.map((f: Record<string, unknown>) => ({\n severity: (['error', 'warning', 'info'].includes(f.severity as string) ? f.severity : 'info') as\n | 'error'\n | 'warning'\n | 'info',\n title: String(f.title ?? ''),\n detail: String(f.detail ?? ''),\n remediation: String(f.remediation ?? ''),\n filePath: f.filePath ? String(f.filePath) : undefined,\n }))\n : [];\n return { findings, summary: String(parsed.summary ?? '') };\n } catch {\n const jsonMatch = text.match(/\\{[\\s\\S]*\"findings\"[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[0]);\n return {\n findings: Array.isArray(parsed.findings) ? parsed.findings : [],\n summary: String(parsed.summary ?? ''),\n };\n } catch {\n // give up\n }\n }\n return { findings: [], summary: text.slice(0, 500) };\n }\n}\n\nasync function callModel(prompt: string, model: string): Promise<string> {\n let creds = getCredentials();\n if (!creds) throw new Error('Not authenticated');\n\n if (isTokenExpired(creds)) {\n if (!creds.refreshToken) throw new Error('Session expired — run `workos login` to re-authenticate');\n const result = await refreshAccessToken(getAuthkitDomain(), getCliAuthClientId());\n if (!result.success || !result.accessToken || !result.expiresAt) {\n throw new Error('Session expired — run `workos login` to re-authenticate');\n }\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n creds = getCredentials()!;\n }\n\n const client = new Anthropic({\n baseURL: getLlmGatewayUrl(),\n apiKey: 'gateway',\n defaultHeaders: { Authorization: `Bearer ${creds.accessToken}` },\n });\n\n const response = await client.messages.create({\n model,\n max_tokens: 2048,\n messages: [{ role: 'user', content: prompt }],\n });\n\n const text = response.content[0];\n if (text.type === 'text') return text.text;\n throw new Error('Unexpected response format');\n}\n\nexport async function checkAiAnalysis(context: AnalysisContext, options: { skipAi?: boolean }): Promise<AiAnalysis> {\n const model = getConfig().doctorModel;\n\n const skippedResult = (reason: string): AiAnalysis => ({\n findings: [],\n summary: '',\n model,\n durationMs: 0,\n skipped: true,\n skipReason: reason,\n });\n\n if (options.skipAi) {\n return skippedResult('Skipped (--skip-ai flag)');\n }\n\n const creds = getCredentials();\n if (!creds) {\n const diag = diagnoseCredentials();\n process.stderr.write('\\n [credential-debug]\\n');\n for (const line of diag) {\n process.stderr.write(` ${line}\\n`);\n }\n process.stderr.write('\\n');\n return skippedResult('Not authenticated — run `workos login` for AI-powered analysis');\n }\n\n const startTime = Date.now();\n const spinner = startSpinner('Analyzing project with AI...');\n\n try {\n const prompt = buildDoctorPrompt(context);\n const responseText = await callModel(prompt, model);\n const durationMs = Date.now() - startTime;\n const { findings, summary } = parseAiResponse(responseText);\n return { findings, summary, model, durationMs };\n } catch (error) {\n const durationMs = Date.now() - startTime;\n const errMsg = error instanceof Error ? error.message : 'Unknown error';\n return { ...skippedResult(`Analysis failed: ${errMsg}`), durationMs };\n } finally {\n spinner.stop();\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { AuthPatternInfo, FrameworkInfo, EnvironmentInfo, SdkInfo, DoctorOptions } from '../types.js';
2
+ export declare function checkAuthPatterns(options: DoctorOptions, framework: FrameworkInfo, environment: EnvironmentInfo, sdk: SdkInfo): Promise<AuthPatternInfo>;