codeloop-mcp-server 0.1.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 (101) hide show
  1. package/dist/auth/api_key.d.ts +6 -0
  2. package/dist/auth/api_key.d.ts.map +1 -0
  3. package/dist/auth/api_key.js +87 -0
  4. package/dist/auth/api_key.js.map +1 -0
  5. package/dist/auth/usage_tracker.d.ts +7 -0
  6. package/dist/auth/usage_tracker.d.ts.map +1 -0
  7. package/dist/auth/usage_tracker.js +71 -0
  8. package/dist/auth/usage_tracker.js.map +1 -0
  9. package/dist/config.d.ts +4 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +41 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/diagnosis/vision_reviewer.d.ts +27 -0
  14. package/dist/diagnosis/vision_reviewer.d.ts.map +1 -0
  15. package/dist/diagnosis/vision_reviewer.js +345 -0
  16. package/dist/diagnosis/vision_reviewer.js.map +1 -0
  17. package/dist/evidence/artifacts.d.ts +12 -0
  18. package/dist/evidence/artifacts.d.ts.map +1 -0
  19. package/dist/evidence/artifacts.js +60 -0
  20. package/dist/evidence/artifacts.js.map +1 -0
  21. package/dist/evidence/screenshot_diff.d.ts +30 -0
  22. package/dist/evidence/screenshot_diff.d.ts.map +1 -0
  23. package/dist/evidence/screenshot_diff.js +144 -0
  24. package/dist/evidence/screenshot_diff.js.map +1 -0
  25. package/dist/index.d.ts +3 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +276 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/recommendations/knowledge_base.d.ts +21 -0
  30. package/dist/recommendations/knowledge_base.d.ts.map +1 -0
  31. package/dist/recommendations/knowledge_base.js +839 -0
  32. package/dist/recommendations/knowledge_base.js.map +1 -0
  33. package/dist/recommendations/selector.d.ts +3 -0
  34. package/dist/recommendations/selector.d.ts.map +1 -0
  35. package/dist/recommendations/selector.js +305 -0
  36. package/dist/recommendations/selector.js.map +1 -0
  37. package/dist/runners/base.d.ts +21 -0
  38. package/dist/runners/base.d.ts.map +1 -0
  39. package/dist/runners/base.js +70 -0
  40. package/dist/runners/base.js.map +1 -0
  41. package/dist/runners/flutter.d.ts +4 -0
  42. package/dist/runners/flutter.d.ts.map +1 -0
  43. package/dist/runners/flutter.js +72 -0
  44. package/dist/runners/flutter.js.map +1 -0
  45. package/dist/runners/generic.d.ts +3 -0
  46. package/dist/runners/generic.d.ts.map +1 -0
  47. package/dist/runners/generic.js +65 -0
  48. package/dist/runners/generic.js.map +1 -0
  49. package/dist/runners/maestro.d.ts +12 -0
  50. package/dist/runners/maestro.d.ts.map +1 -0
  51. package/dist/runners/maestro.js +133 -0
  52. package/dist/runners/maestro.js.map +1 -0
  53. package/dist/runners/playwright.d.ts +3 -0
  54. package/dist/runners/playwright.d.ts.map +1 -0
  55. package/dist/runners/playwright.js +76 -0
  56. package/dist/runners/playwright.js.map +1 -0
  57. package/dist/state/section_registry.d.ts +27 -0
  58. package/dist/state/section_registry.d.ts.map +1 -0
  59. package/dist/state/section_registry.js +219 -0
  60. package/dist/state/section_registry.js.map +1 -0
  61. package/dist/tools/design_compare.d.ts +4 -0
  62. package/dist/tools/design_compare.d.ts.map +1 -0
  63. package/dist/tools/design_compare.js +73 -0
  64. package/dist/tools/design_compare.js.map +1 -0
  65. package/dist/tools/diagnose.d.ts +3 -0
  66. package/dist/tools/diagnose.d.ts.map +1 -0
  67. package/dist/tools/diagnose.js +236 -0
  68. package/dist/tools/diagnose.js.map +1 -0
  69. package/dist/tools/gate_check.d.ts +3 -0
  70. package/dist/tools/gate_check.d.ts.map +1 -0
  71. package/dist/tools/gate_check.js +201 -0
  72. package/dist/tools/gate_check.js.map +1 -0
  73. package/dist/tools/integration_check.d.ts +13 -0
  74. package/dist/tools/integration_check.d.ts.map +1 -0
  75. package/dist/tools/integration_check.js +70 -0
  76. package/dist/tools/integration_check.js.map +1 -0
  77. package/dist/tools/release_readiness.d.ts +3 -0
  78. package/dist/tools/release_readiness.d.ts.map +1 -0
  79. package/dist/tools/release_readiness.js +153 -0
  80. package/dist/tools/release_readiness.js.map +1 -0
  81. package/dist/tools/replan.d.ts +12 -0
  82. package/dist/tools/replan.d.ts.map +1 -0
  83. package/dist/tools/replan.js +118 -0
  84. package/dist/tools/replan.js.map +1 -0
  85. package/dist/tools/section_status.d.ts +24 -0
  86. package/dist/tools/section_status.d.ts.map +1 -0
  87. package/dist/tools/section_status.js +61 -0
  88. package/dist/tools/section_status.js.map +1 -0
  89. package/dist/tools/update_baseline.d.ts +11 -0
  90. package/dist/tools/update_baseline.d.ts.map +1 -0
  91. package/dist/tools/update_baseline.js +19 -0
  92. package/dist/tools/update_baseline.js.map +1 -0
  93. package/dist/tools/verify.d.ts +4 -0
  94. package/dist/tools/verify.d.ts.map +1 -0
  95. package/dist/tools/verify.js +136 -0
  96. package/dist/tools/verify.js.map +1 -0
  97. package/dist/tools/visual_review.d.ts +4 -0
  98. package/dist/tools/visual_review.d.ts.map +1 -0
  99. package/dist/tools/visual_review.js +142 -0
  100. package/dist/tools/visual_review.js.map +1 -0
  101. package/package.json +44 -0
@@ -0,0 +1,6 @@
1
+ import type { ApiKeyValidation, ActivationResponse } from "@codelooptech/shared";
2
+ export declare function validateApiKey(apiKey: string | undefined): Promise<ApiKeyValidation | ActivationResponse>;
3
+ export declare function isActivationRequired(result: ApiKeyValidation | ActivationResponse): result is ActivationResponse;
4
+ /** Clears the validation cache (for testing). */
5
+ export declare function clearValidationCache(): void;
6
+ //# sourceMappingURL=api_key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api_key.d.ts","sourceRoot":"","sources":["../../src/auth/api_key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AA0CjF,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,OAAO,CAAC,gBAAgB,GAAG,kBAAkB,CAAC,CAwDhD;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,GAAG,kBAAkB,GAC5C,MAAM,IAAI,kBAAkB,CAE9B;AAED,iDAAiD;AACjD,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -0,0 +1,87 @@
1
+ import { BACKEND_URL, API_KEY_PREFIX_TEST, API_KEY_CACHE_TTL_MS, SIGNUP_URL, DOCS_URL, } from "@codelooptech/shared";
2
+ const cache = new Map();
3
+ function makeActivationResponse() {
4
+ return {
5
+ status: "activation_required",
6
+ message: "CodeLoop requires an API key. Run `npx codeloop init` in your project to sign up and configure automatically, or visit " +
7
+ SIGNUP_URL +
8
+ " to get your key.",
9
+ signup_url: SIGNUP_URL,
10
+ docs_url: DOCS_URL,
11
+ free_trial: true,
12
+ trial_details: "14-day free trial with full access, no credit card required",
13
+ };
14
+ }
15
+ function makeTestKeyValidation() {
16
+ return {
17
+ valid: true,
18
+ status: "active",
19
+ plan: "trial",
20
+ usage: {
21
+ verification_runs: { used: 0, limit: 999 },
22
+ visual_reviews: { used: 0, limit: 999 },
23
+ design_comparisons: { used: 0, limit: 999 },
24
+ recommendations: { used: 0, limit: 999 },
25
+ },
26
+ expires_at: null,
27
+ message: "Local development mode (test key)",
28
+ };
29
+ }
30
+ export async function validateApiKey(apiKey) {
31
+ if (!apiKey || apiKey.trim() === "") {
32
+ return makeActivationResponse();
33
+ }
34
+ // Local dev mode: test keys bypass backend validation entirely
35
+ if (apiKey.startsWith(API_KEY_PREFIX_TEST)) {
36
+ return makeTestKeyValidation();
37
+ }
38
+ // Check cache
39
+ const cached = cache.get(apiKey);
40
+ if (cached && Date.now() - cached.timestamp < API_KEY_CACHE_TTL_MS) {
41
+ return cached.result;
42
+ }
43
+ // Call backend
44
+ try {
45
+ const response = await fetch(`${BACKEND_URL}/v1/auth/validate`, {
46
+ method: "POST",
47
+ headers: {
48
+ "Content-Type": "application/json",
49
+ Authorization: `Bearer ${apiKey}`,
50
+ },
51
+ body: JSON.stringify({ api_key: apiKey }),
52
+ });
53
+ const result = await response.json();
54
+ if (result.valid) {
55
+ cache.set(apiKey, { result, timestamp: Date.now() });
56
+ }
57
+ return result;
58
+ }
59
+ catch {
60
+ // Backend unreachable — use cached result if available
61
+ if (cached) {
62
+ return cached.result;
63
+ }
64
+ // No cache, no backend — allow with warning (don't block local work)
65
+ return {
66
+ valid: true,
67
+ status: "active",
68
+ plan: "trial",
69
+ usage: {
70
+ verification_runs: { used: 0, limit: 999 },
71
+ visual_reviews: { used: 0, limit: 999 },
72
+ design_comparisons: { used: 0, limit: 999 },
73
+ recommendations: { used: 0, limit: 999 },
74
+ },
75
+ expires_at: null,
76
+ message: "Warning: Could not reach CodeLoop backend. Running in offline mode.",
77
+ };
78
+ }
79
+ }
80
+ export function isActivationRequired(result) {
81
+ return "signup_url" in result;
82
+ }
83
+ /** Clears the validation cache (for testing). */
84
+ export function clearValidationCache() {
85
+ cache.clear();
86
+ }
87
+ //# sourceMappingURL=api_key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api_key.js","sourceRoot":"","sources":["../../src/auth/api_key.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,QAAQ,GACT,MAAM,sBAAsB,CAAC;AAE9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA2D,CAAC;AAEjF,SAAS,sBAAsB;IAC7B,OAAO;QACL,MAAM,EAAE,qBAAqB;QAC7B,OAAO,EACL,yHAAyH;YACzH,UAAU;YACV,mBAAmB;QACrB,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,QAAQ;QAClB,UAAU,EAAE,IAAI;QAChB,aAAa,EACX,6DAA6D;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO;QACL,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;YAC1C,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;YACvC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;YAC3C,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;SACzC;QACD,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,mCAAmC;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAA0B;IAE1B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACpC,OAAO,sBAAsB,EAAE,CAAC;IAClC,CAAC;IAED,+DAA+D;IAC/D,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC3C,OAAO,qBAAqB,EAAE,CAAC;IACjC,CAAC;IAED,cAAc;IACd,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,oBAAoB,EAAE,CAAC;QACnE,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,eAAe;IACf,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,mBAAmB,EAAE;YAC9D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAC1C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAqB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEvD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;QACvD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAED,qEAAqE;QACrE,OAAO;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC1C,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBACvC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC3C,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;aACzC;YACD,UAAU,EAAE,IAAI;YAChB,OAAO,EACL,qEAAqE;SACxE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAA6C;IAE7C,OAAO,YAAY,IAAI,MAAM,CAAC;AAChC,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,oBAAoB;IAClC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type UsageEvent = "verification_run" | "visual_review" | "design_comparison" | "recommendation" | "release_readiness";
2
+ export declare function trackUsage(apiKey: string, event: UsageEvent, count?: number): Promise<void>;
3
+ export declare function flushOfflineQueue(): Promise<number>;
4
+ export declare function getOfflineQueueSize(): number;
5
+ /** Clears the offline queue (for testing). */
6
+ export declare function clearOfflineQueue(): void;
7
+ //# sourceMappingURL=usage_tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage_tracker.d.ts","sourceRoot":"","sources":["../../src/auth/usage_tracker.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAClB,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,mBAAmB,CAAC;AAYxB,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CA6BzD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,71 @@
1
+ import { BACKEND_URL, API_KEY_PREFIX_TEST } from "@codelooptech/shared";
2
+ const offlineQueue = [];
3
+ export async function trackUsage(apiKey, event, count = 1) {
4
+ // Test keys skip tracking entirely
5
+ if (apiKey.startsWith(API_KEY_PREFIX_TEST)) {
6
+ return;
7
+ }
8
+ const idempotencyKey = `${apiKey}_${event}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
9
+ try {
10
+ await fetch(`${BACKEND_URL}/v1/usage/track`, {
11
+ method: "POST",
12
+ headers: {
13
+ "Content-Type": "application/json",
14
+ Authorization: `Bearer ${apiKey}`,
15
+ },
16
+ body: JSON.stringify({
17
+ event,
18
+ count,
19
+ idempotency_key: idempotencyKey,
20
+ }),
21
+ });
22
+ }
23
+ catch {
24
+ // Usage tracking failure must not block tool execution.
25
+ // Queue event locally for retry on next successful connection.
26
+ offlineQueue.push({
27
+ apiKey,
28
+ event,
29
+ count,
30
+ idempotencyKey,
31
+ timestamp: Date.now(),
32
+ });
33
+ }
34
+ }
35
+ export async function flushOfflineQueue() {
36
+ if (offlineQueue.length === 0)
37
+ return 0;
38
+ let flushed = 0;
39
+ const toRetry = [...offlineQueue];
40
+ offlineQueue.length = 0;
41
+ for (const entry of toRetry) {
42
+ try {
43
+ await fetch(`${BACKEND_URL}/v1/usage/track`, {
44
+ method: "POST",
45
+ headers: {
46
+ "Content-Type": "application/json",
47
+ Authorization: `Bearer ${entry.apiKey}`,
48
+ },
49
+ body: JSON.stringify({
50
+ event: entry.event,
51
+ count: entry.count,
52
+ idempotency_key: entry.idempotencyKey,
53
+ }),
54
+ });
55
+ flushed++;
56
+ }
57
+ catch {
58
+ // Re-queue failures
59
+ offlineQueue.push(entry);
60
+ }
61
+ }
62
+ return flushed;
63
+ }
64
+ export function getOfflineQueueSize() {
65
+ return offlineQueue.length;
66
+ }
67
+ /** Clears the offline queue (for testing). */
68
+ export function clearOfflineQueue() {
69
+ offlineQueue.length = 0;
70
+ }
71
+ //# sourceMappingURL=usage_tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage_tracker.js","sourceRoot":"","sources":["../../src/auth/usage_tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAiBxE,MAAM,YAAY,GAAkB,EAAE,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,KAAiB,EACjB,QAAgB,CAAC;IAEjB,mCAAmC;IACnC,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAG,GAAG,MAAM,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjG,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,WAAW,iBAAiB,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK;gBACL,KAAK;gBACL,eAAe,EAAE,cAAc;aAChC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;QACxD,+DAA+D;QAC/D,YAAY,CAAC,IAAI,CAAC;YAChB,MAAM;YACN,KAAK;YACL,KAAK;YACL,cAAc;YACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAExC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,OAAO,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IAClC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAExB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,GAAG,WAAW,iBAAiB,EAAE;gBAC3C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,KAAK,CAAC,MAAM,EAAE;iBACxC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,eAAe,EAAE,KAAK,CAAC,cAAc;iBACtC,CAAC;aACH,CAAC,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;YACpB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,YAAY,CAAC,MAAM,CAAC;AAC7B,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,iBAAiB;IAC/B,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { CodeLoopConfig } from "@codelooptech/shared";
2
+ export declare function getConfigPath(cwd?: string): string;
3
+ export declare function loadConfig(cwd?: string): CodeLoopConfig;
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAEjE;AAED,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc,CAevD"}
package/dist/config.js ADDED
@@ -0,0 +1,41 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ import { DEFAULT_CONFIG } from "@codelooptech/shared";
4
+ export function getConfigPath(cwd = process.cwd()) {
5
+ return join(cwd, ".codeloop", "config.json");
6
+ }
7
+ export function loadConfig(cwd) {
8
+ const configPath = getConfigPath(cwd);
9
+ if (!existsSync(configPath)) {
10
+ return { ...DEFAULT_CONFIG };
11
+ }
12
+ try {
13
+ const raw = readFileSync(configPath, "utf-8");
14
+ const parsed = JSON.parse(raw);
15
+ return deepMerge(DEFAULT_CONFIG, parsed);
16
+ }
17
+ catch {
18
+ return { ...DEFAULT_CONFIG };
19
+ }
20
+ }
21
+ function deepMerge(defaults, overrides) {
22
+ const result = { ...defaults };
23
+ for (const key of Object.keys(overrides)) {
24
+ const val = overrides[key];
25
+ const def = defaults[key];
26
+ if (val !== undefined &&
27
+ typeof val === "object" &&
28
+ val !== null &&
29
+ !Array.isArray(val) &&
30
+ typeof def === "object" &&
31
+ def !== null &&
32
+ !Array.isArray(def)) {
33
+ result[key] = deepMerge(def, val);
34
+ }
35
+ else if (val !== undefined) {
36
+ result[key] = val;
37
+ }
38
+ }
39
+ return result;
40
+ }
41
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,UAAU,aAAa,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACvD,OAAO,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAC1D,OAAO,SAAS,CACd,cAAoD,EACpD,MAAM,CACsB,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAChB,QAAiC,EACjC,SAAkC;IAElC,MAAM,MAAM,GAA4B,EAAE,GAAG,QAAQ,EAAE,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,IACE,GAAG,KAAK,SAAS;YACjB,OAAO,GAAG,KAAK,QAAQ;YACvB,GAAG,KAAK,IAAI;YACZ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YACnB,OAAO,GAAG,KAAK,QAAQ;YACvB,GAAG,KAAK,IAAI;YACZ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EACnB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CACrB,GAA8B,EAC9B,GAA8B,CAC/B,CAAC;QACJ,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { VisualIssue } from "@codelooptech/shared";
2
+ import type { CodeLoopConfig } from "@codelooptech/shared";
3
+ import type { IssueSeverity } from "@codelooptech/shared";
4
+ export interface VisionReviewRequest {
5
+ imagePath: string;
6
+ uxChecklistPath?: string;
7
+ model?: string;
8
+ }
9
+ export interface VisionCompareRequest {
10
+ referencePath: string;
11
+ actualPath: string;
12
+ screenName: string;
13
+ model?: string;
14
+ uxChecklistPath?: string;
15
+ }
16
+ export interface DesignCompareResult {
17
+ matchScore: number;
18
+ differences: Array<{
19
+ area: string;
20
+ description: string;
21
+ severity: IssueSeverity;
22
+ fix_hint: string;
23
+ }>;
24
+ }
25
+ export declare function reviewScreenshot(req: VisionReviewRequest, config: CodeLoopConfig): Promise<VisualIssue[]>;
26
+ export declare function compareDesign(req: VisionCompareRequest, config: CodeLoopConfig): Promise<DesignCompareResult>;
27
+ //# sourceMappingURL=vision_reviewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vision_reviewer.d.ts","sourceRoot":"","sources":["../../src/diagnosis/vision_reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,aAAa,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AA8SD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,mBAAmB,EACxB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,WAAW,EAAE,CAAC,CA8BxB;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,oBAAoB,EACzB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,mBAAmB,CAAC,CAsD9B"}
@@ -0,0 +1,345 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ const REVIEW_JSON_INSTRUCTION = `Respond with ONLY valid JSON (no markdown, no commentary): a JSON array of objects, each with:
3
+ - "issue": string (short title)
4
+ - "severity": one of "critical", "high", "medium", "low"
5
+ - "confidence": number 0-100
6
+ - "evidence": string (what you observe in the image)
7
+ - "fix_hint": string (actionable fix)`;
8
+ const COMPARE_JSON_INSTRUCTION = `Respond with ONLY valid JSON (no markdown, no commentary): an object with:
9
+ - "match_score": number from 0.0 (completely different) to 1.0 (pixel-perfect match in layout and styling intent)
10
+ - "differences": array of { "area": string, "description": string, "severity": "critical"|"high"|"medium"|"low", "fix_hint": string }`;
11
+ function readImageBase64(imagePath) {
12
+ if (!existsSync(imagePath)) {
13
+ throw new Error(`Image not found: ${imagePath}`);
14
+ }
15
+ return readFileSync(imagePath).toString("base64");
16
+ }
17
+ function getEnvKey(provider) {
18
+ switch (provider) {
19
+ case "claude":
20
+ return process.env.ANTHROPIC_API_KEY;
21
+ case "openai":
22
+ return process.env.OPENAI_API_KEY;
23
+ case "gemini":
24
+ return process.env.GOOGLE_AI_KEY;
25
+ default:
26
+ return undefined;
27
+ }
28
+ }
29
+ function resolveAutoProvider() {
30
+ if (getEnvKey("claude"))
31
+ return "claude";
32
+ if (getEnvKey("openai"))
33
+ return "openai";
34
+ if (getEnvKey("gemini"))
35
+ return "gemini";
36
+ return null;
37
+ }
38
+ function resolveProvider(config) {
39
+ const mode = config.vision_model;
40
+ if (mode === "auto") {
41
+ return resolveAutoProvider();
42
+ }
43
+ const map = {
44
+ claude: "claude",
45
+ gpt4o: "openai",
46
+ gemini: "gemini",
47
+ };
48
+ const p = map[mode];
49
+ if (!p || !getEnvKey(p)) {
50
+ return null;
51
+ }
52
+ return p;
53
+ }
54
+ function noVisionKeyIssue() {
55
+ return {
56
+ issue: "No vision model configured",
57
+ severity: "low",
58
+ confidence: 100,
59
+ evidence: "Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_KEY",
60
+ fix_hint: "Configure a vision model API key in your environment",
61
+ };
62
+ }
63
+ function warningIssue(message, evidence) {
64
+ return {
65
+ issue: message,
66
+ severity: "low",
67
+ confidence: 100,
68
+ evidence,
69
+ fix_hint: "Check API keys, network, and model availability; then retry.",
70
+ };
71
+ }
72
+ const SEVERITIES = ["critical", "high", "medium", "low"];
73
+ function normalizeSeverity(s) {
74
+ if (typeof s === "string" && SEVERITIES.includes(s)) {
75
+ return s;
76
+ }
77
+ return "medium";
78
+ }
79
+ function parseJsonPayload(text) {
80
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
81
+ const body = fenced ? fenced[1].trim() : text.trim();
82
+ try {
83
+ return JSON.parse(body);
84
+ }
85
+ catch {
86
+ const startArr = body.indexOf("[");
87
+ const startObj = body.indexOf("{");
88
+ let slice = body;
89
+ if (startArr >= 0 && (startObj < 0 || startArr < startObj)) {
90
+ slice = body.slice(startArr);
91
+ }
92
+ else if (startObj >= 0) {
93
+ slice = body.slice(startObj);
94
+ }
95
+ try {
96
+ return JSON.parse(slice);
97
+ }
98
+ catch {
99
+ throw new Error("Model response did not contain valid JSON");
100
+ }
101
+ }
102
+ }
103
+ function parseVisualIssuesFromResponse(text) {
104
+ let raw;
105
+ try {
106
+ raw = parseJsonPayload(text);
107
+ }
108
+ catch {
109
+ return [];
110
+ }
111
+ if (!Array.isArray(raw)) {
112
+ return [];
113
+ }
114
+ const out = [];
115
+ for (const item of raw) {
116
+ if (!item || typeof item !== "object")
117
+ continue;
118
+ const o = item;
119
+ const issue = typeof o.issue === "string" ? o.issue : "Unspecified issue";
120
+ const confidence = typeof o.confidence === "number" && Number.isFinite(o.confidence)
121
+ ? Math.max(0, Math.min(100, Math.round(o.confidence)))
122
+ : 50;
123
+ out.push({
124
+ issue,
125
+ severity: normalizeSeverity(o.severity),
126
+ confidence,
127
+ evidence: typeof o.evidence === "string" ? o.evidence : "",
128
+ fix_hint: typeof o.fix_hint === "string" ? o.fix_hint : "",
129
+ });
130
+ }
131
+ return out;
132
+ }
133
+ function parseCompareFromResponse(text) {
134
+ let raw;
135
+ try {
136
+ raw = parseJsonPayload(text);
137
+ }
138
+ catch {
139
+ return { matchScore: 0.5, differences: [] };
140
+ }
141
+ if (!raw || typeof raw !== "object") {
142
+ return { matchScore: 0.5, differences: [] };
143
+ }
144
+ const o = raw;
145
+ let matchScore = 0.5;
146
+ if (typeof o.match_score === "number" && Number.isFinite(o.match_score)) {
147
+ matchScore = Math.max(0, Math.min(1, o.match_score));
148
+ }
149
+ else if (typeof o.matchScore === "number" && Number.isFinite(o.matchScore)) {
150
+ matchScore = Math.max(0, Math.min(1, o.matchScore));
151
+ }
152
+ const diffsRaw = o.differences;
153
+ const differences = [];
154
+ if (Array.isArray(diffsRaw)) {
155
+ for (const d of diffsRaw) {
156
+ if (!d || typeof d !== "object")
157
+ continue;
158
+ const rec = d;
159
+ differences.push({
160
+ area: typeof rec.area === "string" ? rec.area : "general",
161
+ description: typeof rec.description === "string" ? rec.description : "",
162
+ severity: normalizeSeverity(rec.severity),
163
+ fix_hint: typeof rec.fix_hint === "string"
164
+ ? rec.fix_hint
165
+ : typeof rec.fixHint === "string"
166
+ ? rec.fixHint
167
+ : "",
168
+ });
169
+ }
170
+ }
171
+ return { matchScore, differences };
172
+ }
173
+ async function callClaudeVision(prompt, images, modelId) {
174
+ const { Anthropic } = await import("@anthropic-ai/sdk");
175
+ const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
176
+ const content = [];
177
+ for (const img of images) {
178
+ content.push({
179
+ type: "image",
180
+ source: {
181
+ type: "base64",
182
+ media_type: img.mediaType,
183
+ data: img.base64,
184
+ },
185
+ });
186
+ }
187
+ content.push({ type: "text", text: prompt });
188
+ const model = modelId || "claude-3-5-sonnet-20241022";
189
+ const res = await client.messages.create({
190
+ model,
191
+ max_tokens: 4096,
192
+ messages: [{ role: "user", content }],
193
+ });
194
+ const block = res.content.find((b) => b.type === "text");
195
+ return block && block.type === "text" ? block.text : "";
196
+ }
197
+ async function callOpenAiVision(prompt, imageUrls, modelId) {
198
+ const { OpenAI } = await import("openai");
199
+ const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
200
+ const content = [{ type: "text", text: prompt }];
201
+ for (const url of imageUrls) {
202
+ content.push({
203
+ type: "image_url",
204
+ image_url: { url },
205
+ });
206
+ }
207
+ const model = modelId || "gpt-4o";
208
+ const res = await client.chat.completions.create({
209
+ model,
210
+ messages: [{ role: "user", content }],
211
+ max_tokens: 4096,
212
+ });
213
+ return res.choices[0]?.message?.content ?? "";
214
+ }
215
+ async function callGeminiVision(prompt, parts, modelId) {
216
+ const { GoogleGenerativeAI } = await import("@google/generative-ai");
217
+ const apiKey = process.env.GOOGLE_AI_KEY;
218
+ if (!apiKey)
219
+ throw new Error("GOOGLE_AI_KEY not set");
220
+ const genAI = new GoogleGenerativeAI(apiKey);
221
+ const model = genAI.getGenerativeModel({ model: modelId || "gemini-1.5-pro" });
222
+ const res = await model.generateContent([
223
+ prompt,
224
+ ...parts.map((p) => ({
225
+ inlineData: { mimeType: p.mimeType, data: p.data },
226
+ })),
227
+ ]);
228
+ const text = res.response.text();
229
+ return text ?? "";
230
+ }
231
+ function mimeForPath(path) {
232
+ const lower = path.toLowerCase();
233
+ if (lower.endsWith(".png"))
234
+ return "image/png";
235
+ if (lower.endsWith(".webp"))
236
+ return "image/webp";
237
+ if (lower.endsWith(".gif"))
238
+ return "image/gif";
239
+ if (lower.endsWith(".jpg") || lower.endsWith(".jpeg"))
240
+ return "image/jpeg";
241
+ return "image/png";
242
+ }
243
+ async function runVision(provider, prompt, imagePaths, modelOverride) {
244
+ const paths = imagePaths;
245
+ if (provider === "claude") {
246
+ const images = paths.map((p) => ({
247
+ base64: readImageBase64(p),
248
+ mediaType: mimeForPath(p),
249
+ }));
250
+ return callClaudeVision(prompt, images, modelOverride ?? "");
251
+ }
252
+ if (provider === "openai") {
253
+ const urls = paths.map((p) => {
254
+ const b64 = readImageBase64(p);
255
+ const mime = mimeForPath(p);
256
+ return `data:${mime};base64,${b64}`;
257
+ });
258
+ return callOpenAiVision(prompt, urls, modelOverride ?? "");
259
+ }
260
+ const parts = paths.map((p) => ({
261
+ mimeType: mimeForPath(p),
262
+ data: readImageBase64(p),
263
+ }));
264
+ return callGeminiVision(prompt, parts, modelOverride ?? "");
265
+ }
266
+ export async function reviewScreenshot(req, config) {
267
+ const provider = resolveProvider(config);
268
+ if (!provider) {
269
+ return [noVisionKeyIssue()];
270
+ }
271
+ let checklist = "";
272
+ if (req.uxChecklistPath && existsSync(req.uxChecklistPath)) {
273
+ try {
274
+ checklist = readFileSync(req.uxChecklistPath, "utf-8");
275
+ }
276
+ catch {
277
+ checklist = "";
278
+ }
279
+ }
280
+ const prompt = `You are an expert UX/UI reviewer. Analyze the screenshot for usability, visual hierarchy, spacing, typography, touch targets, affordances, consistency, and obvious accessibility problems.
281
+
282
+ ${checklist ? `Apply this UX checklist where relevant:\n${checklist}\n\n` : ""}
283
+ ${REVIEW_JSON_INSTRUCTION}`;
284
+ try {
285
+ const text = await runVision(provider, prompt, [req.imagePath], req.model);
286
+ const issues = parseVisualIssuesFromResponse(text);
287
+ return issues;
288
+ }
289
+ catch (e) {
290
+ const msg = e instanceof Error ? e.message : String(e);
291
+ return [
292
+ warningIssue("Vision API error during screenshot review", msg),
293
+ ];
294
+ }
295
+ }
296
+ export async function compareDesign(req, config) {
297
+ const provider = resolveProvider(config);
298
+ if (!provider) {
299
+ return {
300
+ matchScore: 0,
301
+ differences: [
302
+ {
303
+ area: "configuration",
304
+ description: "No vision API key available for design comparison.",
305
+ severity: "low",
306
+ fix_hint: "Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_KEY",
307
+ },
308
+ ],
309
+ };
310
+ }
311
+ let checklist = "";
312
+ if (req.uxChecklistPath && existsSync(req.uxChecklistPath)) {
313
+ try {
314
+ checklist = readFileSync(req.uxChecklistPath, "utf-8");
315
+ }
316
+ catch {
317
+ checklist = "";
318
+ }
319
+ }
320
+ const prompt = `Compare the REFERENCE design image (first image) with the ACTUAL implementation screenshot (second image) for screen "${req.screenName}".
321
+ Assess layout, typography, colors, spacing, component placement, and visual hierarchy. Ignore benign anti-aliasing or compression artifacts.
322
+
323
+ ${checklist ? `Consider these UX/design criteria where relevant:\n${checklist}\n\n` : ""}
324
+ ${COMPARE_JSON_INSTRUCTION}`;
325
+ try {
326
+ const text = await runVision(provider, prompt, [req.referencePath, req.actualPath], req.model);
327
+ const parsed = parseCompareFromResponse(text);
328
+ return parsed;
329
+ }
330
+ catch (e) {
331
+ const msg = e instanceof Error ? e.message : String(e);
332
+ return {
333
+ matchScore: 0,
334
+ differences: [
335
+ {
336
+ area: "vision_api",
337
+ description: "Vision API error during design comparison.",
338
+ severity: "medium",
339
+ fix_hint: msg,
340
+ },
341
+ ],
342
+ };
343
+ }
344
+ }
345
+ //# sourceMappingURL=vision_reviewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vision_reviewer.js","sourceRoot":"","sources":["../../src/diagnosis/vision_reviewer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RunArtifact } from "@codelooptech/shared";
2
+ export declare function generateRunId(): string;
3
+ export declare function getArtifactsBaseDir(cwd?: string): string;
4
+ export declare function createRunDir(runId?: string, baseDir?: string): {
5
+ runId: string;
6
+ runDir: string;
7
+ };
8
+ export declare function saveRunMeta(runDir: string, meta: Partial<RunArtifact>): void;
9
+ export declare function loadRunMeta(runIdOrDir: string, baseDir?: string): Partial<RunArtifact> | null;
10
+ export declare function listRuns(baseDir?: string): string[];
11
+ export declare function getRunDir(runId: string, baseDir?: string): string;
12
+ //# sourceMappingURL=artifacts.d.ts.map