granttap-mcp 0.8.39 → 0.8.41
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/apps/bridge/src/sessions/scan/codex/shared.ts +34 -1
- package/apps/bridge/src/transcript-history/index.ts +4 -3
- package/apps/mcp/src/connection-center/widget.html +1 -1
- package/apps/mcp/src/http/http-server.ts +8 -1
- package/cursor-plugin/README.md +1 -1
- package/cursor-plugin/mcp.json +1 -1
- package/cursor-plugin/stdio-bootstrap.cjs +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,8 @@ import { recordObservedWrite, writtenPaths } from "../../../mesh/observed/writes
|
|
|
8
8
|
* `event_msg` entries of type `token_count` carry
|
|
9
9
|
* `total_token_usage` and `last_token_usage` outright.
|
|
10
10
|
*/
|
|
11
|
-
import { closeSync, openSync, readFileSync, readSync, statSync } from "node:fs";
|
|
11
|
+
import { closeSync, lstatSync, openSync, readFileSync, readSync, readdirSync, statSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
12
13
|
import type {
|
|
13
14
|
ActivityEntry,
|
|
14
15
|
ChildThreadInfo,
|
|
@@ -92,6 +93,37 @@ export const CODEX_SUMMARY_TAIL_BYTES = 512 * 1024;
|
|
|
92
93
|
export const CODEX_ACTIVITY_HEAD_BYTES = 256 * 1024;
|
|
93
94
|
export const CODEX_ACTIVITY_TAIL_BYTES = 16 * 1024 * 1024;
|
|
94
95
|
|
|
96
|
+
/** Resolve the native rollout directly before considering a catalog-wide scan. */
|
|
97
|
+
export function codexLogPathForSession(sessionId: string, startedAt: number,
|
|
98
|
+
root = codexSessionsRoot()): string | undefined {
|
|
99
|
+
const indexed = codexLogPathBySession.get(sessionId);
|
|
100
|
+
if (indexed) {
|
|
101
|
+
try { if (lstatSync(indexed).isFile()) return indexed; } catch { /* Find its new path. */ }
|
|
102
|
+
codexLogPathBySession.delete(sessionId);
|
|
103
|
+
}
|
|
104
|
+
if (!/^[a-zA-Z0-9-]{1,128}$/.test(sessionId) || !Number.isFinite(startedAt)
|
|
105
|
+
|| startedAt <= 0) return undefined;
|
|
106
|
+
const start = ts(startedAt);
|
|
107
|
+
for (const dayOffset of [0, -1, 1]) {
|
|
108
|
+
const day = new Date(start + dayOffset * 86_400_000);
|
|
109
|
+
if (Number.isNaN(day.getTime())) continue;
|
|
110
|
+
const [year, month, date] = day.toISOString().slice(0, 10).split("-");
|
|
111
|
+
const directory = join(root, year!, month!, date!);
|
|
112
|
+
let names: string[];
|
|
113
|
+
try { names = readdirSync(directory); } catch { continue; }
|
|
114
|
+
for (const name of names) {
|
|
115
|
+
if (!name.startsWith("rollout-") || !name.endsWith(`-${sessionId}.jsonl`)) continue;
|
|
116
|
+
const path = join(directory, name);
|
|
117
|
+
try {
|
|
118
|
+
if (!lstatSync(path).isFile()) continue;
|
|
119
|
+
codexLogPathBySession.set(sessionId, path);
|
|
120
|
+
return path;
|
|
121
|
+
} catch { /* A file may disappear during a catalog refresh. */ }
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
95
127
|
/**
|
|
96
128
|
* Codex rollouts may contain a single screenshot/tool-result line larger than a
|
|
97
129
|
* gigabyte. A catalog refresh must never materialize that whole file. Preserve
|
|
@@ -175,6 +207,7 @@ export function codexLogLines(sessionId: string): string[] | undefined {
|
|
|
175
207
|
return row?.type === "session_meta" &&
|
|
176
208
|
String(row.payload?.id ?? row.id ?? "") === sessionId;
|
|
177
209
|
})) {
|
|
210
|
+
codexLogPathBySession.set(sessionId, file);
|
|
178
211
|
return candidate;
|
|
179
212
|
}
|
|
180
213
|
} catch {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ActivityEntry, SessionActivity, SessionInfo } from "../../../../packages/protocol/schema";
|
|
2
2
|
import { appendCodexActivity, codexCapabilityUsage } from "../sessions/scan/codex/activity";
|
|
3
|
-
import { codexLogLines,
|
|
3
|
+
import { codexLogLines, codexLogPathForSession } from "../sessions/scan/codex/shared";
|
|
4
4
|
import { appendClaudeActivity, claudeCapabilityUsage, claudeLogPath } from "../sessions/scan/claude";
|
|
5
5
|
import { previousNativeLines } from "./native-lines";
|
|
6
6
|
import { recordedFileChanges } from "./changes";
|
|
@@ -27,9 +27,10 @@ function boundedEntry(entry: ActivityEntry): ActivityEntry {
|
|
|
27
27
|
export function readTranscriptHistory(session: SessionInfo, cursor?: string): SessionActivity | undefined {
|
|
28
28
|
if (session.agent !== "codex" && session.agent !== "claude") return undefined;
|
|
29
29
|
let path = session.agent === "claude" ? claudeLogPath(session.sessionId)
|
|
30
|
-
:
|
|
30
|
+
: codexLogPathForSession(session.sessionId, session.startedAt);
|
|
31
31
|
if (!path && session.agent === "codex") {
|
|
32
|
-
codexLogLines(session.sessionId);
|
|
32
|
+
codexLogLines(session.sessionId);
|
|
33
|
+
path = codexLogPathForSession(session.sessionId, session.startedAt);
|
|
33
34
|
}
|
|
34
35
|
if (!path) return undefined;
|
|
35
36
|
let window;
|
|
@@ -37,7 +37,7 @@ details{border-top:1px solid #8884;padding-top:14px}summary{cursor:pointer;font-
|
|
|
37
37
|
<dt>Last encrypted message from iPhone</dt><dd id="phone">Not observed</dd></dl>
|
|
38
38
|
<h3>Provider readiness</h3><ul id="providers"></ul>
|
|
39
39
|
<p>QR pairs a phone directly. A passkey links this Mac to your GrantTap account so your signed-in phone can discover its computers. Provider sign-in is separate.</p>
|
|
40
|
-
<p>Missing hooks or background sync? Run <code>npm install -g granttap-mcp@0.8.
|
|
40
|
+
<p>Missing hooks or background sync? Run <code>npm install -g granttap-mcp@0.8.41</code> and <code>granttap setup</code> locally.
|
|
41
41
|
A saved pairing alone does not prove your phone or the background helper is online.</p>
|
|
42
42
|
<p><a href="https://granttap.com" target="_blank" rel="noopener noreferrer">Website</a> ·
|
|
43
43
|
<a href="https://granttap.com/privacy" target="_blank" rel="noopener noreferrer">Privacy</a> ·
|
|
@@ -25,6 +25,7 @@ import { startDesktopEngineBridgeProcess } from "../desktop/process/bridge-proce
|
|
|
25
25
|
|
|
26
26
|
import { installDesktopNativeRoutes } from "../desktop/native-access/routes";
|
|
27
27
|
import { startAccountRecoveryPoller } from "../../../bridge/src/account-recovery/poller";
|
|
28
|
+
import { reloadMonitorHelper } from "../../../bridge/src/install";
|
|
28
29
|
|
|
29
30
|
export const DEFAULT_HTTP_HOST = "127.0.0.1";
|
|
30
31
|
export const DEFAULT_HTTP_PORT = 17342;
|
|
@@ -34,6 +35,12 @@ type ServeOptions = {
|
|
|
34
35
|
port?: number;
|
|
35
36
|
};
|
|
36
37
|
|
|
38
|
+
function refreshRecoveredPairing(): void {
|
|
39
|
+
reloadMonitorHelper();
|
|
40
|
+
resetRelay();
|
|
41
|
+
void relay();
|
|
42
|
+
}
|
|
43
|
+
|
|
37
44
|
export async function startHttpMcpServer(options: ServeOptions = {}): Promise<{
|
|
38
45
|
host: string;
|
|
39
46
|
port: number;
|
|
@@ -113,7 +120,7 @@ export async function startHttpMcpServer(options: ServeOptions = {}): Promise<{
|
|
|
113
120
|
void relay();
|
|
114
121
|
const accountOrigin = websiteOrigin();
|
|
115
122
|
const stopAccountRecovery = accountOrigin
|
|
116
|
-
? startAccountRecoveryPoller(accountOrigin,
|
|
123
|
+
? startAccountRecoveryPoller(accountOrigin, refreshRecoveredPairing) : () => {};
|
|
117
124
|
|
|
118
125
|
return {
|
|
119
126
|
host,
|
package/cursor-plugin/README.md
CHANGED
|
@@ -10,7 +10,7 @@ keeps each phone response tied to the exact originating chat and prompt.
|
|
|
10
10
|
Install the supported CLI on this computer, then run:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
npm install -g granttap-mcp@0.8.
|
|
13
|
+
npm install -g granttap-mcp@0.8.41
|
|
14
14
|
granttap setup
|
|
15
15
|
granttap status
|
|
16
16
|
```
|
package/cursor-plugin/mcp.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"command": "node",
|
|
5
5
|
"args": [
|
|
6
6
|
"-e",
|
|
7
|
-
"\"use strict\";\n\n// Cursor may start this MCP from any cwd. Execute JavaScript entry points with\n// Node itself: Windows batch shims require shell quoting that differs by host.\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst { delimiter, dirname, join } = require(\"node:path\");\n\nconst PACKAGE = \"granttap-mcp@0.8.
|
|
7
|
+
"\"use strict\";\n\n// Cursor may start this MCP from any cwd. Execute JavaScript entry points with\n// Node itself: Windows batch shims require shell quoting that differs by host.\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst { delimiter, dirname, join } = require(\"node:path\");\n\nconst PACKAGE = \"granttap-mcp@0.8.41\";\nconst dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === \"1\";\nconst platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM\n ? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;\nconst nodeRoot = dryRun && process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT\n ? process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT : dirname(process.execPath);\nconst pathRoots = (process.env.PATH || \"\").split(delimiter).filter(Boolean);\nconst appData = process.env.APPDATA;\nconst roots = [nodeRoot, ...pathRoots, ...(appData ? [join(appData, \"npm\")] : [])];\nconst first = (paths) => paths.find((path) => existsSync(path));\n\nfunction launch() {\n if (platform !== \"win32\") {\n const installed = first(roots.map((root) => join(root, \"granttap-mcp\")));\n if (installed) return { command: installed, args: [] };\n const npx = first(roots.map((root) => join(root, \"npx\"))) || \"npx\";\n return { command: npx, args: [\"-y\", PACKAGE] };\n }\n const installed = first(roots.map((root) =>\n join(root, \"node_modules\", \"granttap-mcp\", \"bin\", \"granttap-mcp.mjs\")));\n if (installed) return { command: process.execPath, args: [installed] };\n const npx = first(roots.map((root) =>\n join(root, \"node_modules\", \"npm\", \"bin\", \"npx-cli.js\")));\n if (npx) return { command: process.execPath, args: [npx, \"-y\", PACKAGE] };\n throw new Error(\"Node.js/npm 20+ is required on this Windows device. Install npm and retry GrantTap.\");\n}\n\nlet target;\ntry { target = launch(); }\ncatch (error) {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n}\n\nif (dryRun) {\n process.stdout.write(JSON.stringify(target));\n process.exit(0);\n}\n\nconst child = spawn(target.command, target.args, { stdio: \"inherit\", windowsHide: true });\nchild.on(\"error\", (error) => {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n});\nchild.on(\"exit\", (code, signal) => {\n if (signal && platform !== \"win32\") {\n try { process.kill(process.pid, signal); } catch { process.exit(code ?? 1); }\n return;\n }\n process.exit(code ?? 1);\n});\n"
|
|
8
8
|
]
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -7,7 +7,7 @@ const { spawn } = require("node:child_process");
|
|
|
7
7
|
const { existsSync } = require("node:fs");
|
|
8
8
|
const { delimiter, dirname, join } = require("node:path");
|
|
9
9
|
|
|
10
|
-
const PACKAGE = "granttap-mcp@0.8.
|
|
10
|
+
const PACKAGE = "granttap-mcp@0.8.41";
|
|
11
11
|
const dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === "1";
|
|
12
12
|
const platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM
|
|
13
13
|
? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;
|