@prover-coder-ai/context-doc 1.0.7 → 1.0.9

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.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { Effect } from "effect";
3
+ import { buildSyncProgram, parseArgs } from "./syncKnowledge.js";
4
+ const program = buildSyncProgram(parseArgs());
5
+ Effect.runSync(program);
@@ -28,31 +28,31 @@ const readRepositoryUrl = (cwd, repositoryUrlOverride) => Effect.try({
28
28
  },
29
29
  catch: () => syncError("package.json", "Cannot read repository url"),
30
30
  });
31
- const resolveSourceDir = (cwd, override, metaRoot) => Effect.try({
32
- try: () => {
33
- const envSource = process.env.CODEX_SOURCE_DIR;
34
- const metaCandidate = metaRoot === undefined
35
- ? undefined
36
- : metaRoot.endsWith(".codex")
37
- ? metaRoot
38
- : path.join(metaRoot, ".codex");
39
- const localSource = path.join(cwd, ".codex");
40
- const homeSource = path.join(os.homedir(), ".codex");
41
- const candidates = [
42
- override,
43
- envSource,
44
- metaCandidate,
45
- localSource,
46
- homeSource,
47
- ];
48
- const existing = candidates.find((candidate) => candidate !== undefined && fs.existsSync(candidate));
49
- if (existing === undefined) {
50
- throw new Error("source .codex not found");
51
- }
52
- return existing;
53
- },
54
- catch: () => syncError(".codex", "Source .codex directory is missing"),
55
- });
31
+ const resolveSourceDir = (cwd, override, metaRoot) => pipe(Effect.sync(() => {
32
+ const envSource = process.env.CODEX_SOURCE_DIR;
33
+ const metaCandidate = metaRoot === undefined
34
+ ? undefined
35
+ : metaRoot.endsWith(".codex")
36
+ ? metaRoot
37
+ : path.join(metaRoot, ".codex");
38
+ const localSource = path.join(cwd, ".codex");
39
+ const homeSource = path.join(os.homedir(), ".codex");
40
+ const localKnowledge = path.join(cwd, ".knowledge", ".codex");
41
+ const homeKnowledge = path.join(os.homedir(), ".knowledge", ".codex");
42
+ const candidates = [
43
+ override,
44
+ envSource,
45
+ metaCandidate,
46
+ localSource,
47
+ homeSource,
48
+ localKnowledge,
49
+ homeKnowledge,
50
+ ].filter((candidate) => candidate !== undefined);
51
+ const existing = candidates.find((candidate) => fs.existsSync(candidate));
52
+ return { existing, candidates };
53
+ }), Effect.flatMap(({ existing, candidates }) => existing === undefined
54
+ ? Effect.fail(syncError(".codex", `Source .codex directory is missing; checked: ${candidates.join(", ")}`))
55
+ : Effect.succeed(existing)));
56
56
  const collectJsonlFiles = (root) => Effect.try({
57
57
  try: () => {
58
58
  const collected = [];
@@ -110,10 +110,14 @@ export const syncCodex = (options) => Effect.gen(function* (_) {
110
110
  const repositoryUrl = yield* _(readRepositoryUrl(options.cwd, options.repositoryUrlOverride));
111
111
  const sourceDir = yield* _(resolveSourceDir(options.cwd, options.sourceDir, options.metaRoot));
112
112
  const destinationDir = options.destinationDir ?? path.join(options.cwd, ".knowledge", ".codex");
113
+ if (path.resolve(sourceDir) === path.resolve(destinationDir)) {
114
+ yield* _(Console.log("Codex source equals destination; skipping copy to avoid duplicates"));
115
+ return;
116
+ }
113
117
  yield* _(ensureDirectory(destinationDir));
114
118
  const locator = buildProjectLocator(repositoryUrl, options.cwd);
115
119
  const allJsonlFiles = yield* _(collectJsonlFiles(sourceDir));
116
120
  const relevantFiles = yield* _(selectRelevantFiles(allJsonlFiles, locator));
117
121
  yield* _(Effect.forEach(relevantFiles, (filePath) => copyRelevantFile(sourceDir, destinationDir, filePath)));
118
- yield* _(Console.log(`Synced ${relevantFiles.length} dialog files into .knowledge/.codex`));
119
- });
122
+ yield* _(Console.log(`Codex: copied ${relevantFiles.length} files from ${sourceDir} to ${destinationDir}`));
123
+ }).pipe(Effect.catchAll((error) => Console.log(`Codex source not found; skipped syncing Codex dialog files (${error.reason})`)));
@@ -26,7 +26,7 @@ const copyDirectoryJsonOnly = (sourceRoot, destinationRoot) => Effect.try({
26
26
  catch: () => syncError(sourceRoot, "Cannot traverse Qwen directory"),
27
27
  });
28
28
  const qwenHashFromPath = (projectPath) => createHash("sha256").update(projectPath).digest("hex");
29
- const resolveQwenSourceDir = (cwd, override, metaRoot) => pipe(Effect.sync(() => {
29
+ const resolveQwenSourceDir = (cwd, override, metaRoot) => Effect.gen(function* (_) {
30
30
  const hash = qwenHashFromPath(cwd);
31
31
  const envSource = process.env.QWEN_SOURCE_DIR;
32
32
  const baseFromMeta = metaRoot === undefined
@@ -34,16 +34,33 @@ const resolveQwenSourceDir = (cwd, override, metaRoot) => pipe(Effect.sync(() =>
34
34
  : metaRoot.endsWith(".qwen")
35
35
  ? metaRoot
36
36
  : path.join(metaRoot, ".qwen");
37
+ const metaKnowledge = path.join(metaRoot ?? "", ".knowledge", ".qwen");
37
38
  const homeBase = path.join(os.homedir(), ".qwen");
39
+ const homeKnowledge = path.join(os.homedir(), ".knowledge", ".qwen");
38
40
  const candidates = [
39
41
  override,
40
42
  envSource,
41
43
  baseFromMeta ? path.join(baseFromMeta, "tmp", hash) : undefined,
42
44
  path.join(cwd, ".qwen", "tmp", hash),
45
+ path.join(cwd, ".knowledge", ".qwen", "tmp", hash),
46
+ metaKnowledge ? path.join(metaKnowledge, "tmp", hash) : undefined,
43
47
  path.join(homeBase, "tmp", hash),
44
- ];
45
- return candidates.find((candidate) => candidate !== undefined && fs.existsSync(candidate));
46
- }), Effect.flatMap((found) => found === undefined
47
- ? Effect.fail(syncError(".qwen", "Qwen source directory is missing"))
48
- : Effect.succeed(found)));
49
- export const syncQwen = (options) => pipe(resolveQwenSourceDir(options.cwd, options.qwenSourceDir, options.metaRoot), Effect.flatMap((qwenSource) => pipe(ensureDirectory(path.join(options.cwd, ".knowledge", ".qwen")), Effect.flatMap(() => copyDirectoryJsonOnly(qwenSource, path.join(options.cwd, ".knowledge", ".qwen"))), Effect.flatMap((copiedCount) => Console.log(`Synced ${copiedCount} Qwen dialog files into .knowledge/.qwen`)))), Effect.catchAll(() => Console.log("Qwen source not found; skipped syncing Qwen dialog files")));
48
+ path.join(homeKnowledge, "tmp", hash),
49
+ ].filter((candidate) => candidate !== undefined);
50
+ const found = candidates.find((candidate) => fs.existsSync(candidate));
51
+ if (found === undefined) {
52
+ return yield* _(Effect.fail(syncError(".qwen", `Qwen source directory is missing for hash ${hash}`)));
53
+ }
54
+ return found;
55
+ });
56
+ export const syncQwen = (options) => pipe(resolveQwenSourceDir(options.cwd, options.qwenSourceDir, options.metaRoot), Effect.flatMap((qwenSource) => Effect.gen(function* (_) {
57
+ const destination = path.join(options.cwd, ".knowledge", ".qwen");
58
+ if (path.resolve(qwenSource) === path.resolve(destination)) {
59
+ yield* _(Console.log("Qwen source equals destination; skipping copy to avoid duplicates"));
60
+ return;
61
+ }
62
+ yield* _(ensureDirectory(destination));
63
+ const qwenRoot = path.dirname(path.dirname(qwenSource));
64
+ const copiedCount = yield* _(copyDirectoryJsonOnly(qwenSource, destination));
65
+ yield* _(Console.log(`Qwen: copied ${copiedCount} files from ${qwenRoot} to ${destination}`));
66
+ })), Effect.catchAll((error) => Console.log(`Qwen source not found; skipped syncing Qwen dialog files (${error.reason})`)));
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { pathToFileURL } from "node:url";
3
2
  import { Effect } from "effect";
4
3
  import { syncCodex } from "./codexSync.js";
5
4
  import { syncQwen } from "./qwenSync.js";
@@ -8,14 +7,7 @@ export const buildSyncProgram = (options) => Effect.gen(function* (_) {
8
7
  yield* _(syncCodex(options));
9
8
  yield* _(syncQwen(options));
10
9
  });
11
- const isMainModule = () => {
12
- const entry = process.argv[1];
13
- if (entry === undefined) {
14
- return false;
15
- }
16
- return import.meta.url === pathToFileURL(entry).href;
17
- };
18
- const parseArgs = () => {
10
+ export const parseArgs = () => {
19
11
  const argv = process.argv.slice(2);
20
12
  let result = { cwd: process.cwd() };
21
13
  const mapping = {
@@ -42,7 +34,3 @@ const parseArgs = () => {
42
34
  }
43
35
  return result;
44
36
  };
45
- if (isMainModule()) {
46
- const program = buildSyncProgram(parseArgs());
47
- Effect.runSync(program);
48
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prover-coder-ai/context-doc",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -8,11 +8,11 @@
8
8
  "build": "tsc -p tsconfig.build.json",
9
9
  "lint": "npx --no-install @ton-ai-core/vibecode-linter src/",
10
10
  "test": "npx --no-install @ton-ai-core/vibecode-linter tests/ && vitest run --passWithNoTests",
11
- "sync:knowledge": "tsx src/shell/syncKnowledge.ts",
11
+ "sync:knowledge": "npm run build && PKG=prover-coder-ai-context-doc-$(node -p \"require('./package.json').version\").tgz && rm -f \"$PKG\" && npm pack >/dev/null && npx -y -p \"./$PKG\" context-doc",
12
12
  "release": "npm run build && npm run lint && npm version patch && npm publish --access public"
13
13
  },
14
14
  "bin": {
15
- "context-doc": "dist/shell/syncKnowledge.js"
15
+ "context-doc": "dist/shell/cli.js"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { Effect } from "effect";
3
+ import { buildSyncProgram, parseArgs } from "./syncKnowledge.js";
4
+
5
+ const program = buildSyncProgram(parseArgs());
6
+
7
+ Effect.runSync(program);
@@ -46,8 +46,8 @@ const resolveSourceDir = (
46
46
  override?: string,
47
47
  metaRoot?: string,
48
48
  ): Effect.Effect<string, SyncError> =>
49
- Effect.try({
50
- try: () => {
49
+ pipe(
50
+ Effect.sync(() => {
51
51
  const envSource = process.env.CODEX_SOURCE_DIR;
52
52
  const metaCandidate =
53
53
  metaRoot === undefined
@@ -57,25 +57,34 @@ const resolveSourceDir = (
57
57
  : path.join(metaRoot, ".codex");
58
58
  const localSource = path.join(cwd, ".codex");
59
59
  const homeSource = path.join(os.homedir(), ".codex");
60
+ const localKnowledge = path.join(cwd, ".knowledge", ".codex");
61
+ const homeKnowledge = path.join(os.homedir(), ".knowledge", ".codex");
62
+
60
63
  const candidates = [
61
64
  override,
62
65
  envSource,
63
66
  metaCandidate,
64
67
  localSource,
65
68
  homeSource,
66
- ];
67
- const existing = candidates.find(
68
- (candidate) => candidate !== undefined && fs.existsSync(candidate),
69
- );
70
-
71
- if (existing === undefined) {
72
- throw new Error("source .codex not found");
73
- }
74
-
75
- return existing;
76
- },
77
- catch: () => syncError(".codex", "Source .codex directory is missing"),
78
- });
69
+ localKnowledge,
70
+ homeKnowledge,
71
+ ].filter((candidate): candidate is string => candidate !== undefined);
72
+
73
+ const existing = candidates.find((candidate) => fs.existsSync(candidate));
74
+
75
+ return { existing, candidates };
76
+ }),
77
+ Effect.flatMap(({ existing, candidates }) =>
78
+ existing === undefined
79
+ ? Effect.fail(
80
+ syncError(
81
+ ".codex",
82
+ `Source .codex directory is missing; checked: ${candidates.join(", ")}`,
83
+ ),
84
+ )
85
+ : Effect.succeed(existing),
86
+ ),
87
+ );
79
88
 
80
89
  const collectJsonlFiles = (
81
90
  root: string,
@@ -169,6 +178,15 @@ export const syncCodex = (
169
178
  const destinationDir =
170
179
  options.destinationDir ?? path.join(options.cwd, ".knowledge", ".codex");
171
180
 
181
+ if (path.resolve(sourceDir) === path.resolve(destinationDir)) {
182
+ yield* _(
183
+ Console.log(
184
+ "Codex source equals destination; skipping copy to avoid duplicates",
185
+ ),
186
+ );
187
+ return;
188
+ }
189
+
172
190
  yield* _(ensureDirectory(destinationDir));
173
191
 
174
192
  const locator = buildProjectLocator(repositoryUrl, options.cwd);
@@ -183,7 +201,13 @@ export const syncCodex = (
183
201
 
184
202
  yield* _(
185
203
  Console.log(
186
- `Synced ${relevantFiles.length} dialog files into .knowledge/.codex`,
204
+ `Codex: copied ${relevantFiles.length} files from ${sourceDir} to ${destinationDir}`,
187
205
  ),
188
206
  );
189
- });
207
+ }).pipe(
208
+ Effect.catchAll((error) =>
209
+ Console.log(
210
+ `Codex source not found; skipped syncing Codex dialog files (${error.reason})`,
211
+ ),
212
+ ),
213
+ );
@@ -40,36 +40,45 @@ const resolveQwenSourceDir = (
40
40
  override?: string,
41
41
  metaRoot?: string,
42
42
  ): Effect.Effect<string, SyncError> =>
43
- pipe(
44
- Effect.sync(() => {
45
- const hash = qwenHashFromPath(cwd);
46
- const envSource = process.env.QWEN_SOURCE_DIR;
47
- const baseFromMeta =
48
- metaRoot === undefined
49
- ? undefined
50
- : metaRoot.endsWith(".qwen")
51
- ? metaRoot
52
- : path.join(metaRoot, ".qwen");
53
- const homeBase = path.join(os.homedir(), ".qwen");
43
+ Effect.gen(function* (_) {
44
+ const hash = qwenHashFromPath(cwd);
45
+ const envSource = process.env.QWEN_SOURCE_DIR;
46
+ const baseFromMeta =
47
+ metaRoot === undefined
48
+ ? undefined
49
+ : metaRoot.endsWith(".qwen")
50
+ ? metaRoot
51
+ : path.join(metaRoot, ".qwen");
52
+ const metaKnowledge = path.join(metaRoot ?? "", ".knowledge", ".qwen");
53
+ const homeBase = path.join(os.homedir(), ".qwen");
54
+ const homeKnowledge = path.join(os.homedir(), ".knowledge", ".qwen");
55
+
56
+ const candidates = [
57
+ override,
58
+ envSource,
59
+ baseFromMeta ? path.join(baseFromMeta, "tmp", hash) : undefined,
60
+ path.join(cwd, ".qwen", "tmp", hash),
61
+ path.join(cwd, ".knowledge", ".qwen", "tmp", hash),
62
+ metaKnowledge ? path.join(metaKnowledge, "tmp", hash) : undefined,
63
+ path.join(homeBase, "tmp", hash),
64
+ path.join(homeKnowledge, "tmp", hash),
65
+ ].filter((candidate): candidate is string => candidate !== undefined);
54
66
 
55
- const candidates = [
56
- override,
57
- envSource,
58
- baseFromMeta ? path.join(baseFromMeta, "tmp", hash) : undefined,
59
- path.join(cwd, ".qwen", "tmp", hash),
60
- path.join(homeBase, "tmp", hash),
61
- ];
67
+ const found = candidates.find((candidate) => fs.existsSync(candidate));
62
68
 
63
- return candidates.find(
64
- (candidate) => candidate !== undefined && fs.existsSync(candidate),
69
+ if (found === undefined) {
70
+ return yield* _(
71
+ Effect.fail(
72
+ syncError(
73
+ ".qwen",
74
+ `Qwen source directory is missing for hash ${hash}`,
75
+ ),
76
+ ),
65
77
  );
66
- }),
67
- Effect.flatMap((found) =>
68
- found === undefined
69
- ? Effect.fail(syncError(".qwen", "Qwen source directory is missing"))
70
- : Effect.succeed(found),
71
- ),
72
- );
78
+ }
79
+
80
+ return found;
81
+ });
73
82
 
74
83
  export const syncQwen = (
75
84
  options: SyncOptions,
@@ -77,22 +86,32 @@ export const syncQwen = (
77
86
  pipe(
78
87
  resolveQwenSourceDir(options.cwd, options.qwenSourceDir, options.metaRoot),
79
88
  Effect.flatMap((qwenSource) =>
80
- pipe(
81
- ensureDirectory(path.join(options.cwd, ".knowledge", ".qwen")),
82
- Effect.flatMap(() =>
83
- copyDirectoryJsonOnly(
84
- qwenSource,
85
- path.join(options.cwd, ".knowledge", ".qwen"),
86
- ),
87
- ),
88
- Effect.flatMap((copiedCount) =>
89
+ Effect.gen(function* (_) {
90
+ const destination = path.join(options.cwd, ".knowledge", ".qwen");
91
+ if (path.resolve(qwenSource) === path.resolve(destination)) {
92
+ yield* _(
93
+ Console.log(
94
+ "Qwen source equals destination; skipping copy to avoid duplicates",
95
+ ),
96
+ );
97
+ return;
98
+ }
99
+
100
+ yield* _(ensureDirectory(destination));
101
+ const qwenRoot = path.dirname(path.dirname(qwenSource));
102
+ const copiedCount = yield* _(
103
+ copyDirectoryJsonOnly(qwenSource, destination),
104
+ );
105
+ yield* _(
89
106
  Console.log(
90
- `Synced ${copiedCount} Qwen dialog files into .knowledge/.qwen`,
107
+ `Qwen: copied ${copiedCount} files from ${qwenRoot} to ${destination}`,
91
108
  ),
92
- ),
93
- ),
109
+ );
110
+ }),
94
111
  ),
95
- Effect.catchAll(() =>
96
- Console.log("Qwen source not found; skipped syncing Qwen dialog files"),
112
+ Effect.catchAll((error) =>
113
+ Console.log(
114
+ `Qwen source not found; skipped syncing Qwen dialog files (${error.reason})`,
115
+ ),
97
116
  ),
98
117
  );
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { pathToFileURL } from "node:url";
3
2
  import { Effect } from "effect";
4
3
  import { syncCodex } from "./codexSync.js";
5
4
  import { syncQwen } from "./qwenSync.js";
@@ -14,17 +13,7 @@ export const buildSyncProgram = (
14
13
  yield* _(syncQwen(options));
15
14
  });
16
15
 
17
- const isMainModule = (): boolean => {
18
- const entry = process.argv[1];
19
-
20
- if (entry === undefined) {
21
- return false;
22
- }
23
-
24
- return import.meta.url === pathToFileURL(entry).href;
25
- };
26
-
27
- const parseArgs = (): SyncOptions => {
16
+ export const parseArgs = (): SyncOptions => {
28
17
  const argv = process.argv.slice(2);
29
18
  let result: SyncOptions = { cwd: process.cwd() };
30
19
 
@@ -55,9 +44,3 @@ const parseArgs = (): SyncOptions => {
55
44
 
56
45
  return result;
57
46
  };
58
-
59
- if (isMainModule()) {
60
- const program = buildSyncProgram(parseArgs());
61
-
62
- Effect.runSync(program);
63
- }