@thecat69/cache-ctrl 1.0.0 → 1.2.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.
- package/README.md +289 -78
- package/cache_ctrl.ts +107 -25
- package/package.json +2 -1
- package/skills/cache-ctrl-caller/SKILL.md +53 -114
- package/skills/cache-ctrl-external/SKILL.md +29 -89
- package/skills/cache-ctrl-local/SKILL.md +82 -164
- package/src/analysis/graphBuilder.ts +85 -0
- package/src/analysis/pageRank.ts +164 -0
- package/src/analysis/symbolExtractor.ts +240 -0
- package/src/cache/cacheManager.ts +53 -4
- package/src/cache/externalCache.ts +72 -77
- package/src/cache/graphCache.ts +12 -0
- package/src/cache/localCache.ts +2 -0
- package/src/commands/checkFiles.ts +9 -6
- package/src/commands/flush.ts +9 -2
- package/src/commands/graph.ts +131 -0
- package/src/commands/inspect.ts +13 -181
- package/src/commands/inspectExternal.ts +79 -0
- package/src/commands/inspectLocal.ts +134 -0
- package/src/commands/install.ts +6 -0
- package/src/commands/invalidate.ts +24 -24
- package/src/commands/list.ts +11 -11
- package/src/commands/map.ts +87 -0
- package/src/commands/prune.ts +20 -8
- package/src/commands/search.ts +9 -2
- package/src/commands/touch.ts +15 -25
- package/src/commands/uninstall.ts +103 -0
- package/src/commands/update.ts +65 -0
- package/src/commands/version.ts +14 -0
- package/src/commands/watch.ts +270 -0
- package/src/commands/writeExternal.ts +51 -0
- package/src/commands/writeLocal.ts +121 -0
- package/src/files/changeDetector.ts +15 -0
- package/src/files/gitFiles.ts +15 -0
- package/src/files/openCodeInstaller.ts +21 -2
- package/src/index.ts +314 -58
- package/src/search/keywordSearch.ts +24 -0
- package/src/types/cache.ts +38 -26
- package/src/types/commands.ts +123 -22
- package/src/types/result.ts +26 -9
- package/src/utils/errors.ts +14 -0
- package/src/utils/traversal.ts +42 -0
- package/src/commands/checkFreshness.ts +0 -123
- package/src/commands/write.ts +0 -170
- package/src/http/freshnessChecker.ts +0 -116
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
export interface FreshnessCheckInput {
|
|
2
|
-
url: string;
|
|
3
|
-
etag?: string;
|
|
4
|
-
last_modified?: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface FreshnessCheckOutput {
|
|
8
|
-
url: string;
|
|
9
|
-
status: "fresh" | "stale" | "error";
|
|
10
|
-
http_status?: number;
|
|
11
|
-
etag?: string;
|
|
12
|
-
last_modified?: string;
|
|
13
|
-
error?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* RFC-1918 / loopback / link-local / ULA / mapped-IPv6 IP pattern.
|
|
18
|
-
* Blocks raw IP literals only — does NOT do DNS resolution.
|
|
19
|
-
*
|
|
20
|
-
* Covers:
|
|
21
|
-
* - 127.x loopback IPv4
|
|
22
|
-
* - ::1 loopback IPv6 (URL.hostname returns "[::1]")
|
|
23
|
-
* - localhost loopback hostname
|
|
24
|
-
* - 10.x RFC-1918 class A
|
|
25
|
-
* - 169.254.x link-local IPv4
|
|
26
|
-
* - 172.16–31.x RFC-1918 class B
|
|
27
|
-
* - 192.168.x RFC-1918 class C
|
|
28
|
-
* - 0.0.0.0 unspecified IPv4
|
|
29
|
-
* - fc00::/7 RFC-4193 unique-local IPv6 (ULA — fc or fd prefix)
|
|
30
|
-
* - ::ffff: IPv4-mapped IPv6
|
|
31
|
-
*/
|
|
32
|
-
const PRIVATE_IP_PATTERN =
|
|
33
|
-
/^(127\.|localhost$|10\.|169\.254\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|0\.0\.0\.0$|\[::1\]$|::1$|::ffff:|f[cd][0-9a-f]{0,2}:|\[f[cd][0-9a-f]{0,2}:)/i;
|
|
34
|
-
|
|
35
|
-
export function isAllowedUrl(url: string): { allowed: boolean; reason?: string } {
|
|
36
|
-
try {
|
|
37
|
-
const parsed = new URL(url);
|
|
38
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
39
|
-
return { allowed: false, reason: `Disallowed URL scheme — only http and https are permitted: ${url}` };
|
|
40
|
-
}
|
|
41
|
-
if (PRIVATE_IP_PATTERN.test(parsed.hostname)) {
|
|
42
|
-
return { allowed: false, reason: `Requests to private/loopback addresses are not permitted: ${url}` };
|
|
43
|
-
}
|
|
44
|
-
return { allowed: true };
|
|
45
|
-
} catch {
|
|
46
|
-
return { allowed: false, reason: `Invalid URL: ${url}` };
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function checkFreshness(input: FreshnessCheckInput): Promise<FreshnessCheckOutput> {
|
|
51
|
-
const allowCheck = isAllowedUrl(input.url);
|
|
52
|
-
if (!allowCheck.allowed) {
|
|
53
|
-
const reason = allowCheck.reason ?? `Freshness check blocked for URL: ${input.url}`;
|
|
54
|
-
return {
|
|
55
|
-
url: input.url,
|
|
56
|
-
status: "error",
|
|
57
|
-
error: reason,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const controller = new AbortController();
|
|
62
|
-
const timeoutId = setTimeout(() => controller.abort(), 10_000);
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const headers: Record<string, string> = {};
|
|
66
|
-
if (input.etag) {
|
|
67
|
-
headers["If-None-Match"] = input.etag;
|
|
68
|
-
}
|
|
69
|
-
if (input.last_modified) {
|
|
70
|
-
headers["If-Modified-Since"] = input.last_modified;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const response = await fetch(input.url, {
|
|
74
|
-
method: "HEAD",
|
|
75
|
-
headers,
|
|
76
|
-
signal: controller.signal,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
if (response.status === 304) {
|
|
80
|
-
return {
|
|
81
|
-
url: input.url,
|
|
82
|
-
status: "fresh",
|
|
83
|
-
http_status: 304,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (response.status === 200) {
|
|
88
|
-
const etag = response.headers.get("etag") ?? undefined;
|
|
89
|
-
const lastModified = response.headers.get("last-modified") ?? undefined;
|
|
90
|
-
return {
|
|
91
|
-
url: input.url,
|
|
92
|
-
status: "stale",
|
|
93
|
-
http_status: 200,
|
|
94
|
-
...(etag !== undefined ? { etag } : {}),
|
|
95
|
-
...(lastModified !== undefined ? { last_modified: lastModified } : {}),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// 4xx/5xx
|
|
100
|
-
return {
|
|
101
|
-
url: input.url,
|
|
102
|
-
status: "error",
|
|
103
|
-
http_status: response.status,
|
|
104
|
-
error: `HTTP ${response.status}: ${response.statusText}`,
|
|
105
|
-
};
|
|
106
|
-
} catch (err) {
|
|
107
|
-
const error = err as Error;
|
|
108
|
-
return {
|
|
109
|
-
url: input.url,
|
|
110
|
-
status: "error",
|
|
111
|
-
error: error.message,
|
|
112
|
-
};
|
|
113
|
-
} finally {
|
|
114
|
-
clearTimeout(timeoutId);
|
|
115
|
-
}
|
|
116
|
-
}
|