context-eng 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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +272 -0
  3. package/dist/categories.d.ts +27 -0
  4. package/dist/categories.js +71 -0
  5. package/dist/categories.js.map +1 -0
  6. package/dist/cli-entry.d.ts +2 -0
  7. package/dist/cli-entry.js +7 -0
  8. package/dist/cli-entry.js.map +1 -0
  9. package/dist/cli.d.ts +30 -0
  10. package/dist/cli.js +327 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/db.d.ts +40 -0
  13. package/dist/db.js +158 -0
  14. package/dist/db.js.map +1 -0
  15. package/dist/engine.d.ts +149 -0
  16. package/dist/engine.js +589 -0
  17. package/dist/engine.js.map +1 -0
  18. package/dist/harness.d.ts +56 -0
  19. package/dist/harness.js +358 -0
  20. package/dist/harness.js.map +1 -0
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.js +3 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/inspect-cli.d.ts +2 -0
  25. package/dist/inspect-cli.js +96 -0
  26. package/dist/inspect-cli.js.map +1 -0
  27. package/dist/inspect.d.ts +33 -0
  28. package/dist/inspect.js +149 -0
  29. package/dist/inspect.js.map +1 -0
  30. package/dist/map.d.ts +39 -0
  31. package/dist/map.js +106 -0
  32. package/dist/map.js.map +1 -0
  33. package/dist/mcp.d.ts +5 -0
  34. package/dist/mcp.js +348 -0
  35. package/dist/mcp.js.map +1 -0
  36. package/dist/migrate.d.ts +7 -0
  37. package/dist/migrate.js +107 -0
  38. package/dist/migrate.js.map +1 -0
  39. package/dist/paths.d.ts +29 -0
  40. package/dist/paths.js +69 -0
  41. package/dist/paths.js.map +1 -0
  42. package/dist/search.d.ts +144 -0
  43. package/dist/search.js +449 -0
  44. package/dist/search.js.map +1 -0
  45. package/dist/secrets.d.ts +28 -0
  46. package/dist/secrets.js +135 -0
  47. package/dist/secrets.js.map +1 -0
  48. package/dist/text.d.ts +22 -0
  49. package/dist/text.js +153 -0
  50. package/dist/text.js.map +1 -0
  51. package/dist/tokens.d.ts +6 -0
  52. package/dist/tokens.js +15 -0
  53. package/dist/tokens.js.map +1 -0
  54. package/dist/typesafe.d.ts +40 -0
  55. package/dist/typesafe.js +170 -0
  56. package/dist/typesafe.js.map +1 -0
  57. package/package.json +51 -0
  58. package/system_prompts/AGENTS.md +14 -0
  59. package/system_prompts/CLAUDE.md +14 -0
  60. package/system_prompts/rules.md +157 -0
@@ -0,0 +1,135 @@
1
+ export const TYPE_SAFE_KEY_PROMPT = "TypeSafe API key (hidden, Enter to skip): ";
2
+ export const TYPE_SAFE_KEY_REPLACE_PROMPT = "New TypeSafe API key (hidden, Enter to keep the saved key): ";
3
+ const KEYCHAIN_SERVICE = "context-eng";
4
+ const KEYCHAIN_ACCOUNT = "typesafe-api-key";
5
+ export function resolveTypeSafeApiKey(env, read) {
6
+ if (env.TYPESAFE_API_KEY !== undefined)
7
+ return { apiKey: env.TYPESAFE_API_KEY.trim() };
8
+ try {
9
+ return { apiKey: read()?.trim() ?? "" };
10
+ }
11
+ catch (error) {
12
+ return {
13
+ apiKey: "",
14
+ warning: `TypeSafe keychain unreadable. Search will stay local. ${errorText(error)}`,
15
+ };
16
+ }
17
+ }
18
+ export async function loadTypeSafeApiKey(env = process.env) {
19
+ if (env.TYPESAFE_API_KEY !== undefined)
20
+ return { apiKey: env.TYPESAFE_API_KEY.trim() };
21
+ const store = await openOsKeychain();
22
+ return resolveTypeSafeApiKey(env, () => store.get());
23
+ }
24
+ export async function openOsKeychain() {
25
+ try {
26
+ const { Entry } = await import("@napi-rs/keyring");
27
+ const entry = new Entry(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT);
28
+ return {
29
+ get: () => entry.getPassword(),
30
+ set: (secret) => {
31
+ entry.setPassword(secret);
32
+ },
33
+ };
34
+ }
35
+ catch (error) {
36
+ const message = `OS keychain is unavailable. ${errorText(error)}`;
37
+ return {
38
+ get() {
39
+ throw new Error(message);
40
+ },
41
+ set() {
42
+ throw new Error(message);
43
+ },
44
+ };
45
+ }
46
+ }
47
+ export async function ensureTypeSafeKey(options) {
48
+ const log = options.log ?? ((line) => console.log(line));
49
+ let existing;
50
+ try {
51
+ existing = options.store.get();
52
+ }
53
+ catch (error) {
54
+ log(`TypeSafe keychain unavailable. Search will stay local. ${errorText(error)}`);
55
+ return "skipped";
56
+ }
57
+ const replacing = existing !== null && existing.trim() !== "";
58
+ if (!options.interactive) {
59
+ log(replacing
60
+ ? "TypeSafe key is already in the OS keychain."
61
+ : "No TypeSafe key saved. Run context-eng init in a terminal to store one in the OS keychain.");
62
+ return replacing ? "present" : "skipped";
63
+ }
64
+ log(replacing
65
+ ? "A TypeSafe key is already saved. Enter a new key to replace it, or press Enter to keep it."
66
+ : "The key is stored in the OS keychain for this login. It is not written to the project.");
67
+ const prompt = options.prompt ?? ((label) => promptHidden(label));
68
+ const key = (await prompt(replacing ? TYPE_SAFE_KEY_REPLACE_PROMPT : TYPE_SAFE_KEY_PROMPT)).trim();
69
+ if (key === "") {
70
+ log(replacing
71
+ ? "Kept the saved TypeSafe key."
72
+ : "Skipped. Search stays on local FTS5 until a key is saved.");
73
+ return replacing ? "present" : "skipped";
74
+ }
75
+ try {
76
+ options.store.set(key);
77
+ }
78
+ catch (error) {
79
+ log(replacing
80
+ ? `Could not replace the TypeSafe key. The saved key is unchanged. ${errorText(error)}`
81
+ : `Could not save the TypeSafe key. Search will stay local. ${errorText(error)}`);
82
+ return replacing ? "present" : "skipped";
83
+ }
84
+ log(replacing
85
+ ? "Replaced the TypeSafe key in the OS keychain."
86
+ : "Saved the TypeSafe key in the OS keychain.");
87
+ return "saved";
88
+ }
89
+ export function promptHidden(label, io = {}) {
90
+ const input = io.input ?? process.stdin;
91
+ const output = io.output ?? process.stdout;
92
+ if (!input.isTTY || typeof input.setRawMode !== "function")
93
+ return Promise.resolve("");
94
+ return new Promise((resolve, reject) => {
95
+ let value = "";
96
+ let settled = false;
97
+ const finish = (fn) => {
98
+ if (settled)
99
+ return;
100
+ settled = true;
101
+ input.setRawMode(false);
102
+ input.pause();
103
+ input.off("data", onData);
104
+ output.write("\n");
105
+ fn();
106
+ };
107
+ const onData = (chunk) => {
108
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
109
+ for (const char of text) {
110
+ if (char === "\u0003") {
111
+ finish(() => reject(new Error("TypeSafe key prompt aborted")));
112
+ return;
113
+ }
114
+ if (char === "\r" || char === "\n") {
115
+ finish(() => resolve(value.trim()));
116
+ return;
117
+ }
118
+ if (char === "\u007f" || char === "\b") {
119
+ value = value.slice(0, -1);
120
+ continue;
121
+ }
122
+ if (char >= " ")
123
+ value += char;
124
+ }
125
+ };
126
+ output.write(label);
127
+ input.setRawMode(true);
128
+ input.resume();
129
+ input.on("data", onData);
130
+ });
131
+ }
132
+ function errorText(error) {
133
+ return error instanceof Error ? error.message : String(error);
134
+ }
135
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,4CAA4C,CAAC;AACjF,MAAM,CAAC,MAAM,4BAA4B,GAAG,8DAA8D,CAAC;AAS3G,MAAM,gBAAgB,GAAG,aAAa,CAAC;AACvC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAE5C,MAAM,UAAU,qBAAqB,CACnC,GAAkC,EAClC,IAAyB;IAEzB,IAAI,GAAG,CAAC,gBAAgB,KAAK,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC;IACvF,IAAI,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,EAAE;YACV,OAAO,EAAE,yDAAyD,SAAS,CAAC,KAAK,CAAC,EAAE;SACrF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,GAAG,CAAC,gBAAgB,KAAK,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC;IACvF,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;IACrC,OAAO,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;QAC5D,OAAO;YACL,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,GAAG,EAAE,CAAC,MAAc,EAAE,EAAE;gBACtB,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,+BAA+B,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAClE,OAAO;YACL,GAAG;gBACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;YACD,GAAG;gBACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;SACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAKvC;IACC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,IAAI,QAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,0DAA0D,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAC9D,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzB,GAAG,CAAC,SAAS;YACX,CAAC,CAAC,6CAA6C;YAC/C,CAAC,CAAC,4FAA4F,CAAC,CAAC;QAClG,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3C,CAAC;IACD,GAAG,CAAC,SAAS;QACX,CAAC,CAAC,4FAA4F;QAC9F,CAAC,CAAC,wFAAwF,CAAC,CAAC;IAC9F,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACnG,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QACf,GAAG,CAAC,SAAS;YACX,CAAC,CAAC,8BAA8B;YAChC,CAAC,CAAC,2DAA2D,CAAC,CAAC;QACjE,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,SAAS;YACX,CAAC,CAAC,mEAAmE,SAAS,CAAC,KAAK,CAAC,EAAE;YACvF,CAAC,CAAC,4DAA4D,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpF,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3C,CAAC;IACD,GAAG,CAAC,SAAS;QACX,CAAC,CAAC,+CAA+C;QACjD,CAAC,CAAC,4CAA4C,CAAC,CAAC;IAClD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAa,EACb,KAAiE,EAAE;IAEnE,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IACxC,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,KAAK,GAAG,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,EAAc,EAAE,EAAE;YAChC,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACxB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACnB,EAAE,EAAE,CAAC;QACP,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,KAAsB,EAAE,EAAE;YACxC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxE,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;gBACxB,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACtB,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC;oBAC/D,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBACnC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;oBACpC,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBACvC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBACD,IAAI,IAAI,IAAI,GAAG;oBAAE,KAAK,IAAI,IAAI,CAAC;YACjC,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpB,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACvB,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
package/dist/text.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ /** Unicode-aware, lowercased word tokens with English stopwords removed, deduplicated in order. */
2
+ export declare function keywords(text: string): string[];
3
+ /** True when a second sentence starts after `.` `!` or `?`. */
4
+ export declare function hasMultipleSentences(content: string): boolean;
5
+ /** Structured labels are stored as normalized comma-separated values for FTS display. */
6
+ export declare function parseLabels(labels: string | null | undefined): string[];
7
+ export declare const parseTags: typeof parseLabels;
8
+ export declare function normalizeLabel(value: string): string;
9
+ export declare function normalizeLabels(values: readonly string[] | undefined): string[];
10
+ export declare function serializeLabels(values: readonly string[] | undefined): string | null;
11
+ export declare const serializeTags: typeof serializeLabels;
12
+ /**
13
+ * Build an FTS5 MATCH expression from free text. Each token is quoted so
14
+ * FTS5 syntax characters in the query cannot break the statement.
15
+ * Returns null when nothing is searchable.
16
+ */
17
+ export declare function buildFtsQuery(query: string): string | null;
18
+ export declare function lexicalQueryTerms(query: string): string[];
19
+ /** Return one conservatively corrected lexical query, or null when no unambiguous correction exists. */
20
+ export declare function correctTypoQuery(query: string, vocabularyText: readonly string[]): string | null;
21
+ /** Unicode-aware Damerau-Levenshtein. Caps at maxDistance+1 when the bound is finite. */
22
+ export declare function editDistance(left: string, right: string, maxDistance?: number): number;
package/dist/text.js ADDED
@@ -0,0 +1,153 @@
1
+ const STOPWORDS = new Set([
2
+ "a", "an", "the", "and", "or", "but", "if", "then", "else", "when", "while",
3
+ "of", "to", "in", "on", "at", "by", "for", "with", "from", "into", "about",
4
+ "as", "is", "are", "was", "were", "be", "been", "being", "am",
5
+ "it", "its", "this", "that", "these", "those", "there", "here",
6
+ "i", "we", "you", "he", "she", "they", "me", "us", "them", "my", "our", "your",
7
+ "do", "does", "did", "done", "doing", "have", "has", "had",
8
+ "yes", "so", "too", "very", "just", "only", "also",
9
+ "can", "could", "should", "would", "will", "may", "might",
10
+ "use", "used", "using", "prefer", "please",
11
+ "after", "before", "over", "under", "again", "all", "any", "each", "some",
12
+ "how", "what", "which", "who", "why", "where",
13
+ ]);
14
+ const NEGATIVE_TERMS = ["not", "no", "never"];
15
+ const POSITIVE_TERMS = ["always", "must", "required"];
16
+ const POLARITY_TERMS = new Set([...NEGATIVE_TERMS, ...POSITIVE_TERMS]);
17
+ /** Unicode-aware, lowercased word tokens with English stopwords removed, deduplicated in order. */
18
+ export function keywords(text) {
19
+ const seen = new Set();
20
+ const out = [];
21
+ const rawTokens = text.toLowerCase().match(/[\p{L}\p{M}\p{N}_-]+/gu) ?? [];
22
+ for (const raw of rawTokens) {
23
+ const tok = raw.replace(/^[-_]+|[-_]+$/g, "");
24
+ const singleAsciiCharacter = tok.length === 1 && /^[a-z0-9]$/.test(tok);
25
+ if (tok.length === 0 || singleAsciiCharacter || STOPWORDS.has(tok) || seen.has(tok))
26
+ continue;
27
+ seen.add(tok);
28
+ out.push(tok);
29
+ }
30
+ return out;
31
+ }
32
+ /** True when a second sentence starts after `.` `!` or `?`. */
33
+ export function hasMultipleSentences(content) {
34
+ return /[.!?]["')\]]*\s+[A-Za-z]/.test(content.trim());
35
+ }
36
+ /** Structured labels are stored as normalized comma-separated values for FTS display. */
37
+ export function parseLabels(labels) {
38
+ if (!labels)
39
+ return [];
40
+ return labels
41
+ .split(",")
42
+ .map((t) => normalizeLabel(t))
43
+ .filter((t) => t.length > 0);
44
+ }
45
+ export const parseTags = parseLabels;
46
+ export function normalizeLabel(value) {
47
+ return value.normalize("NFKC").trim().toLocaleLowerCase("en-US");
48
+ }
49
+ export function normalizeLabels(values) {
50
+ if (!values)
51
+ return [];
52
+ return [...new Set(values.map(normalizeLabel).filter(Boolean))];
53
+ }
54
+ export function serializeLabels(values) {
55
+ const clean = normalizeLabels(values);
56
+ return clean.length ? clean.join(",") : null;
57
+ }
58
+ export const serializeTags = serializeLabels;
59
+ /**
60
+ * Build an FTS5 MATCH expression from free text. Each token is quoted so
61
+ * FTS5 syntax characters in the query cannot break the statement.
62
+ * Returns null when nothing is searchable.
63
+ */
64
+ export function buildFtsQuery(query) {
65
+ const toks = keywords(query);
66
+ if (toks.length === 0)
67
+ return null;
68
+ const groups = [];
69
+ if (toks.some((token) => NEGATIVE_TERMS.includes(token))) {
70
+ groups.push(orGroup(NEGATIVE_TERMS, true));
71
+ }
72
+ else if (toks.some((token) => POSITIVE_TERMS.includes(token))) {
73
+ groups.push(orGroup(POSITIVE_TERMS, true));
74
+ }
75
+ const subjectTerms = toks.filter((token) => !POLARITY_TERMS.has(token));
76
+ if (subjectTerms.length > 0)
77
+ groups.push(orGroup(subjectTerms, groups.length > 0));
78
+ return groups.length > 0 ? groups.join(" AND ") : null;
79
+ }
80
+ export function lexicalQueryTerms(query) {
81
+ return keywords(query).filter((token) => !POLARITY_TERMS.has(token));
82
+ }
83
+ /** Return one conservatively corrected lexical query, or null when no unambiguous correction exists. */
84
+ export function correctTypoQuery(query, vocabularyText) {
85
+ const queryTokens = keywords(query);
86
+ const vocabulary = new Set(vocabularyText.flatMap((text) => keywords(text)));
87
+ const replacements = new Map();
88
+ for (const token of queryTokens) {
89
+ if (replacements.size >= 3 || vocabulary.has(token) || POLARITY_TERMS.has(token))
90
+ continue;
91
+ const characters = [...token];
92
+ if (characters.length < 4 || !/^\p{L}[\p{L}\p{M}]*$/u.test(token))
93
+ continue;
94
+ const maxDistance = characters.length >= 8 ? 2 : 1;
95
+ let bestDistance = maxDistance + 1;
96
+ let best;
97
+ let tied = false;
98
+ for (const candidate of vocabulary) {
99
+ if (!/^\p{L}[\p{L}\p{M}]*$/u.test(candidate))
100
+ continue;
101
+ if (Math.abs([...candidate].length - characters.length) > maxDistance)
102
+ continue;
103
+ const distance = editDistance(token, candidate, maxDistance);
104
+ if (distance < bestDistance) {
105
+ bestDistance = distance;
106
+ best = candidate;
107
+ tied = false;
108
+ }
109
+ else if (distance === bestDistance) {
110
+ tied = true;
111
+ }
112
+ }
113
+ if (best !== undefined && bestDistance <= maxDistance && !tied)
114
+ replacements.set(token, best);
115
+ }
116
+ if (replacements.size === 0)
117
+ return null;
118
+ return queryTokens.map((token) => replacements.get(token) ?? token).join(" ");
119
+ }
120
+ function orGroup(tokens, parenthesize) {
121
+ const quoted = tokens.map((token) => `"${token.replace(/"/g, "")}"`);
122
+ const expression = quoted.join(" OR ");
123
+ return parenthesize && quoted.length > 1 ? `(${expression})` : expression;
124
+ }
125
+ /** Unicode-aware Damerau-Levenshtein. Caps at maxDistance+1 when the bound is finite. */
126
+ export function editDistance(left, right, maxDistance = Number.POSITIVE_INFINITY) {
127
+ const a = [...left];
128
+ const b = [...right];
129
+ if (Math.abs(a.length - b.length) > maxDistance)
130
+ return maxDistance + 1;
131
+ const matrix = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
132
+ for (let row = 0; row <= a.length; row += 1)
133
+ matrix[row][0] = row;
134
+ for (let column = 0; column <= b.length; column += 1)
135
+ matrix[0][column] = column;
136
+ for (let row = 1; row <= a.length; row += 1) {
137
+ for (let column = 1; column <= b.length; column += 1) {
138
+ const substitution = matrix[row - 1][column - 1] + (a[row - 1] === b[column - 1] ? 0 : 1);
139
+ const deletion = matrix[row - 1][column] + 1;
140
+ const insertion = matrix[row][column - 1] + 1;
141
+ let distance = Math.min(substitution, deletion, insertion);
142
+ if (row > 1 &&
143
+ column > 1 &&
144
+ a[row - 1] === b[column - 2] &&
145
+ a[row - 2] === b[column - 1]) {
146
+ distance = Math.min(distance, matrix[row - 2][column - 2] + 1);
147
+ }
148
+ matrix[row][column] = distance;
149
+ }
150
+ }
151
+ return matrix[a.length][b.length];
152
+ }
153
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Cheap token estimate. No tokenizer dependency in stage one.
3
+ * Uses the larger of a character-based and a word-based estimate so both
4
+ * dense code and prose land close to what a BPE tokenizer would report.
5
+ */
6
+ export declare function approxTokens(text: string): number;
package/dist/tokens.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Cheap token estimate. No tokenizer dependency in stage one.
3
+ * Uses the larger of a character-based and a word-based estimate so both
4
+ * dense code and prose land close to what a BPE tokenizer would report.
5
+ */
6
+ export function approxTokens(text) {
7
+ const trimmed = text.trim();
8
+ if (trimmed.length === 0)
9
+ return 0;
10
+ const byChars = Math.ceil(trimmed.length / 4);
11
+ const words = trimmed.split(/\s+/).length;
12
+ const byWords = Math.ceil(words * 1.3);
13
+ return Math.max(byChars, byWords);
14
+ }
15
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { type SearchHit, type SearchResult } from "./engine.js";
2
+ /** @context-eng-locked Jev request deadline. Do not change unless the user asks. */
3
+ export declare const DEFAULT_JEV_TIMEOUT_MS = 20000;
4
+ export declare const RELEVANCE_THRESHOLD = 0.5;
5
+ export declare const NOT_RELEVANT_MESSAGE = "no matching memory. after work, memory_create if something happened like a decision , preferences , workflow , mistakes , instructions and you need to save it for later.";
6
+ export declare const TOO_LARGE_TO_EVALUATE_MESSAGE = "Memory is too large to evaluate.";
7
+ export declare const MAX_JEV_EVALUATE_COUNT: number;
8
+ export interface RelevanceEvaluator {
9
+ available?(): boolean;
10
+ evaluate(query: string, candidates: SearchHit[]): Promise<number[]>;
11
+ }
12
+ export interface RelevantSearchHit extends SearchHit {
13
+ relevance: number;
14
+ }
15
+ export interface RelevantSearchResult extends Omit<SearchResult, "hits"> {
16
+ hits: RelevantSearchHit[];
17
+ rejected_count: number;
18
+ message?: string;
19
+ }
20
+ export declare class TypeSafeError extends Error {
21
+ constructor(message: string);
22
+ }
23
+ interface TypeSafeOptions {
24
+ apiKey?: string;
25
+ endpoint?: string;
26
+ fetcher?: typeof fetch;
27
+ timeoutMs?: number;
28
+ }
29
+ export declare class TypeSafeRelevanceEvaluator implements RelevanceEvaluator {
30
+ private readonly apiKey;
31
+ private readonly endpoint;
32
+ private readonly fetcher;
33
+ private readonly timeoutMs;
34
+ constructor(options?: TypeSafeOptions);
35
+ available(): boolean;
36
+ evaluate(query: string, candidates: SearchHit[]): Promise<number[]>;
37
+ private evaluateBatch;
38
+ }
39
+ export declare function applyRelevanceGate(result: SearchResult, evaluator: RelevanceEvaluator): Promise<RelevantSearchResult>;
40
+ export {};
@@ -0,0 +1,170 @@
1
+ import { budgetHits, sortHits, } from "./engine.js";
2
+ import { MAX_JEV_BATCHES, MAX_JEV_CANDIDATES } from "./categories.js";
3
+ const DEFAULT_ENDPOINT = "https://api.typesafe.ai/v1/systemone";
4
+ /** @context-eng-locked Jev request deadline. Do not change unless the user asks. */
5
+ export const DEFAULT_JEV_TIMEOUT_MS = 20_000;
6
+ export const RELEVANCE_THRESHOLD = 0.5;
7
+ export const NOT_RELEVANT_MESSAGE = "no matching memory. after work, memory_create if something happened like a decision , preferences , workflow , mistakes , instructions and you need to save it for later.";
8
+ export const TOO_LARGE_TO_EVALUATE_MESSAGE = "Memory is too large to evaluate.";
9
+ export const MAX_JEV_EVALUATE_COUNT = MAX_JEV_CANDIDATES * MAX_JEV_BATCHES;
10
+ export class TypeSafeError extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = "TypeSafeError";
14
+ }
15
+ }
16
+ export class TypeSafeRelevanceEvaluator {
17
+ apiKey;
18
+ endpoint;
19
+ fetcher;
20
+ timeoutMs;
21
+ constructor(options = {}) {
22
+ this.apiKey = options.apiKey?.trim() || process.env.TYPESAFE_API_KEY?.trim() || "";
23
+ this.endpoint = options.endpoint?.trim() || process.env.TYPESAFE_API_URL?.trim() || DEFAULT_ENDPOINT;
24
+ this.fetcher = options.fetcher ?? fetch;
25
+ this.timeoutMs = normalizeTimeout(options.timeoutMs);
26
+ }
27
+ available() {
28
+ return this.apiKey.length > 0;
29
+ }
30
+ async evaluate(query, candidates) {
31
+ if (candidates.length === 0)
32
+ return [];
33
+ if (!this.available())
34
+ throw new TypeSafeError("TYPESAFE_API_KEY is not configured.");
35
+ const limited = limitJevCandidates(candidates);
36
+ const batches = [];
37
+ for (let index = 0; index < limited.length; index += MAX_JEV_CANDIDATES) {
38
+ batches.push(limited.slice(index, index + MAX_JEV_CANDIDATES));
39
+ }
40
+ const scores = await Promise.all(batches.map((batch) => this.evaluateBatch(query, batch)));
41
+ return scores.flat();
42
+ }
43
+ async evaluateBatch(query, candidates) {
44
+ const questions = Object.fromEntries(candidates.map((_, index) => [
45
+ `context_${index}`,
46
+ {
47
+ type: "noul",
48
+ instructions: [
49
+ `Decide whether contexts[${index}] is directly useful for answering or completing agent_prompt.`,
50
+ "Judge semantic usefulness, not merely shared words.",
51
+ ],
52
+ criteria: {
53
+ true: "The context meaningfully helps complete the agent prompt.",
54
+ false: "The context is unrelated, incidental, or too weak to help.",
55
+ },
56
+ },
57
+ ]));
58
+ const controller = new AbortController();
59
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
60
+ timer.unref?.();
61
+ try {
62
+ const response = await this.fetcher(this.endpoint, {
63
+ method: "POST",
64
+ headers: {
65
+ Authorization: `Bearer ${this.apiKey}`,
66
+ "Content-Type": "application/json",
67
+ },
68
+ body: JSON.stringify({
69
+ state: {
70
+ agent_prompt: query,
71
+ contexts: candidates.map((candidate) => candidate.content),
72
+ },
73
+ model: "jev-latest",
74
+ questions,
75
+ }),
76
+ signal: controller.signal,
77
+ });
78
+ if (!response.ok) {
79
+ throw new TypeSafeError(`TypeSafe relevance evaluation failed with HTTP ${response.status}.`);
80
+ }
81
+ let body;
82
+ try {
83
+ body = await response.json();
84
+ }
85
+ catch (error) {
86
+ if (controller.signal.aborted)
87
+ throw error;
88
+ throw new TypeSafeError("TypeSafe relevance evaluation returned invalid JSON.");
89
+ }
90
+ if (!isRecord(body) || !isRecord(body.answers)) {
91
+ throw new TypeSafeError("TypeSafe relevance evaluation returned an invalid response.");
92
+ }
93
+ const answers = body.answers;
94
+ return candidates.map((_, index) => {
95
+ const answer = answers[`context_${index}`];
96
+ if (!isRecord(answer) ||
97
+ answer.type !== "noul" ||
98
+ typeof answer.noul !== "number" ||
99
+ !Number.isFinite(answer.noul) ||
100
+ answer.noul < 0 ||
101
+ answer.noul > 1) {
102
+ throw new TypeSafeError(`TypeSafe relevance evaluation omitted context_${index}.`);
103
+ }
104
+ return answer.noul;
105
+ });
106
+ }
107
+ catch (error) {
108
+ if (controller.signal.aborted) {
109
+ throw new TypeSafeError(`TypeSafe relevance evaluation timed out after ${this.timeoutMs}ms.`);
110
+ }
111
+ if (error instanceof TypeSafeError)
112
+ throw error;
113
+ const detail = error instanceof Error ? error.message : String(error);
114
+ throw new TypeSafeError(`TypeSafe relevance evaluation failed: ${detail}`);
115
+ }
116
+ finally {
117
+ clearTimeout(timer);
118
+ }
119
+ }
120
+ }
121
+ function normalizeTimeout(value) {
122
+ if (value === undefined)
123
+ return DEFAULT_JEV_TIMEOUT_MS;
124
+ if (!Number.isFinite(value) || value <= 0) {
125
+ throw new TypeError("timeoutMs must be a positive finite number");
126
+ }
127
+ return Math.floor(value);
128
+ }
129
+ export async function applyRelevanceGate(result, evaluator) {
130
+ if (result.hits.length === 0) {
131
+ return { ...result, hits: [], rejected_count: 0, message: NOT_RELEVANT_MESSAGE };
132
+ }
133
+ const truncated = result.hits.length > MAX_JEV_EVALUATE_COUNT;
134
+ const candidates = limitJevCandidates(result.hits);
135
+ const scores = await evaluator.evaluate(result.query, candidates);
136
+ if (scores.length !== candidates.length) {
137
+ throw new TypeSafeError("TypeSafe relevance evaluation returned the wrong number of scores.");
138
+ }
139
+ const approved = [];
140
+ for (const [index, hit] of candidates.entries()) {
141
+ const relevance = scores[index];
142
+ if (relevance !== undefined && relevance > RELEVANCE_THRESHOLD) {
143
+ const rounded = round(relevance);
144
+ approved.push({ ...hit, score: rounded, relevance: rounded });
145
+ }
146
+ }
147
+ const sorted = sortHits(approved, result.sort);
148
+ const hits = budgetHits(sorted, result.budget.max_hits, result.budget.max_tokens);
149
+ const filtered = {
150
+ ...result,
151
+ hits,
152
+ total_tokens: hits.reduce((sum, hit) => sum + hit.tokens, 0),
153
+ rejected_count: result.hits.length - approved.length,
154
+ };
155
+ if (truncated && hits.length > 0)
156
+ filtered.message = TOO_LARGE_TO_EVALUATE_MESSAGE;
157
+ else if (hits.length === 0)
158
+ filtered.message = NOT_RELEVANT_MESSAGE;
159
+ return filtered;
160
+ }
161
+ function limitJevCandidates(candidates) {
162
+ return candidates.slice(0, MAX_JEV_EVALUATE_COUNT);
163
+ }
164
+ function isRecord(value) {
165
+ return typeof value === "object" && value !== null && !Array.isArray(value);
166
+ }
167
+ function round(value) {
168
+ return Math.round(value * 1000) / 1000;
169
+ }
170
+ //# sourceMappingURL=typesafe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typesafe.js","sourceRoot":"","sources":["../src/typesafe.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "context-eng",
3
+ "version": "0.1.0",
4
+ "description": "Local Project Memory Router for Codex and Claude Code: SQLite + FTS5 behind MCP tools.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "mayank",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/mayank-devac/context-eng.git"
11
+ },
12
+ "bin": {
13
+ "context-eng": "./dist/cli-entry.js"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "system_prompts"
19
+ ],
20
+ "engines": {
21
+ "node": ">=20"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.json",
25
+ "prepublishOnly": "npm run build",
26
+ "typecheck": "tsc -p tsconfig.json --noEmit",
27
+ "typecheck:test": "tsc -p tsconfig.test.json",
28
+ "mcp": "tsx src/cli-entry.ts mcp",
29
+ "init": "tsx src/cli-entry.ts init",
30
+ "inspect:search": "tsx src/inspect-cli.ts",
31
+ "start": "node dist/cli-entry.js mcp",
32
+ "test": "vitest run",
33
+ "lint": "eslint src test"
34
+ },
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "^1.30.0",
37
+ "@napi-rs/keyring": "^1.3.0",
38
+ "better-sqlite3": "^13.0.3",
39
+ "zod": "^4.6.4"
40
+ },
41
+ "devDependencies": {
42
+ "@eslint/js": "^10.0.1",
43
+ "@types/better-sqlite3": "^9.6.0",
44
+ "@types/node": "^26.5.1",
45
+ "eslint": "^10.10.0",
46
+ "tsx": "^4.23.13",
47
+ "typescript": "^5.9.3",
48
+ "typescript-eslint": "^8.70.0",
49
+ "vitest": "^5.0.0"
50
+ }
51
+ }