kojee-mcp 0.7.1 → 0.7.3

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 (32) hide show
  1. package/dist/{chunk-KPMD72FY.js → chunk-6XWTUDWW.js} +65 -26
  2. package/dist/{chunk-GNLCUJBK.js → chunk-A4IOKD4Z.js} +100 -2
  3. package/dist/{chunk-FBJCPRVH.js → chunk-ABECLEYE.js} +62 -11
  4. package/dist/{chunk-SSW5AQSR.js → chunk-FJUAMJHU.js} +3 -6
  5. package/dist/{chunk-FSKGQ6GT.js → chunk-HI42GBQ3.js} +5 -0
  6. package/dist/chunk-IZN7IZPW.js +132 -0
  7. package/dist/{chunk-UPJV7GBE.js → chunk-TCWIXG5C.js} +1 -1
  8. package/dist/{chunk-QJFMU4QC.js → chunk-TMCNB4JH.js} +1 -1
  9. package/dist/chunk-XLRF5ATG.js +103 -0
  10. package/dist/{chunk-UFHGZUST.js → chunk-XPIW4N55.js} +22 -14
  11. package/dist/cli.js +23 -14
  12. package/dist/codex-prompt-submit-hook-J5PZEJSK.js +39 -0
  13. package/dist/codex-stop-hook-32W4BIOM.js +136 -0
  14. package/dist/{connect-handler-4DRTFMOB.js → connect-handler-NZINEMG3.js} +14 -7
  15. package/dist/{doctor-5QJ3HGNR.js → doctor-WUU5BVPT.js} +2 -2
  16. package/dist/doctor-codex-PJFWIABF.js +370 -0
  17. package/dist/{event-stream-KRYWEYWO.js → event-stream-WPN3EN7C.js} +5 -1
  18. package/dist/index.js +5 -5
  19. package/dist/{install-V7LSQCYZ.js → install-JQNDGAAQ.js} +14 -2
  20. package/dist/lib.d.ts +40 -15
  21. package/dist/lib.js +7 -7
  22. package/dist/pending-state-6TVRR63P.js +134 -0
  23. package/dist/{registry-ZZZ26WGA.js → registry-2QS42EQF.js} +114 -51
  24. package/dist/{server-ITPFQVTK.js → server-DU3LFS32.js} +4 -2
  25. package/dist/{setup-handler-JFM45NCN.js → setup-handler-44ASXYMS.js} +7 -7
  26. package/dist/{stop-hook-5ABGTC2O.js → stop-hook-N6TX4YQT.js} +2 -2
  27. package/dist/{tail-stream-NBGHHBS4.js → tail-stream-N43D53RC.js} +99 -19
  28. package/package.json +1 -1
  29. package/skills/using-tandems/SKILL.md +2 -2
  30. package/dist/chunk-EBYUJM3H.js +0 -14
  31. package/dist/codex-stop-hook-BMOJVM6O.js +0 -96
  32. package/dist/doctor-codex-VGJKTX2E.js +0 -163
@@ -1,96 +0,0 @@
1
- import {
2
- readHookStdin
3
- } from "./chunk-LSUB6QMP.js";
4
- import {
5
- codexPendingAckPath,
6
- codexPendingMarkerPath
7
- } from "./chunk-EBYUJM3H.js";
8
- import {
9
- buildCodexWakeReason
10
- } from "./chunk-SSW5AQSR.js";
11
-
12
- // src/hooks/codex-stop-hook.ts
13
- import fs from "fs";
14
- import path from "path";
15
- var CODEX_PEEK_MS = clampPeekMs(
16
- Number.parseInt(process.env["KOJEE_CODEX_PEEK_MS"] ?? "150", 10)
17
- );
18
- function clampPeekMs(raw) {
19
- if (!Number.isFinite(raw) || raw <= 0) return 150;
20
- return Math.min(raw, 500);
21
- }
22
- function decideCodexStopHook(deps) {
23
- if (deps.stopHookActive) return "{}";
24
- const peek = deps.peekPending();
25
- if (!peek.pending || peek.cursor === null) return "{}";
26
- return JSON.stringify({
27
- decision: "block",
28
- reason: buildCodexWakeReason(peek.cursor)
29
- });
30
- }
31
- function defaultPeekPending() {
32
- let body;
33
- try {
34
- body = fs.readFileSync(codexPendingMarkerPath(), "utf8").trim();
35
- } catch {
36
- return { pending: false, cursor: null };
37
- }
38
- let acked = null;
39
- try {
40
- acked = fs.readFileSync(codexPendingAckPath(), "utf8").trim();
41
- } catch {
42
- acked = null;
43
- }
44
- if (acked !== null && body === acked) return { pending: false, cursor: null };
45
- const n = Number.parseInt(body.split(/\s+/)[0] ?? "", 10);
46
- const cursor = Number.isFinite(n) && n >= 0 ? n : 0;
47
- return { pending: true, cursor, markerToken: body };
48
- }
49
- var MAX_ACK_BODY_CHARS = 128;
50
- function writeCodexPendingAck(markerToken) {
51
- const ackPath = codexPendingAckPath();
52
- const tmp = `${ackPath}.tmp-${process.pid}`;
53
- try {
54
- fs.mkdirSync(path.dirname(ackPath), { recursive: true });
55
- fs.writeFileSync(tmp, markerToken.slice(0, MAX_ACK_BODY_CHARS), { mode: 384 });
56
- fs.renameSync(tmp, ackPath);
57
- } catch {
58
- try {
59
- fs.unlinkSync(tmp);
60
- } catch {
61
- }
62
- }
63
- }
64
- function peekDecideAndAck(stopHookActive) {
65
- let peeked = { pending: false, cursor: null };
66
- const out = decideCodexStopHook({
67
- stopHookActive,
68
- peekPending: () => {
69
- try {
70
- peeked = defaultPeekPending();
71
- } catch {
72
- peeked = { pending: false, cursor: null };
73
- }
74
- return peeked;
75
- }
76
- });
77
- if (!stopHookActive && peeked.pending && peeked.markerToken !== void 0) {
78
- writeCodexPendingAck(peeked.markerToken);
79
- }
80
- return out;
81
- }
82
- async function runCodexStopHook() {
83
- const { stopHookActive } = await readHookStdin();
84
- process.stdout.write(peekDecideAndAck(stopHookActive));
85
- }
86
- var CODEX_PEEK_BUDGET_MS = CODEX_PEEK_MS;
87
- export {
88
- CODEX_PEEK_BUDGET_MS,
89
- codexPendingAckPath,
90
- codexPendingMarkerPath,
91
- decideCodexStopHook,
92
- defaultPeekPending,
93
- peekDecideAndAck,
94
- runCodexStopHook,
95
- writeCodexPendingAck
96
- };
@@ -1,163 +0,0 @@
1
- import {
2
- defaultCodexConfigPath,
3
- defaultCodexHooksPath,
4
- isPlaceholderWebhookUrl
5
- } from "./chunk-KPMD72FY.js";
6
- import "./chunk-QJFMU4QC.js";
7
- import "./chunk-D6JKFJ6A.js";
8
- import "./chunk-SQL56SEB.js";
9
- import {
10
- resolveWebhookConfig
11
- } from "./chunk-V5VZPYMZ.js";
12
- import "./chunk-U5HHHRXA.js";
13
- import {
14
- CODEX_LISTEN_CAP_MS
15
- } from "./chunk-SSW5AQSR.js";
16
-
17
- // src/doctor-codex.ts
18
- import fs from "fs";
19
- function parseCodexEnvFromToml(toml) {
20
- const env = {};
21
- let inEnv = false;
22
- for (const line of toml.split("\n")) {
23
- const header = line.trim();
24
- const isTableHeader = /^\[\[?[^\]]+\]\]?$/.test(header);
25
- if (isTableHeader) {
26
- inEnv = header === "[mcp_servers.kojee.env]";
27
- continue;
28
- }
29
- if (!inEnv) continue;
30
- const eq = line.indexOf("=");
31
- if (eq <= 0) continue;
32
- const key = line.slice(0, eq).trim();
33
- if (!/^[A-Za-z0-9_.-]+$/.test(key)) continue;
34
- let value = line.slice(eq + 1).trim();
35
- const quote = value[0];
36
- if ((quote === '"' || quote === "'") && value.endsWith(quote)) {
37
- value = value.slice(1, -1);
38
- if (quote === '"') value = value.replace(/\\"/g, '"').replace(/\\\\/g, "\\");
39
- }
40
- env[key] = value;
41
- }
42
- return env;
43
- }
44
- var WIZARD_RERUN = "re-run `kojee-mcp init --runtime codex`";
45
- function extractPairedConfigPath(toml) {
46
- const m = toml.match(/args\s*=\s*\[[^\]]*"--paired-config"\s*,\s*"([^"]+)"/);
47
- return m ? m[1].replace(/\\\\/g, "\\") : null;
48
- }
49
- function defaultReadFile(path) {
50
- return () => {
51
- try {
52
- return fs.readFileSync(path, "utf8");
53
- } catch {
54
- return null;
55
- }
56
- };
57
- }
58
- function collectCodexDoctorReport(deps = {}) {
59
- const readConfigToml = deps.readConfigToml ?? defaultReadFile(defaultCodexConfigPath());
60
- const readHooksJson = deps.readHooksJson ?? defaultReadFile(defaultCodexHooksPath());
61
- const checks = [];
62
- const toml = readConfigToml() ?? "";
63
- const env = deps.env ?? parseCodexEnvFromToml(toml);
64
- const hasKojeeTable = toml.includes("[mcp_servers.kojee]");
65
- const hasRuntimeEnv = /KOJEE_RUNTIME\s*=\s*"codex"/.test(toml);
66
- const configOk = hasKojeeTable && hasRuntimeEnv;
67
- checks.push({
68
- name: "~/.codex/config.toml [mcp_servers.kojee]",
69
- ok: configOk,
70
- detail: configOk ? 'present with env.KOJEE_RUNTIME="codex" (Tier-1 contract)' : `MISSING [mcp_servers.kojee] or env.KOJEE_RUNTIME="codex" \u2014 ${WIZARD_RERUN}`
71
- });
72
- const hooksRaw = readHooksJson() ?? "{}";
73
- let hookPresent = false;
74
- try {
75
- const hooks = JSON.parse(hooksRaw);
76
- hookPresent = !!hooks.hooks?.Stop?.some(
77
- (e) => e.hooks?.some((h) => (h.command ?? "").includes("hook --type=codex-stop"))
78
- );
79
- } catch {
80
- }
81
- if (!hookPresent && /hook --type=codex-stop/.test(toml)) hookPresent = true;
82
- checks.push({
83
- name: "Codex Stop hook (codex-stop)",
84
- ok: hookPresent,
85
- detail: hookPresent ? "present (fast PEEK + model-chosen bounded listen)" : `MISSING in ~/.codex/hooks.json / [[hooks.Stop]] \u2014 ${WIZARD_RERUN}`
86
- });
87
- const resolution = resolveWebhookConfig(env);
88
- if (resolution.enabled && resolution.config) {
89
- checks.push({
90
- name: "webhook sink",
91
- ok: true,
92
- detail: `enabled \u2014 ${resolution.config.redactedSummary}`
93
- });
94
- if (resolution.warning) {
95
- checks.push({
96
- name: "webhook signature config",
97
- ok: "warn",
98
- detail: `${resolution.warning} \u2014 ${WIZARD_RERUN} with valid signature flags`
99
- });
100
- }
101
- } else if (resolution.error) {
102
- checks.push({
103
- name: "webhook sink",
104
- ok: false,
105
- detail: `${resolution.error} \u2014 ${WIZARD_RERUN} (it generates a secret)`
106
- });
107
- } else {
108
- checks.push({
109
- name: "webhook sink",
110
- ok: true,
111
- detail: "optional \u2014 OFF (no KOJEE_WEBHOOK_URL). Codex wake is self-contained: the proxy refreshes the stop-hook pending marker on every event. Configure a receiver only for an extra low-latency push path."
112
- });
113
- }
114
- const configuredUrl = (env["KOJEE_WEBHOOK_URL"] ?? "").trim();
115
- if (configuredUrl && isPlaceholderWebhookUrl(configuredUrl)) {
116
- checks.push({
117
- name: "webhook url placeholder",
118
- ok: "warn",
119
- detail: `KOJEE_WEBHOOK_URL is the legacy placeholder (${configuredUrl}) \u2014 the sink POSTs every event at a non-resolving host. Re-run \`kojee-mcp connect <code> --runtime codex\` (it scrubs the placeholder), or delete KOJEE_WEBHOOK_URL + KOJEE_WEBHOOK_SECRET from [mcp_servers.kojee.env]. Codex wake is self-contained and unaffected.`
120
- });
121
- }
122
- const pairedPath = extractPairedConfigPath(toml);
123
- if (pairedPath) {
124
- const present = fs.existsSync(pairedPath);
125
- checks.push({
126
- name: "paired-config slot",
127
- ok: present,
128
- detail: present ? `present \u2014 proxy launches with --paired-config ${pairedPath}` : `MISSING referenced config ${pairedPath} \u2014 re-run \`kojee-mcp connect <code> --runtime codex\``
129
- });
130
- }
131
- if (deps.pingReceiver) {
132
- const reachable = deps.pingReceiver();
133
- checks.push({
134
- name: "webhook receiver (optional ping)",
135
- ok: reachable ? true : "warn",
136
- detail: reachable ? "reachable" : "unreachable \u2014 stand up your receiver at KOJEE_WEBHOOK_URL (owner-built; see doctor note)"
137
- });
138
- }
139
- const verdict = checks.some((c) => c.ok === false) ? "broken" : checks.some((c) => c.ok === "warn") ? "degraded" : "healthy";
140
- return { checks, verdict };
141
- }
142
- function formatCodexDoctorReport(report) {
143
- const mark = (ok) => ok === true ? "\u2713" : ok === "warn" ? "\u26A0" : ok === "unknown" ? "?" : "\u2717";
144
- const lines = [];
145
- lines.push(`kojee-mcp doctor (codex) \u2014 verdict: ${report.verdict.toUpperCase()}`);
146
- lines.push("");
147
- lines.push(
148
- " Wake mode: self-contained (proxy-written pending marker) + stop-hook peek (Codex has no channel injection). Webhook OPTIONAL, never required."
149
- );
150
- lines.push(` Bounded-listen cap: ${CODEX_LISTEN_CAP_MS}ms (model picks listen vs drain vs ignore).`);
151
- lines.push("");
152
- for (const c of report.checks) {
153
- lines.push(` ${mark(c.ok)} ${c.name}: ${c.detail}`);
154
- }
155
- lines.push("");
156
- lines.push("NOTE: live Codex verification (hook fires, MCP connects, bounded listen) is an owner step.");
157
- return lines.join("\n");
158
- }
159
- export {
160
- collectCodexDoctorReport,
161
- formatCodexDoctorReport,
162
- parseCodexEnvFromToml
163
- };