@ksm0709/context 0.0.25 → 0.0.27

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 CHANGED
@@ -14,7 +14,7 @@ This plugin automatically registers an MCP (Model Context Protocol) server named
14
14
 
15
15
  ## OMX Support
16
16
 
17
- This plugin supports OMX (OpenCode Managed eXtension). See [[docs/omx-setup.md]] for setup instructions.
17
+ This plugin supports OMX (OpenCode Managed eXtension). See [docs/omx-setup.md](docs/omx-setup.md) for setup instructions.
18
18
 
19
19
  ## Installation
20
20
 
package/dist/cli/index.js CHANGED
@@ -27,7 +27,7 @@ function resolveContextDir(projectDir) {
27
27
  // package.json
28
28
  var package_default = {
29
29
  name: "@ksm0709/context",
30
- version: "0.0.25",
30
+ version: "0.0.27",
31
31
  author: {
32
32
  name: "TaehoKang",
33
33
  email: "ksm07091@gmail.com"
@@ -69,7 +69,7 @@ var package_default = {
69
69
  "@opencode-ai/plugin": ">=1.0.0"
70
70
  },
71
71
  dependencies: {
72
- "@ksm0709/context": "^0.0.22",
72
+ "@ksm0709/context": "^0.0.26",
73
73
  "@modelcontextprotocol/sdk": "^1.27.1",
74
74
  "jsonc-parser": "^3.0.0"
75
75
  },
@@ -577,16 +577,88 @@ function updateConfigPaths(contextDir) {
577
577
  }
578
578
 
579
579
  // src/cli/commands/install.ts
580
- import { join as join5, resolve as resolve3, dirname } from "path";
581
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, copyFileSync } from "fs";
582
- import { fileURLToPath } from "url";
580
+ import { join as join6, resolve as resolve4, dirname as dirname2 } from "path";
581
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, copyFileSync } from "fs";
582
+ import { fileURLToPath as fileURLToPath2 } from "url";
583
583
  import { createRequire } from "module";
584
+
585
+ // src/omx/registry.ts
586
+ import { fileURLToPath } from "url";
587
+ import { dirname, join as join5, resolve as resolve3 } from "path";
588
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
589
+ import { homedir as homedir2 } from "os";
590
+ function resolveMcpPath() {
591
+ const currentFile = fileURLToPath(import.meta.url);
592
+ const currentDir = dirname(currentFile);
593
+ const distMcpPath = resolve3(currentDir, "..", "mcp.js");
594
+ if (existsSync5(distMcpPath)) {
595
+ return distMcpPath;
596
+ }
597
+ const srcMcpPath = resolve3(currentDir, "..", "mcp.ts");
598
+ if (existsSync5(srcMcpPath)) {
599
+ return srcMcpPath;
600
+ }
601
+ return distMcpPath;
602
+ }
603
+ function getRegistryPaths() {
604
+ return [
605
+ join5(homedir2(), ".omx", "mcp-registry.json"),
606
+ join5(homedir2(), ".omc", "mcp-registry.json")
607
+ ];
608
+ }
609
+ function ensureMcpRegistered(sdkLog) {
610
+ const registryPaths = getRegistryPaths();
611
+ let targetPath = registryPaths[0];
612
+ for (const p of registryPaths) {
613
+ if (existsSync5(p)) {
614
+ targetPath = p;
615
+ break;
616
+ }
617
+ }
618
+ let registry = {};
619
+ if (existsSync5(targetPath)) {
620
+ try {
621
+ const content = readFileSync3(targetPath, "utf-8");
622
+ registry = JSON.parse(content);
623
+ } catch (e) {
624
+ if (sdkLog) {
625
+ sdkLog(`[ERROR] Failed to parse MCP registry at ${targetPath}: ${e instanceof Error ? e.message : String(e)}`);
626
+ }
627
+ registry = {};
628
+ }
629
+ }
630
+ const mcpPath = resolveMcpPath();
631
+ const expectedConfig = {
632
+ command: "bun",
633
+ args: [mcpPath]
634
+ };
635
+ const currentConfig = registry["context-mcp"];
636
+ if (!currentConfig || currentConfig.command !== expectedConfig.command || !Array.isArray(currentConfig.args) || currentConfig.args[0] !== expectedConfig.args[0]) {
637
+ registry["context-mcp"] = expectedConfig;
638
+ try {
639
+ mkdirSync2(dirname(targetPath), { recursive: true });
640
+ writeFileSync3(targetPath, JSON.stringify(registry, null, 2), "utf-8");
641
+ if (sdkLog) {
642
+ sdkLog(`[INFO] Registered context-mcp in ${targetPath}`);
643
+ }
644
+ return true;
645
+ } catch (e) {
646
+ if (sdkLog) {
647
+ sdkLog(`[ERROR] Failed to write MCP registry to ${targetPath}: ${e instanceof Error ? e.message : String(e)}`);
648
+ }
649
+ return false;
650
+ }
651
+ }
652
+ return false;
653
+ }
654
+
655
+ // src/cli/commands/install.ts
584
656
  function resolveOmxSource() {
585
657
  try {
586
- const cliDir = dirname(fileURLToPath(import.meta.url));
587
- const pkgRoot = resolve3(cliDir, "..", "..");
588
- const source = join5(pkgRoot, "dist", "omx", "index.mjs");
589
- if (existsSync5(source))
658
+ const cliDir = dirname2(fileURLToPath2(import.meta.url));
659
+ const pkgRoot = resolve4(cliDir, "..", "..");
660
+ const source = join6(pkgRoot, "dist", "omx", "index.mjs");
661
+ if (existsSync6(source))
590
662
  return source;
591
663
  } catch {}
592
664
  try {
@@ -597,17 +669,21 @@ function resolveOmxSource() {
597
669
  }
598
670
  }
599
671
  function installOmx(projectDir, sourcePath) {
600
- if (!existsSync5(sourcePath)) {
672
+ if (!existsSync6(sourcePath)) {
601
673
  process.stderr.write(`Could not find OMX plugin source file: ${sourcePath}
602
674
  `);
603
675
  process.exit(1);
604
676
  return;
605
677
  }
606
- const targetDir = join5(projectDir, ".omx", "hooks");
607
- mkdirSync2(targetDir, { recursive: true });
608
- copyFileSync(sourcePath, join5(targetDir, "context.mjs"));
678
+ const targetDir = join6(projectDir, ".omx", "hooks");
679
+ mkdirSync3(targetDir, { recursive: true });
680
+ copyFileSync(sourcePath, join6(targetDir, "context.mjs"));
609
681
  process.stdout.write(`Installed context plugin to .omx/hooks/context.mjs
610
682
  `);
683
+ if (ensureMcpRegistered()) {
684
+ process.stdout.write(`Successfully registered context-mcp in ~/.omx/mcp-registry.json
685
+ `);
686
+ }
611
687
  }
612
688
  function runInstall(args) {
613
689
  const [subcommand] = args;
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ import { join as join2 } from "path";
25
25
  // package.json
26
26
  var package_default = {
27
27
  name: "@ksm0709/context",
28
- version: "0.0.25",
28
+ version: "0.0.27",
29
29
  author: {
30
30
  name: "TaehoKang",
31
31
  email: "ksm07091@gmail.com"
@@ -67,7 +67,7 @@ var package_default = {
67
67
  "@opencode-ai/plugin": ">=1.0.0"
68
68
  },
69
69
  dependencies: {
70
- "@ksm0709/context": "^0.0.22",
70
+ "@ksm0709/context": "^0.0.26",
71
71
  "@modelcontextprotocol/sdk": "^1.27.1",
72
72
  "jsonc-parser": "^3.0.0"
73
73
  },
package/dist/mcp.js CHANGED
@@ -32789,7 +32789,7 @@ Snippet: ${r.snippet}`).join(`
32789
32789
  textToAppend = `
32790
32790
  ` + textToAppend;
32791
32791
  }
32792
- } catch (err) {}
32792
+ } catch {}
32793
32793
  if (!textToAppend.endsWith(`
32794
32794
  `)) {
32795
32795
  textToAppend += `
@@ -32982,7 +32982,7 @@ ${tags.map((t) => ` - ${t}`).join(`
32982
32982
  textToAppend = `
32983
32983
  ` + textToAppend;
32984
32984
  }
32985
- } catch (err) {}
32985
+ } catch {}
32986
32986
  if (!textToAppend.endsWith(`
32987
32987
  `)) {
32988
32988
  textToAppend += `
@@ -33015,37 +33015,43 @@ ${tags.map((t) => ` - ${t}`).join(`
33015
33015
  server.registerTool("submit_turn_complete", {
33016
33016
  description: "Mark the current turn as complete after verifying all required steps",
33017
33017
  inputSchema: {
33018
- daily_note_updated: exports_external.boolean().optional().default(false).describe("\uB370\uC77C\uB9AC \uB178\uD2B8\uC5D0 \uC911\uC694\uD55C \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uAE30\uB85D\uD558\uC5EC \uB2E4\uC74C \uC138\uC158\uC774\uB098 \uC5D0\uC774\uC804\uD2B8 \uD300\uC774 \uCC38\uACE0\uD560 \uC218 \uC788\uB3C4\uB85D \uD558\uC138\uC694. \uAE30\uC874 \uB0B4\uC6A9 \uC218\uC815\uC740 \uBD88\uAC00\uD558\uBA70, \uC0C8\uB85C\uC6B4 \uBA54\uBAA8\uB97C \uCD94\uAC00 \uD558\uB294\uAC83\uB9CC \uAC00\uB2A5\uD569\uB2C8\uB2E4. \uCC38\uACE0 \uAC00\uC774\uB4DC: .context/guides/daily-note-guide.md \uD30C\uC77C\uC744 \uC77D\uACE0 \uC9C0\uCE68\uC744 \uB530\uB974\uC138\uC694. \uC2E4\uC81C\uB85C \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD574 \uB178\uD2B8\uB97C \uC791\uC131\uD588\uAC70\uB098 \uAC80\uC99D\uC744 \uC218\uD589\uD55C \uACBD\uC6B0\uC5D0\uB9CC true\uB85C \uC124\uC815\uD558\uC138\uC694. \uAC70\uC9D3\uC73C\uB85C true\uB97C \uC785\uB825\uD558\uC9C0 \uB9C8\uC138\uC694. (Set to true ONLY if you actually performed this action. Do not fake it.)"),
33019
- knowledge_note_created: exports_external.boolean().optional().default(false).describe("\uC791\uC5C5\uAE30\uC5B5(\uB370\uC77C\uB9AC\uB178\uD2B8, \uC138\uC158 \uCEE8\uD14D\uC2A4\uD2B8)\uBCF4\uB2E4 \uC624\uB798 \uAE30\uC5B5\uB418\uC5B4\uC57C \uD558\uB294 \uC911\uC694\uD55C \uACB0\uC815, \uD328\uD134, \uC2E4\uC218, \uBC1C\uACAC\uC740 \uC9C0\uC2DD \uB178\uD2B8\uB85C \uAE30\uB85D\uD558\uC5EC \uD504\uB85C\uC81D\uD2B8\uC758 \uC9D1\uB2E8 \uC9C0\uC2DD\uC73C\uB85C \uB0A8\uAE30\uC138\uC694. \uCC38\uACE0 \uAC00\uC774\uB4DC: .context/guides/note-guide.md \uD30C\uC77C\uC744 \uC77D\uACE0 \uC9C0\uCE68\uC744 \uB530\uB974\uC138\uC694. \uC2E4\uC81C\uB85C \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD574 \uB178\uD2B8\uB97C \uC791\uC131\uD588\uAC70\uB098 \uAC80\uC99D\uC744 \uC218\uD589\uD55C \uACBD\uC6B0\uC5D0\uB9CC true\uB85C \uC124\uC815\uD558\uC138\uC694. \uAC70\uC9D3\uC73C\uB85C true\uB97C \uC785\uB825\uD558\uC9C0 \uB9C8\uC138\uC694. (Set to true ONLY if you actually performed this action. Do not fake it.)"),
33020
- quality_check_passed: exports_external.boolean().describe("\uC791\uC5C5 \uC644\uB8CC \uC804\uC5D0 \uBC18\uB4DC\uC2DC \uC218\uD589\uD558\uC138\uC694. \uCF54\uB4DC \uB9B0\uD2B8, \uD3EC\uB9F7\uD130, \uD14C\uC2A4\uD2B8, \uBE4C\uB4DC, \uCF54\uB4DC\uB9AC\uBDF0\uB97C \uC2E4\uD589\uD558\uC5EC \uC791\uC5C5 \uACB0\uACFC\uBB3C\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uD488\uC9C8 \uAE30\uC900\uC744 \uCDA9\uC871\uD558\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694. \uCC38\uACE0 \uAC00\uC774\uB4DC: .context/guides/quality-check.md \uD30C\uC77C\uC744 \uC77D\uACE0 \uC9C0\uCE68\uC744 \uB530\uB974\uC138\uC694. \uC2E4\uC81C\uB85C \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD574 \uB178\uD2B8\uB97C \uC791\uC131\uD588\uAC70\uB098 \uAC80\uC99D\uC744 \uC218\uD589\uD55C \uACBD\uC6B0\uC5D0\uB9CC true\uB85C \uC124\uC815\uD558\uC138\uC694. \uAC70\uC9D3\uC73C\uB85C true\uB97C \uC785\uB825\uD558\uC9C0 \uB9C8\uC138\uC694. (Set to true ONLY if you actually performed this action. Do not fake it.)"),
33021
- checkpoints_committed: exports_external.boolean().describe("\uC791\uC5C5\uC774 \uAE38\uC5B4\uC9C8 \uACBD\uC6B0, \uC911\uC694\uD55C \uB2E8\uACC4\uB9C8\uB2E4 \uCCB4\uD06C\uD3EC\uC778\uD2B8 \uCEE4\uBC0B\uC744 \uD558\uC5EC \uC791\uC5C5 \uB0B4\uC6A9\uC744 \uC548\uC804\uD558\uAC8C \uC800\uC7A5\uD558\uACE0, \uD544\uC694 \uC2DC \uC774\uC804 \uC0C1\uD0DC\uB85C \uB3CC\uC544\uAC08 \uC218 \uC788\uB3C4\uB85D \uD558\uC138\uC694. \uCC38\uACE0 \uAC00\uC774\uB4DC: .context/guides/commit-guide.md \uD30C\uC77C\uC744 \uC77D\uACE0 \uC9C0\uCE68\uC744 \uB530\uB974\uC138\uC694. \uC2E4\uC81C\uB85C \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD574 \uB178\uD2B8\uB97C \uC791\uC131\uD588\uAC70\uB098 \uAC80\uC99D\uC744 \uC218\uD589\uD55C \uACBD\uC6B0\uC5D0\uB9CC true\uB85C \uC124\uC815\uD558\uC138\uC694. \uAC70\uC9D3\uC73C\uB85C true\uB97C \uC785\uB825\uD558\uC9C0 \uB9C8\uC138\uC694. (Set to true ONLY if you actually performed this action. Do not fake it.)"),
33022
- scope_reviewed: exports_external.boolean().describe("\uC0AC\uC6A9\uC790\uAC00 \uC758\uB3C4\uD55C \uC791\uC5C5 \uBC94\uC704\uB97C \uBC97\uC5B4\uB098\uC9C0 \uC54A\uC558\uB294\uC9C0, \uC791\uC5C5\uC774 \uB108\uBB34 \uD06C\uAC70\uB098 \uBCF5\uC7A1\uD574\uC9C0\uC9C0\uB294 \uC54A\uC558\uB294\uC9C0 \uAC80\uD1A0\uD558\uC138\uC694. \uCC38\uACE0 \uAC00\uC774\uB4DC: .context/guides/scope-review.md \uD30C\uC77C\uC744 \uC77D\uACE0 \uC9C0\uCE68\uC744 \uB530\uB974\uC138\uC694. \uC2E4\uC81C\uB85C \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD574 \uB178\uD2B8\uB97C \uC791\uC131\uD588\uAC70\uB098 \uAC80\uC99D\uC744 \uC218\uD589\uD55C \uACBD\uC6B0\uC5D0\uB9CC true\uB85C \uC124\uC815\uD558\uC138\uC694. \uAC70\uC9D3\uC73C\uB85C true\uB97C \uC785\uB825\uD558\uC9C0 \uB9C8\uC138\uC694. (Set to true ONLY if you actually performed this action. Do not fake it.)")
33018
+ daily_note_update_proof: exports_external.string().min(5).optional().describe("Provide the file path of the updated daily note, or explicitly write 'skipped' if no update was needed."),
33019
+ knowledge_note_proof: exports_external.string().min(5).optional().describe("Provide the file path of the created knowledge note, or explicitly write 'skipped' if no note was created."),
33020
+ quality_check_output: exports_external.string().min(20).describe("Provide the last 5 lines of the `mise run lint && mise run test` execution output to prove quality checks passed."),
33021
+ checkpoint_commit_hashes: exports_external.string().min(7).describe("Provide the output of `git log -1 --oneline` or an explanation if the task was too small for checkpoints."),
33022
+ scope_review_notes: exports_external.string().min(10).describe("Provide a brief sentence confirming the scope check and that the work did not exceed the intended boundaries.")
33023
33023
  }
33024
33024
  }, async ({
33025
- daily_note_updated = false,
33026
- knowledge_note_created = false,
33027
- quality_check_passed,
33028
- checkpoints_committed,
33029
- scope_reviewed
33025
+ daily_note_update_proof,
33026
+ knowledge_note_proof,
33027
+ quality_check_output,
33028
+ checkpoint_commit_hashes,
33029
+ scope_review_notes
33030
33030
  }) => {
33031
33031
  const missingSteps = [];
33032
33032
  const warnings = [];
33033
- if (daily_note_updated === false)
33033
+ if (!daily_note_update_proof || daily_note_update_proof.toLowerCase() === "skipped") {
33034
33034
  warnings.push("Warning: Daily note was skipped. This is allowed, but ensure no important context is lost.");
33035
- if (knowledge_note_created === false)
33035
+ } else if (daily_note_update_proof.length < 5) {
33036
+ missingSteps.push("daily_note_update_proof (too short)");
33037
+ }
33038
+ if (!knowledge_note_proof || knowledge_note_proof.toLowerCase() === "skipped") {
33036
33039
  warnings.push("Warning: Knowledge note was skipped. This is allowed, but ensure no important context is lost.");
33037
- if (!quality_check_passed)
33038
- missingSteps.push("quality_check_passed");
33039
- if (!checkpoints_committed)
33040
- missingSteps.push("checkpoints_committed");
33041
- if (!scope_reviewed)
33042
- missingSteps.push("scope_reviewed");
33040
+ } else if (knowledge_note_proof.length < 5) {
33041
+ missingSteps.push("knowledge_note_proof (too short)");
33042
+ }
33043
+ if (!quality_check_output || quality_check_output.length < 20)
33044
+ missingSteps.push("quality_check_output");
33045
+ if (!checkpoint_commit_hashes || checkpoint_commit_hashes.length < 7)
33046
+ missingSteps.push("checkpoint_commit_hashes");
33047
+ if (!scope_review_notes || scope_review_notes.length < 10)
33048
+ missingSteps.push("scope_review_notes");
33043
33049
  if (missingSteps.length > 0) {
33044
33050
  return {
33045
33051
  content: [
33046
33052
  {
33047
33053
  type: "text",
33048
- text: `Error: The following required steps were not completed: ${missingSteps.join(", ")}. You must complete all steps before finishing the turn.`
33054
+ text: `Error: The following required steps were not completed or provided insufficient proof: ${missingSteps.join(", ")}. You must provide valid proof for all steps before finishing the turn.`
33049
33055
  }
33050
33056
  ],
33051
33057
  isError: true
@@ -1,6 +1,6 @@
1
1
  // src/omx/index.ts
2
- import { existsSync as existsSync4, readFileSync as readFileSync4, unlinkSync } from "node:fs";
3
- import { join as join4 } from "node:path";
2
+ import { existsSync as existsSync5, readFileSync as readFileSync5, unlinkSync } from "node:fs";
3
+ import { join as join5 } from "node:path";
4
4
 
5
5
  // src/constants.ts
6
6
  var DEFAULTS = {
@@ -95,7 +95,7 @@ import { join as join3 } from "node:path";
95
95
  // package.json
96
96
  var package_default = {
97
97
  name: "@ksm0709/context",
98
- version: "0.0.25",
98
+ version: "0.0.27",
99
99
  author: {
100
100
  name: "TaehoKang",
101
101
  email: "ksm07091@gmail.com"
@@ -137,7 +137,7 @@ var package_default = {
137
137
  "@opencode-ai/plugin": ">=1.0.0"
138
138
  },
139
139
  dependencies: {
140
- "@ksm0709/context": "^0.0.22",
140
+ "@ksm0709/context": "^0.0.26",
141
141
  "@modelcontextprotocol/sdk": "^1.27.1",
142
142
  "jsonc-parser": "^3.0.0"
143
143
  },
@@ -545,6 +545,76 @@ function injectIntoAgentsMd(agentsMdPath, content) {
545
545
  writeFileAtomically(agentsMdPath, nextContent);
546
546
  }
547
547
 
548
+ // src/omx/registry.ts
549
+ import { fileURLToPath } from "node:url";
550
+ import { dirname as dirname2, join as join4, resolve } from "node:path";
551
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
552
+ import { homedir } from "node:os";
553
+ function resolveMcpPath() {
554
+ const currentFile = fileURLToPath(import.meta.url);
555
+ const currentDir = dirname2(currentFile);
556
+ const distMcpPath = resolve(currentDir, "..", "mcp.js");
557
+ if (existsSync4(distMcpPath)) {
558
+ return distMcpPath;
559
+ }
560
+ const srcMcpPath = resolve(currentDir, "..", "mcp.ts");
561
+ if (existsSync4(srcMcpPath)) {
562
+ return srcMcpPath;
563
+ }
564
+ return distMcpPath;
565
+ }
566
+ function getRegistryPaths() {
567
+ return [
568
+ join4(homedir(), ".omx", "mcp-registry.json"),
569
+ join4(homedir(), ".omc", "mcp-registry.json")
570
+ ];
571
+ }
572
+ function ensureMcpRegistered(sdkLog) {
573
+ const registryPaths = getRegistryPaths();
574
+ let targetPath = registryPaths[0];
575
+ for (const p of registryPaths) {
576
+ if (existsSync4(p)) {
577
+ targetPath = p;
578
+ break;
579
+ }
580
+ }
581
+ let registry = {};
582
+ if (existsSync4(targetPath)) {
583
+ try {
584
+ const content = readFileSync4(targetPath, "utf-8");
585
+ registry = JSON.parse(content);
586
+ } catch (e) {
587
+ if (sdkLog) {
588
+ sdkLog(`[ERROR] Failed to parse MCP registry at ${targetPath}: ${e instanceof Error ? e.message : String(e)}`);
589
+ }
590
+ registry = {};
591
+ }
592
+ }
593
+ const mcpPath = resolveMcpPath();
594
+ const expectedConfig = {
595
+ command: "bun",
596
+ args: [mcpPath]
597
+ };
598
+ const currentConfig = registry["context-mcp"];
599
+ if (!currentConfig || currentConfig.command !== expectedConfig.command || !Array.isArray(currentConfig.args) || currentConfig.args[0] !== expectedConfig.args[0]) {
600
+ registry["context-mcp"] = expectedConfig;
601
+ try {
602
+ mkdirSync3(dirname2(targetPath), { recursive: true });
603
+ writeFileSync3(targetPath, JSON.stringify(registry, null, 2), "utf-8");
604
+ if (sdkLog) {
605
+ sdkLog(`[INFO] Registered context-mcp in ${targetPath}`);
606
+ }
607
+ return true;
608
+ } catch (e) {
609
+ if (sdkLog) {
610
+ sdkLog(`[ERROR] Failed to write MCP registry to ${targetPath}: ${e instanceof Error ? e.message : String(e)}`);
611
+ }
612
+ return false;
613
+ }
614
+ }
615
+ return false;
616
+ }
617
+
548
618
  // src/omx/tmux-submit.ts
549
619
  import { spawnSync } from "node:child_process";
550
620
  function runTmux(args) {
@@ -561,7 +631,7 @@ function runTmux(args) {
561
631
  return { ok: true };
562
632
  }
563
633
  function sleep(ms) {
564
- return new Promise((resolve) => globalThis.setTimeout(resolve, ms));
634
+ return new Promise((resolve2) => globalThis.setTimeout(resolve2, ms));
565
635
  }
566
636
  async function sendTmuxSubmitSequence(target, attempts = 3) {
567
637
  const totalAttempts = Math.max(1, Math.floor(attempts));
@@ -660,8 +730,21 @@ var STATIC_KNOWLEDGE_CONTEXT = `## Knowledge Context
660
730
  async function onSessionStart(event, sdk) {
661
731
  const projectDir = resolveProjectDir(event);
662
732
  scaffoldIfNeeded(projectDir);
663
- injectIntoAgentsMd(join4(projectDir, "AGENTS.md"), STATIC_KNOWLEDGE_CONTEXT);
733
+ injectIntoAgentsMd(join5(projectDir, "AGENTS.md"), STATIC_KNOWLEDGE_CONTEXT);
664
734
  await sdk.log.info(`Injected context into AGENTS.md for ${projectDir}`);
735
+ const wasRegistered = ensureMcpRegistered(sdk.log.info);
736
+ if (wasRegistered) {
737
+ const warningMsg = "Context MCP was just added to your OMX registry. You must stop this session, run 'omx setup', and restart to use MCP tools.";
738
+ await sdk.log.info(warningMsg);
739
+ if (typeof sdk.tmux?.sendKeys === "function") {
740
+ const sessionName = typeof event.context?.session_name === "string" && event.context.session_name.trim().length > 0 ? event.context.session_name.trim() : undefined;
741
+ await sdk.tmux.sendKeys({
742
+ sessionName,
743
+ text: `# WARNING: ${warningMsg}`,
744
+ submit: true
745
+ });
746
+ }
747
+ }
665
748
  }
666
749
  async function onTurnComplete(event, sdk) {
667
750
  const projectDir = resolveProjectDir(event);
@@ -687,9 +770,9 @@ async function onTurnComplete(event, sdk) {
687
770
  }
688
771
  const followupScopeKey = resolveFollowupScopeKey(event);
689
772
  let pendingFollowupScopes = typeof sdk.state?.read === "function" ? await sdk.state.read(TURN_END_PENDING_SKIP_KEY, {}) ?? {} : {};
690
- const workCompleteFile = join4(projectDir, DEFAULTS.workCompleteFile);
691
- if (existsSync4(workCompleteFile)) {
692
- const content = readFileSync4(workCompleteFile, "utf-8");
773
+ const workCompleteFile = join5(projectDir, DEFAULTS.workCompleteFile);
774
+ if (existsSync5(workCompleteFile)) {
775
+ const content = readFileSync5(workCompleteFile, "utf-8");
693
776
  const { sessionId: fileSessionId, turnId: fileTurnId } = parseWorkComplete(content);
694
777
  const currentScopeId = event.session_id ?? event.thread_id ?? "";
695
778
  if (!fileSessionId || fileSessionId === currentScopeId) {
@@ -755,7 +838,7 @@ async function onTurnComplete(event, sdk) {
755
838
  ${turnEnd}
756
839
  </system-reminder>`;
757
840
  const sessionName = typeof event.context?.session_name === "string" && event.context.session_name.trim().length > 0 ? event.context.session_name.trim() : undefined;
758
- await new Promise((resolve) => globalThis.setTimeout(resolve, 500));
841
+ await new Promise((resolve2) => globalThis.setTimeout(resolve2, 500));
759
842
  if (typeof sdk.tmux?.sendKeys === "function") {}
760
843
  const result = await sdk.tmux.sendKeys({
761
844
  sessionName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ksm0709/context",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "author": {
5
5
  "name": "TaehoKang",
6
6
  "email": "ksm07091@gmail.com"
@@ -42,7 +42,7 @@
42
42
  "@opencode-ai/plugin": ">=1.0.0"
43
43
  },
44
44
  "dependencies": {
45
- "@ksm0709/context": "^0.0.22",
45
+ "@ksm0709/context": "^0.0.26",
46
46
  "@modelcontextprotocol/sdk": "^1.27.1",
47
47
  "jsonc-parser": "^3.0.0"
48
48
  },