@ksm0709/context 0.0.33 → 0.0.35

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.
@@ -20,7 +20,7 @@ function resolveContextDir(projectDir) {
20
20
  // package.json
21
21
  var package_default = {
22
22
  name: "@ksm0709/context",
23
- version: "0.0.33",
23
+ version: "0.0.35",
24
24
  author: {
25
25
  name: "TaehoKang",
26
26
  email: "ksm07091@gmail.com"
@@ -62,24 +62,23 @@ var package_default = {
62
62
  "@opencode-ai/plugin": ">=1.0.0"
63
63
  },
64
64
  dependencies: {
65
- "@ksm0709/context": "^0.0.33",
66
65
  "@modelcontextprotocol/sdk": "^1.27.1",
67
66
  "jsonc-parser": "^3.0.0"
68
67
  },
69
68
  devDependencies: {
70
- "@opencode-ai/plugin": "^1.2.10",
71
69
  "@eslint/js": "^9.39.1",
70
+ "@opencode-ai/plugin": "^1.2.10",
72
71
  "@types/node": "^20.11.5",
73
72
  "@typescript-eslint/eslint-plugin": "8.47.0",
74
73
  "@typescript-eslint/parser": "8.47.0",
74
+ "@vitest/coverage-v8": "^3.2.4",
75
75
  "bun-types": "latest",
76
76
  eslint: "^9.39.1",
77
77
  "eslint-config-prettier": "10.1.8",
78
78
  "eslint-plugin-prettier": "^5.1.3",
79
79
  prettier: "^3.2.4",
80
80
  "typescript-eslint": "^8.47.0",
81
- vitest: "^3.2.4",
82
- "@vitest/coverage-v8": "^3.2.4"
81
+ vitest: "^3.2.4"
83
82
  }
84
83
  };
85
84
 
@@ -482,14 +481,17 @@ var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
482
481
  3. **\uC790\uAE30 \uC5B8\uC5B4** -- \uBCF5\uC0AC-\uBD99\uC5EC\uB123\uAE30\uAC00 \uC544\uB2CC, \uD575\uC2EC\uC744 \uC774\uD574\uD558\uACE0 \uAC04\uACB0\uD558\uAC8C \uC11C\uC220\uD558\uC138\uC694.
483
482
 
484
483
  ### MCP Tools
485
- - **\uC9C0\uC2DD \uAD00\uB9AC**: \`context_mcp_search_knowledge\`, \`context_mcp_read_knowledge\`, \`context_mcp_create_knowledge_note\`, \`context_mcp_update_knowledge_note\`
484
+ - **\uC9C0\uC2DD \uD0D0\uC0C9**: \`context_mcp_search_knowledge\`\uB85C \uD6C4\uBCF4 \uB178\uD2B8\uB97C \uCC3E\uACE0, \uACB0\uACFC\uC758 title / description / tags / path / score\uB97C \uBA3C\uC800 \uBE44\uAD50\uD558\uC138\uC694.
485
+ - **\uB178\uD2B8 \uC5F4\uAE30**: \`context_mcp_read_knowledge\`\uB85C \uC120\uD0DD\uD55C \uB178\uD2B8\uB97C \uC5F4\uACE0, \uB05D\uC5D0 \uBD99\uB294 related notes \uBA54\uD0C0\uB370\uC774\uD130\uB85C \uB2E4\uC74C \uD0D0\uC0C9 \uACBD\uB85C\uB97C \uC815\uD558\uC138\uC694.
486
+ - **\uB178\uD2B8 \uC791\uC131/\uC218\uC815**: \`context_mcp_create_knowledge_note\`, \`context_mcp_update_knowledge_note\`
486
487
  - **\uB370\uC77C\uB9AC \uB178\uD2B8**: \`context_mcp_read_daily_note\`, \`context_mcp_append_daily_note\`
487
488
  - **\uC791\uC5C5 \uC644\uB8CC**: \`context_mcp_submit_turn_complete\` (\uC791\uC5C5 \uC885\uB8CC \uC2DC \uD544\uC218 \uD638\uCD9C)
488
489
 
489
490
  ### \uC791\uC5C5 \uC804 \uD544\uC218
490
491
  - **\uB370\uC77C\uB9AC \uB178\uD2B8 \uD655\uC778**: \uAC00\uC7A5 \uCD5C\uADFC\uC758 \uB370\uC77C\uB9AC \uB178\uD2B8\uB97C \uC77D\uACE0 \uC774\uC804 \uC138\uC158\uC758 \uCEE8\uD14D\uC2A4\uD2B8\uC640 \uBBF8\uD574\uACB0 \uC774\uC288\uB97C \uD30C\uC545\uD558\uC138\uC694.
491
492
  - **\uC791\uC5C5 \uC758\uB3C4 \uC120\uC5B8**: \uC791\uC5C5 \uC2DC\uC791 \uC804, \uD604\uC7AC \uC138\uC158\uC758 \uBAA9\uD45C\uC640 \uC791\uC5C5 \uC758\uB3C4\uB97C \uBA85\uD655\uD788 \uD30C\uC545\uD558\uACE0 \uC120\uC5B8\uD558\uC138\uC694.
492
- - **\uC9C0\uC2DD \uAC80\uC0C9**: \uC791\uC5C5\uACFC \uAD00\uB828\uB41C \uBB38\uC11C\uB97C **\uC9C1\uC811 \uBA3C\uC800** \uAC80\uC0C9\uD558\uACE0 \uC77D\uC73C\uC138\uC694.
493
+ - **\uBA54\uD0C0\uB370\uC774\uD130 \uC6B0\uC120 \uAC80\uC0C9**: \uBA3C\uC800 \`search_knowledge\`\uB85C \uAD00\uB828 \uD6C4\uBCF4\uB97C \uCC3E\uACE0, \uBA54\uD0C0\uB370\uC774\uD130\uB97C \uBE44\uAD50\uD55C \uB4A4 \uAC00\uC7A5 \uC720\uB825\uD55C \uB178\uD2B8\uB97C \`read_knowledge\`\uB85C \uC5EC\uC138\uC694.
494
+ - **\uAD00\uB828 \uB178\uD2B8 \uCD94\uC801**: \`read_knowledge\` \uB05D\uC758 related notes \uC139\uC158\uC5D0\uC11C \uC5F0\uACB0\uB41C \uB178\uD2B8\uC758 title / description / tags / path\uB97C \uD655\uC778\uD558\uACE0 \uD544\uC694\uC2DC \uC5F0\uC1C4 \uD0D0\uC0C9\uD558\uC138\uC694.
493
495
  - \uC9C0\uC2DD \uD30C\uC77C\uC5D0 \uAE30\uB85D\uB41C \uC544\uD0A4\uD14D\uCC98 \uACB0\uC815, \uD328\uD134, \uC81C\uC57D\uC0AC\uD56D\uC744 \uBC18\uB4DC\uC2DC \uB530\uB974\uC138\uC694.
494
496
 
495
497
  ### \uAC1C\uBC1C \uC6D0\uCE59
@@ -1,6 +1,6 @@
1
1
  // src/omx/index.ts
2
- import { existsSync as existsSync6, readFileSync as readFileSync5, unlinkSync } from "node:fs";
3
- import { join as join6 } from "node:path";
2
+ import { existsSync as existsSync7, readFileSync as readFileSync6, unlinkSync } from "node:fs";
3
+ import { join as join7 } from "node:path";
4
4
 
5
5
  // src/constants.ts
6
6
  var DEFAULTS = {
@@ -105,7 +105,7 @@ import { join as join3 } from "node:path";
105
105
  // package.json
106
106
  var package_default = {
107
107
  name: "@ksm0709/context",
108
- version: "0.0.33",
108
+ version: "0.0.35",
109
109
  author: {
110
110
  name: "TaehoKang",
111
111
  email: "ksm07091@gmail.com"
@@ -147,24 +147,23 @@ var package_default = {
147
147
  "@opencode-ai/plugin": ">=1.0.0"
148
148
  },
149
149
  dependencies: {
150
- "@ksm0709/context": "^0.0.33",
151
150
  "@modelcontextprotocol/sdk": "^1.27.1",
152
151
  "jsonc-parser": "^3.0.0"
153
152
  },
154
153
  devDependencies: {
155
- "@opencode-ai/plugin": "^1.2.10",
156
154
  "@eslint/js": "^9.39.1",
155
+ "@opencode-ai/plugin": "^1.2.10",
157
156
  "@types/node": "^20.11.5",
158
157
  "@typescript-eslint/eslint-plugin": "8.47.0",
159
158
  "@typescript-eslint/parser": "8.47.0",
159
+ "@vitest/coverage-v8": "^3.2.4",
160
160
  "bun-types": "latest",
161
161
  eslint: "^9.39.1",
162
162
  "eslint-config-prettier": "10.1.8",
163
163
  "eslint-plugin-prettier": "^5.1.3",
164
164
  prettier: "^3.2.4",
165
165
  "typescript-eslint": "^8.47.0",
166
- vitest: "^3.2.4",
167
- "@vitest/coverage-v8": "^3.2.4"
166
+ vitest: "^3.2.4"
168
167
  }
169
168
  };
170
169
 
@@ -555,6 +554,59 @@ function injectIntoAgentsMd(agentsMdPath, content) {
555
554
  writeFileAtomically(agentsMdPath, nextContent);
556
555
  }
557
556
 
557
+ // src/shared/codex-settings.ts
558
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
559
+ import { homedir } from "node:os";
560
+ import { isAbsolute, join as join4 } from "node:path";
561
+ var STALE_MOCK_MCP_SERVER_NAME = "mock-mcp";
562
+ var codexConfigPath = join4(homedir(), ".codex", "config.toml");
563
+ function findMcpServerBlockRange(lines, serverName) {
564
+ const header = `[mcp_servers.${serverName}]`;
565
+ const start = lines.findIndex((line) => line.trim() === header);
566
+ if (start === -1) {
567
+ return null;
568
+ }
569
+ let end = lines.length;
570
+ for (let index = start + 1;index < lines.length; index += 1) {
571
+ if (lines[index].startsWith("[")) {
572
+ end = index;
573
+ break;
574
+ }
575
+ }
576
+ return { start, end };
577
+ }
578
+ function resolveFirstArgPath(blockLines) {
579
+ for (const line of blockLines) {
580
+ const match = line.match(/^\s*args\s*=\s*\[\s*["']([^"']+)["']/);
581
+ if (!match) {
582
+ continue;
583
+ }
584
+ return match[1];
585
+ }
586
+ return null;
587
+ }
588
+ function pruneStaleMockMcpServer() {
589
+ if (!existsSync4(codexConfigPath)) {
590
+ return false;
591
+ }
592
+ const content = readFileSync4(codexConfigPath, "utf8");
593
+ const lines = content.split(`
594
+ `);
595
+ const blockRange = findMcpServerBlockRange(lines, STALE_MOCK_MCP_SERVER_NAME);
596
+ if (!blockRange) {
597
+ return false;
598
+ }
599
+ const blockLines = lines.slice(blockRange.start, blockRange.end);
600
+ const firstArgPath = resolveFirstArgPath(blockLines);
601
+ if (!firstArgPath || !isAbsolute(firstArgPath) || existsSync4(firstArgPath)) {
602
+ return false;
603
+ }
604
+ const nextLines = [...lines.slice(0, blockRange.start), ...lines.slice(blockRange.end)];
605
+ writeFileSync3(codexConfigPath, nextLines.join(`
606
+ `), "utf8");
607
+ return true;
608
+ }
609
+
558
610
  // src/shared/knowledge-context.ts
559
611
  var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
560
612
 
@@ -567,14 +619,17 @@ var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
567
619
  3. **자기 언어** -- 복사-붙여넣기가 아닌, 핵심을 이해하고 간결하게 서술하세요.
568
620
 
569
621
  ### MCP Tools
570
- - **지식 관리**: \`context_mcp_search_knowledge\`, \`context_mcp_read_knowledge\`, \`context_mcp_create_knowledge_note\`, \`context_mcp_update_knowledge_note\`
622
+ - **지식 탐색**: \`context_mcp_search_knowledge\`로 후보 노트를 찾고, 결과의 title / description / tags / path / score를 먼저 비교하세요.
623
+ - **노트 열기**: \`context_mcp_read_knowledge\`로 선택한 노트를 열고, 끝에 붙는 related notes 메타데이터로 다음 탐색 경로를 정하세요.
624
+ - **노트 작성/수정**: \`context_mcp_create_knowledge_note\`, \`context_mcp_update_knowledge_note\`
571
625
  - **데일리 노트**: \`context_mcp_read_daily_note\`, \`context_mcp_append_daily_note\`
572
626
  - **작업 완료**: \`context_mcp_submit_turn_complete\` (작업 종료 시 필수 호출)
573
627
 
574
628
  ### 작업 전 필수
575
629
  - **데일리 노트 확인**: 가장 최근의 데일리 노트를 읽고 이전 세션의 컨텍스트와 미해결 이슈를 파악하세요.
576
630
  - **작업 의도 선언**: 작업 시작 전, 현재 세션의 목표와 작업 의도를 명확히 파악하고 선언하세요.
577
- - **지식 검색**: 작업과 관련된 문서를 **직접 먼저** 검색하고 읽으세요.
631
+ - **메타데이터 우선 검색**: 먼저 \`search_knowledge\`로 관련 후보를 찾고, 메타데이터를 비교한 뒤 가장 유력한 노트를 \`read_knowledge\`로 여세요.
632
+ - **관련 노트 추적**: \`read_knowledge\` 끝의 related notes 섹션에서 연결된 노트의 title / description / tags / path를 확인하고 필요시 연쇄 탐색하세요.
578
633
  - 지식 파일에 기록된 아키텍처 결정, 패턴, 제약사항을 반드시 따르세요.
579
634
 
580
635
  ### 개발 원칙
@@ -593,32 +648,32 @@ var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
593
648
  - 필요한 인자: daily_note_update_proof, knowledge_note_proof, quality_check_output, checkpoint_commit_hashes, scope_review_notes`;
594
649
 
595
650
  // src/omx/registry.ts
596
- import { join as join5, dirname as dirname3 } from "node:path";
597
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
651
+ import { join as join6, dirname as dirname3 } from "node:path";
652
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "node:fs";
598
653
  import { execSync } from "node:child_process";
599
- import { homedir } from "node:os";
654
+ import { homedir as homedir2 } from "node:os";
600
655
 
601
656
  // src/shared/mcp-path.ts
602
657
  import { fileURLToPath } from "node:url";
603
- import { dirname as dirname2, join as join4, resolve } from "node:path";
604
- import { existsSync as existsSync4 } from "node:fs";
658
+ import { dirname as dirname2, join as join5, resolve } from "node:path";
659
+ import { existsSync as existsSync5 } from "node:fs";
605
660
  import { createRequire } from "node:module";
606
661
  function resolveMcpPath() {
607
662
  try {
608
663
  const req = createRequire(import.meta.url);
609
664
  const pkgJsonPath = req.resolve("@ksm0709/context/package.json");
610
665
  const pkgRoot = dirname2(pkgJsonPath);
611
- const distMcp = join4(pkgRoot, "dist", "mcp.js");
612
- if (existsSync4(distMcp))
666
+ const distMcp = join5(pkgRoot, "dist", "mcp.js");
667
+ if (existsSync5(distMcp))
613
668
  return distMcp;
614
669
  } catch {}
615
670
  const currentFile = fileURLToPath(import.meta.url);
616
671
  const currentDir = dirname2(currentFile);
617
672
  const distMcpPath = resolve(currentDir, "..", "mcp.js");
618
- if (existsSync4(distMcpPath))
673
+ if (existsSync5(distMcpPath))
619
674
  return distMcpPath;
620
675
  const srcMcpPath = resolve(currentDir, "..", "mcp.ts");
621
- if (existsSync4(srcMcpPath))
676
+ if (existsSync5(srcMcpPath))
622
677
  return srcMcpPath;
623
678
  return distMcpPath;
624
679
  }
@@ -633,23 +688,23 @@ function resolveBunPath() {
633
688
  }
634
689
  function getRegistryPaths() {
635
690
  return [
636
- join5(homedir(), ".omx", "mcp-registry.json"),
637
- join5(homedir(), ".omc", "mcp-registry.json")
691
+ join6(homedir2(), ".omx", "mcp-registry.json"),
692
+ join6(homedir2(), ".omc", "mcp-registry.json")
638
693
  ];
639
694
  }
640
695
  function ensureMcpRegistered(sdkLog) {
641
696
  const registryPaths = getRegistryPaths();
642
697
  let targetPath = registryPaths[0];
643
698
  for (const p of registryPaths) {
644
- if (existsSync5(p)) {
699
+ if (existsSync6(p)) {
645
700
  targetPath = p;
646
701
  break;
647
702
  }
648
703
  }
649
704
  let registry = {};
650
- if (existsSync5(targetPath)) {
705
+ if (existsSync6(targetPath)) {
651
706
  try {
652
- const content = readFileSync4(targetPath, "utf-8");
707
+ const content = readFileSync5(targetPath, "utf-8");
653
708
  registry = JSON.parse(content);
654
709
  } catch (e) {
655
710
  if (sdkLog) {
@@ -678,7 +733,7 @@ function ensureMcpRegistered(sdkLog) {
678
733
  if (changed) {
679
734
  try {
680
735
  mkdirSync3(dirname3(targetPath), { recursive: true });
681
- writeFileSync3(targetPath, JSON.stringify(registry, null, 2), "utf-8");
736
+ writeFileSync4(targetPath, JSON.stringify(registry, null, 2), "utf-8");
682
737
  if (sdkLog) {
683
738
  sdkLog(`[INFO] Registered context-mcp in ${targetPath}`);
684
739
  }
@@ -777,8 +832,11 @@ async function logWarn(sdk, message, meta = {}) {
777
832
  }
778
833
  async function onSessionStart(event, sdk) {
779
834
  const projectDir = resolveProjectDir(event);
835
+ if (pruneStaleMockMcpServer()) {
836
+ await sdk.log.info("Removed stale mock-mcp from ~/.codex/config.toml because its target file is missing.");
837
+ }
780
838
  scaffoldIfNeeded(projectDir);
781
- injectIntoAgentsMd(join6(projectDir, "AGENTS.md"), STATIC_KNOWLEDGE_CONTEXT);
839
+ injectIntoAgentsMd(join7(projectDir, "AGENTS.md"), STATIC_KNOWLEDGE_CONTEXT);
782
840
  await sdk.log.info(`Injected context into AGENTS.md for ${projectDir}`);
783
841
  const wasRegistered = ensureMcpRegistered(sdk.log.info);
784
842
  if (wasRegistered) {
@@ -818,9 +876,9 @@ async function onTurnComplete(event, sdk) {
818
876
  }
819
877
  const followupScopeKey = resolveFollowupScopeKey(event);
820
878
  let pendingFollowupScopes = typeof sdk.state?.read === "function" ? await sdk.state.read(TURN_END_PENDING_SKIP_KEY, {}) ?? {} : {};
821
- const workCompleteFile = join6(projectDir, DEFAULTS.workCompleteFile);
822
- if (existsSync6(workCompleteFile)) {
823
- const content = readFileSync5(workCompleteFile, "utf-8");
879
+ const workCompleteFile = join7(projectDir, DEFAULTS.workCompleteFile);
880
+ if (existsSync7(workCompleteFile)) {
881
+ const content = readFileSync6(workCompleteFile, "utf-8");
824
882
  const { sessionId: fileSessionId, turnId: fileTurnId } = parseWorkComplete(content);
825
883
  const currentScopeId = event.session_id ?? event.thread_id ?? "";
826
884
  if (!fileSessionId || fileSessionId === currentScopeId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ksm0709/context",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "author": {
5
5
  "name": "TaehoKang",
6
6
  "email": "ksm07091@gmail.com"
@@ -42,23 +42,22 @@
42
42
  "@opencode-ai/plugin": ">=1.0.0"
43
43
  },
44
44
  "dependencies": {
45
- "@ksm0709/context": "^0.0.33",
46
45
  "@modelcontextprotocol/sdk": "^1.27.1",
47
46
  "jsonc-parser": "^3.0.0"
48
47
  },
49
48
  "devDependencies": {
50
- "@opencode-ai/plugin": "^1.2.10",
51
49
  "@eslint/js": "^9.39.1",
50
+ "@opencode-ai/plugin": "^1.2.10",
52
51
  "@types/node": "^20.11.5",
53
52
  "@typescript-eslint/eslint-plugin": "8.47.0",
54
53
  "@typescript-eslint/parser": "8.47.0",
54
+ "@vitest/coverage-v8": "^3.2.4",
55
55
  "bun-types": "latest",
56
56
  "eslint": "^9.39.1",
57
57
  "eslint-config-prettier": "10.1.8",
58
58
  "eslint-plugin-prettier": "^5.1.3",
59
59
  "prettier": "^3.2.4",
60
60
  "typescript-eslint": "^8.47.0",
61
- "vitest": "^3.2.4",
62
- "@vitest/coverage-v8": "^3.2.4"
61
+ "vitest": "^3.2.4"
63
62
  }
64
63
  }