@cueai/omni-reader-mcp 1.5.0 → 1.5.2
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 +59 -12
- package/dist/cli/agent-config.d.ts +1 -0
- package/dist/cli/agent-config.js +92 -44
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/operation-manager.js +35 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ differ from the numbers above, report the live values.
|
|
|
64
64
|
Always use an audited exact version, never an implicit `latest`:
|
|
65
65
|
|
|
66
66
|
```sh
|
|
67
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
67
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 setup
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
The interactive setup supports Hermes, Cursor, Claude Desktop, and generic stdio
|
|
@@ -72,9 +72,9 @@ configuration. Non-interactive installation uses the same argument parsing and w
|
|
|
72
72
|
logic:
|
|
73
73
|
|
|
74
74
|
```sh
|
|
75
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
76
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
77
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
75
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 setup --client hermes --allowed-root /absolute/minimum/root --yes --json
|
|
76
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 setup --client cursor --add-root /absolute/minimum/root --yes --json
|
|
77
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 setup --client claude-desktop --allowed-root /absolute/minimum/root --yes --json
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
When an agent or script runs under a pty (stdin is still a TTY), declare non-interactive
|
|
@@ -82,9 +82,39 @@ mode explicitly with `--headless` (alias `--non-interactive`): no `--yes` is req
|
|
|
82
82
|
stdin is never read:
|
|
83
83
|
|
|
84
84
|
```sh
|
|
85
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
85
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 setup --client cursor --allowed-root /absolute/minimum/root --headless --json
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
## Windows configuration
|
|
89
|
+
|
|
90
|
+
On Windows, `npx` on the command line is actually `npx.cmd` — a batch-file wrapper, not
|
|
91
|
+
an executable. An MCP client that launches the server with a bare `npx` command and no
|
|
92
|
+
shell therefore fails immediately with `MCP error -32000: Connection closed` before the
|
|
93
|
+
server even starts. This is a launcher-shape problem, not an Omni problem: the same
|
|
94
|
+
entry works unchanged on macOS and Linux.
|
|
95
|
+
|
|
96
|
+
If the agent reports `Connection closed` right after connecting on Windows, use one of
|
|
97
|
+
the runnable forms below. From 1.5.2 on, `setup` writes the first form automatically on
|
|
98
|
+
Windows and migrates an entry that 1.5.1's `setup` wrote (the bare `npx` shape) to it
|
|
99
|
+
automatically; the second is the most robust when you configure by hand.
|
|
100
|
+
|
|
101
|
+
1. **`cmd` + `npx` (what `setup` writes on Windows)** — `cmd.exe` is a real executable,
|
|
102
|
+
so a client's no-shell spawn works:
|
|
103
|
+
```json
|
|
104
|
+
{ "command": "cmd", "args": ["/d", "/c", "npx", "-y", "@cueai/omni-reader-mcp@1.5.2"] }
|
|
105
|
+
```
|
|
106
|
+
2. **`node` + the package entry (most robust)** — skips `npx` entirely; the absolute
|
|
107
|
+
path must be a stable install you control:
|
|
108
|
+
```json
|
|
109
|
+
{ "command": "node", "args": ["C:\\path\\to\\node_modules\\@cueai\\omni-reader-mcp\\dist\\index.js"] }
|
|
110
|
+
```
|
|
111
|
+
A deliberate local `npm install @cueai/omni-reader-mcp@1.5.2` gives you that stable
|
|
112
|
+
path. Do not point the entry at an `_npx` cache directory — its hash subdirectory
|
|
113
|
+
changes between installs.
|
|
114
|
+
3. **Never use a session/timestamp directory** — such paths are cleaned up, and the
|
|
115
|
+
connection silently breaks at the next session. Re-run `setup` or install into a
|
|
116
|
+
stable directory instead.
|
|
117
|
+
|
|
88
118
|
## Cache and journal isolation
|
|
89
119
|
|
|
90
120
|
The local parse cache and operation journal default to the user-level cache directory
|
|
@@ -221,30 +251,47 @@ satisfies the constraints.
|
|
|
221
251
|
## Commands
|
|
222
252
|
|
|
223
253
|
```sh
|
|
224
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
225
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
226
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
227
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
254
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 doctor
|
|
255
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 doctor --json
|
|
256
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 clean
|
|
257
|
+
npx -y @cueai/omni-reader-mcp@1.5.2 uninstall --yes --json
|
|
228
258
|
```
|
|
229
259
|
|
|
230
260
|
Running the pinned version without a command starts the stdio MCP server:
|
|
231
261
|
|
|
232
262
|
```sh
|
|
233
|
-
npx -y @cueai/omni-reader-mcp@1.5.
|
|
263
|
+
npx -y @cueai/omni-reader-mcp@1.5.2
|
|
234
264
|
```
|
|
235
265
|
|
|
236
266
|
`doctor --json` returns package/npm/client adapter, Key present/absent, allowed-root
|
|
237
267
|
safety status, endpoint compatibility, artifacts, cache mode, onboarding, and reload
|
|
238
268
|
status; it never prints the Key, private source paths, or content.
|
|
239
269
|
|
|
270
|
+
## Network diagnostics
|
|
271
|
+
|
|
272
|
+
Bridge connects to the Omni parse API at `https://cubefile.ai.iiis.co:9443`. When a
|
|
273
|
+
connection fails, run `doctor` first — its endpoint-compatibility check covers the
|
|
274
|
+
API reachability from your machine. The common symptoms:
|
|
275
|
+
|
|
276
|
+
| Symptom | Most likely cause | Check |
|
|
277
|
+
|---|---|---|
|
|
278
|
+
| `MCP error -32000: Connection closed` on Windows | launcher shape (see Windows configuration) | `doctor` package/client rows |
|
|
279
|
+
| `CUBE_PROTOCOL_ERROR` or connection refused/timeout on connect | the hostname resolves to a private address on your network, or the route cannot reach the public endpoint | `nslookup cubefile.ai.iiis.co` — the public record is `122.200.68.28` |
|
|
280
|
+
| Works in the browser / on another machine but not this one | a local hosts-file override hides a DNS or route problem | check `/etc/hosts` (or `C:\Windows\System32\drivers\etc\hosts`) for a `cubefile.ai.iiis.co` line; test `curl --noproxy '*' -w '%{remote_ip}\n' https://cubefile.ai.iiis.co:9443/omni/health` |
|
|
281
|
+
|
|
282
|
+
If the API is reachable but a specific public URL fails to parse (`parse_timeout` /
|
|
283
|
+
parse failed) while it works in your browser, that is a fetch-layer condition of the
|
|
284
|
+
source on the parse API side — not a Bridge configuration problem — and it affects the
|
|
285
|
+
URL the same way from every client.
|
|
286
|
+
|
|
240
287
|
## Uninstall and rollback
|
|
241
288
|
|
|
242
|
-
`uninstall --yes --json` removes only a trusted 1.
|
|
289
|
+
`uninstall --yes --json` removes only a trusted 1.5.1 or 1.5.2 Bridge entry; when a
|
|
243
290
|
matching trusted backup exists, it restores the original URL-only `omni-reader` entry.
|
|
244
291
|
Uninstall never deletes user source files and never silently removes unexpired local
|
|
245
292
|
results.
|
|
246
293
|
|
|
247
|
-
To roll back from 1.5.
|
|
294
|
+
To roll back from 1.5.2:
|
|
248
295
|
|
|
249
296
|
1. stop recommending or installing that version;
|
|
250
297
|
2. run `uninstall --yes --json` to restore the trusted URL-only entry;
|
|
@@ -41,6 +41,7 @@ export declare function agentConfigPath(target: AgentTarget, environment: AgentC
|
|
|
41
41
|
export declare function agentBackupPath(configPath: string): string;
|
|
42
42
|
export declare function displayConfigPath(configPath: string, environment: AgentConfigEnvironment): string;
|
|
43
43
|
export declare function buildAgentEntry(target: AgentTarget, extraRoots: readonly string[], platform: NodeJS.Platform): Record<string, unknown>;
|
|
44
|
+
export declare function expectedBridgeVersion(target: AgentTarget, value: unknown, platform: NodeJS.Platform): string | undefined;
|
|
44
45
|
export declare function prepareAgentConfig(target: AgentTarget, extraRoots: readonly string[], environment: AgentConfigEnvironment): Promise<PreparedAgentConfig>;
|
|
45
46
|
export declare function verifyPreparedAgentConfig(prepared: PreparedAgentConfig): Promise<void>;
|
|
46
47
|
export declare function writePreparedAgentConfig(prepared: PreparedAgentConfig): Promise<void>;
|
package/dist/cli/agent-config.js
CHANGED
|
@@ -7,7 +7,7 @@ const PACKAGE_SPEC = `@cueai/omni-reader-mcp@${BRIDGE_RELEASE_VERSION}`;
|
|
|
7
7
|
// The release that the current version is a trusted upgrade from: uninstall and
|
|
8
8
|
// rollback recognize exactly {previous, current} and nothing else. Bump this to
|
|
9
9
|
// the version we just published when BRIDGE_RELEASE_VERSION advances.
|
|
10
|
-
const PREVIOUS_RELEASE_VERSION = "1.
|
|
10
|
+
const PREVIOUS_RELEASE_VERSION = "1.5.1";
|
|
11
11
|
const PREVIOUS_PACKAGE_SPEC = `@cueai/omni-reader-mcp@${PREVIOUS_RELEASE_VERSION}`;
|
|
12
12
|
const LEGACY_PACKAGE_SPEC = "@cueai/omni-reader-mcp";
|
|
13
13
|
const TRUSTED_EXACT_PACKAGE_SPECS = new Set([PREVIOUS_PACKAGE_SPEC, PACKAGE_SPEC]);
|
|
@@ -116,10 +116,14 @@ export function displayConfigPath(configPath, environment) {
|
|
|
116
116
|
return configPath;
|
|
117
117
|
}
|
|
118
118
|
export function buildAgentEntry(target, extraRoots, platform) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
// On Windows `npx` is `npx.cmd` — a batch wrapper a client cannot spawn without a
|
|
120
|
+
// shell (spawn("npx") → ENOENT, spawn("npx.cmd") → EINVAL). `cmd /d /c npx ...` is a
|
|
121
|
+
// real executable, so a no-shell spawn works (`/d` skips the AutoRun registry command,
|
|
122
|
+
// whose stdout would corrupt the MCP stdio frames); macOS/Linux keep the bare `npx`
|
|
123
|
+
// form.
|
|
124
|
+
const entry = platform === "win32"
|
|
125
|
+
? { command: "cmd", args: ["/d", "/c", "npx", "-y", PACKAGE_SPEC] }
|
|
126
|
+
: { command: "npx", args: ["-y", PACKAGE_SPEC] };
|
|
123
127
|
const env = {};
|
|
124
128
|
if (target === "hermes")
|
|
125
129
|
env.CUE_API_KEY = "${CUE_API_KEY}";
|
|
@@ -130,6 +134,49 @@ export function buildAgentEntry(target, extraRoots, platform) {
|
|
|
130
134
|
entry.env = env;
|
|
131
135
|
return entry;
|
|
132
136
|
}
|
|
137
|
+
/** The exact package spec at the invocation's spec position, given its platform shape. */
|
|
138
|
+
function entryPackageSpec(entry, platform) {
|
|
139
|
+
const args = entry.args;
|
|
140
|
+
if (!Array.isArray(args))
|
|
141
|
+
return undefined;
|
|
142
|
+
if (platform !== "win32")
|
|
143
|
+
return args[1];
|
|
144
|
+
return entry.command === "npx" ? args[1] : args[4];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Matches the trusted invocation shape for the platform: `cmd /d /c npx -y <spec>` on
|
|
148
|
+
* Windows (runnable by a no-shell spawn; `/d` skips the AutoRun command whose stdout
|
|
149
|
+
* would corrupt MCP stdio frames), `npx -y <spec>` everywhere else. On Windows the
|
|
150
|
+
* previous release's bare-`npx` shape is additionally recognized as the migration
|
|
151
|
+
* source — 1.5.1's setup wrote it there and it can never run, but upgrade and
|
|
152
|
+
* uninstall must still identify it as a trusted entry so 1.5.2 can replace it.
|
|
153
|
+
*/
|
|
154
|
+
function entryInvocationMatches(entry, platform) {
|
|
155
|
+
const args = entry.args;
|
|
156
|
+
if (platform === "win32") {
|
|
157
|
+
const cmdForm = entry.command === "cmd"
|
|
158
|
+
&& Array.isArray(args)
|
|
159
|
+
&& args.length === 5
|
|
160
|
+
&& args[0] === "/d"
|
|
161
|
+
&& args[1] === "/c"
|
|
162
|
+
&& args[2] === "npx"
|
|
163
|
+
&& args[3] === "-y"
|
|
164
|
+
&& typeof args[4] === "string"
|
|
165
|
+
&& TRUSTED_EXACT_PACKAGE_SPECS.has(args[4]);
|
|
166
|
+
const previousNpxForm = entry.command === "npx"
|
|
167
|
+
&& Array.isArray(args)
|
|
168
|
+
&& args.length === 2
|
|
169
|
+
&& args[0] === "-y"
|
|
170
|
+
&& args[1] === PREVIOUS_PACKAGE_SPEC;
|
|
171
|
+
return cmdForm || previousNpxForm;
|
|
172
|
+
}
|
|
173
|
+
return entry.command === "npx"
|
|
174
|
+
&& Array.isArray(args)
|
|
175
|
+
&& args.length === 2
|
|
176
|
+
&& args[0] === "-y"
|
|
177
|
+
&& typeof args[1] === "string"
|
|
178
|
+
&& TRUSTED_EXACT_PACKAGE_SPECS.has(args[1]);
|
|
179
|
+
}
|
|
133
180
|
function configFormat(target) {
|
|
134
181
|
return target === "hermes" ? "hermes-yaml" : "json";
|
|
135
182
|
}
|
|
@@ -500,7 +547,7 @@ function yamlEntry(entry, newline) {
|
|
|
500
547
|
const args = entry.args;
|
|
501
548
|
const lines = [
|
|
502
549
|
" omni-reader:",
|
|
503
|
-
|
|
550
|
+
` command: ${entry.command}`,
|
|
504
551
|
" args:",
|
|
505
552
|
...args.map((argument) => ` - ${JSON.stringify(argument)}`),
|
|
506
553
|
];
|
|
@@ -541,16 +588,8 @@ function entryDigest(entry) {
|
|
|
541
588
|
};
|
|
542
589
|
return `sha256:${createHash("sha256").update(JSON.stringify(identity), "utf8").digest("hex")}`;
|
|
543
590
|
}
|
|
544
|
-
function isExpectedOmniEntry(target, value) {
|
|
545
|
-
if (!isRecord(value))
|
|
546
|
-
return false;
|
|
547
|
-
const args = value.args;
|
|
548
|
-
if (value.command !== "npx" ||
|
|
549
|
-
!Array.isArray(args) ||
|
|
550
|
-
args.length !== 2 ||
|
|
551
|
-
args[0] !== "-y" ||
|
|
552
|
-
typeof args[1] !== "string" ||
|
|
553
|
-
!TRUSTED_EXACT_PACKAGE_SPECS.has(args[1]))
|
|
591
|
+
function isExpectedOmniEntry(target, value, platform) {
|
|
592
|
+
if (!isRecord(value) || !entryInvocationMatches(value, platform))
|
|
554
593
|
return false;
|
|
555
594
|
const keys = Object.keys(value).sort();
|
|
556
595
|
if (value.env === undefined) {
|
|
@@ -586,21 +625,30 @@ function isExpectedOmniEntry(target, value) {
|
|
|
586
625
|
&& keys[1] === "command"
|
|
587
626
|
&& keys[2] === "env";
|
|
588
627
|
}
|
|
589
|
-
function expectedBridgeVersion(target, value) {
|
|
590
|
-
if (!isExpectedOmniEntry(target, value))
|
|
628
|
+
export function expectedBridgeVersion(target, value, platform) {
|
|
629
|
+
if (!isExpectedOmniEntry(target, value, platform))
|
|
591
630
|
return undefined;
|
|
592
|
-
const packageSpec = value
|
|
631
|
+
const packageSpec = entryPackageSpec(value, platform);
|
|
593
632
|
return packageSpec === PREVIOUS_PACKAGE_SPEC ? PREVIOUS_RELEASE_VERSION : BRIDGE_RELEASE_VERSION;
|
|
594
633
|
}
|
|
595
|
-
function isLegacyBridgeEntry(target, value) {
|
|
596
|
-
|
|
634
|
+
function isLegacyBridgeEntry(target, value, platform) {
|
|
635
|
+
// The legacy npx form (what every pre-1.5.2 setup wrote, incl. on Windows) plus, on
|
|
636
|
+
// Windows, the current cmd form — both are recognizable Bridge entries.
|
|
637
|
+
const legacyNpx = (entry) => {
|
|
638
|
+
const args = entry.args;
|
|
639
|
+
return entry.command === "npx"
|
|
640
|
+
&& Array.isArray(args)
|
|
641
|
+
&& args.length === 2
|
|
642
|
+
&& args[0] === "-y"
|
|
643
|
+
&& typeof args[1] === "string"
|
|
644
|
+
&& (args[1] === LEGACY_PACKAGE_SPEC || TRUSTED_EXACT_PACKAGE_SPECS.has(args[1]));
|
|
645
|
+
};
|
|
646
|
+
if (!isRecord(value))
|
|
597
647
|
return false;
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
typeof args[1] !== "string" ||
|
|
603
|
-
(args[1] !== LEGACY_PACKAGE_SPEC && !TRUSTED_EXACT_PACKAGE_SPECS.has(args[1])))
|
|
648
|
+
const shapeOk = platform === "win32"
|
|
649
|
+
? (legacyNpx(value) || entryInvocationMatches(value, platform))
|
|
650
|
+
: legacyNpx(value);
|
|
651
|
+
if (!shapeOk)
|
|
604
652
|
return false;
|
|
605
653
|
if (value.env === undefined)
|
|
606
654
|
return target !== "hermes";
|
|
@@ -640,12 +688,12 @@ function hermesOmniEntry(document, displayPath) {
|
|
|
640
688
|
}
|
|
641
689
|
return entry;
|
|
642
690
|
}
|
|
643
|
-
function previousJsonEntry(value, displayPath) {
|
|
691
|
+
function previousJsonEntry(value, displayPath, platform) {
|
|
644
692
|
if (value === undefined)
|
|
645
693
|
return null;
|
|
646
694
|
if (isCanonicalRemoteEntry(value))
|
|
647
695
|
return { format: "json", value };
|
|
648
|
-
if (isLegacyBridgeEntry("cursor", value))
|
|
696
|
+
if (isLegacyBridgeEntry("cursor", value, platform))
|
|
649
697
|
return null;
|
|
650
698
|
throw fileError(`The existing "omni-reader" entry in ${displayPath} is not a trusted remote or Bridge `
|
|
651
699
|
+ "configuration; no changes were written. Remove that entry manually, or restore a backup, "
|
|
@@ -663,7 +711,7 @@ function hermesCredentialsAreReferences(serialized) {
|
|
|
663
711
|
}
|
|
664
712
|
return true;
|
|
665
713
|
}
|
|
666
|
-
function previousHermesEntry(entry, displayPath) {
|
|
714
|
+
function previousHermesEntry(entry, displayPath, platform) {
|
|
667
715
|
if (entry === undefined)
|
|
668
716
|
return null;
|
|
669
717
|
const value = parseHermesEntry(entry);
|
|
@@ -675,7 +723,7 @@ function previousHermesEntry(entry, displayPath) {
|
|
|
675
723
|
}
|
|
676
724
|
return { format: "hermes-yaml", serialized: entry.serialized };
|
|
677
725
|
}
|
|
678
|
-
if (isLegacyBridgeEntry("hermes", value))
|
|
726
|
+
if (isLegacyBridgeEntry("hermes", value, platform))
|
|
679
727
|
return null;
|
|
680
728
|
throw fileError(`The existing "omni-reader" entry in ${displayPath} is not a trusted remote or Bridge `
|
|
681
729
|
+ "configuration; no changes were written. Remove that entry manually, or restore a backup, "
|
|
@@ -710,7 +758,7 @@ export async function prepareAgentConfig(target, extraRoots, environment) {
|
|
|
710
758
|
}
|
|
711
759
|
const servers = existingServers ?? {};
|
|
712
760
|
const existing = onlyOmniEntry(servers, displayPath);
|
|
713
|
-
const previousEntry = previousJsonEntry(existing.value, displayPath);
|
|
761
|
+
const previousEntry = previousJsonEntry(existing.value, displayPath, environment.platform);
|
|
714
762
|
const afterValue = {
|
|
715
763
|
...value,
|
|
716
764
|
mcpServers: {
|
|
@@ -737,7 +785,7 @@ export async function prepareAgentConfig(target, extraRoots, environment) {
|
|
|
737
785
|
}
|
|
738
786
|
const document = parseHermesDocument(loaded.serialized);
|
|
739
787
|
const existing = hermesOmniEntry(document, displayPath);
|
|
740
|
-
const previousEntry = previousHermesEntry(existing, displayPath);
|
|
788
|
+
const previousEntry = previousHermesEntry(existing, displayPath, environment.platform);
|
|
741
789
|
const serializedAfter = replaceHermesEntry(loaded.serialized, document, yamlEntry(entry, document.newline));
|
|
742
790
|
return {
|
|
743
791
|
target: "hermes",
|
|
@@ -964,7 +1012,7 @@ export async function writePreparedAgentConfig(prepared) {
|
|
|
964
1012
|
const existingBackup = await readTrustedBackup(configPath);
|
|
965
1013
|
let replacementBackup = backup;
|
|
966
1014
|
if (existingBackup !== undefined) {
|
|
967
|
-
const currentEntry = expectedConfigEntry(prepared.target, current);
|
|
1015
|
+
const currentEntry = expectedConfigEntry(prepared.target, current, prepared.environment?.platform ?? "darwin");
|
|
968
1016
|
if (currentEntry !== undefined && existingBackup.target === prepared.target) {
|
|
969
1017
|
if (existingBackup.bridge_entry_digest !== entryDigest(currentEntry)) {
|
|
970
1018
|
throw fileError("A conflicting trusted Omni backup already exists; no changes were written.");
|
|
@@ -1011,21 +1059,21 @@ function jsonConfigEntry(value) {
|
|
|
1011
1059
|
return undefined;
|
|
1012
1060
|
return onlyOmniEntry(value.mcpServers, "the Agent configuration").value;
|
|
1013
1061
|
}
|
|
1014
|
-
function expectedConfigEntry(target, loaded) {
|
|
1062
|
+
function expectedConfigEntry(target, loaded, platform) {
|
|
1015
1063
|
if (target === "hermes") {
|
|
1016
1064
|
const document = parseHermesDocument(loaded.serialized);
|
|
1017
1065
|
const entry = hermesOmniEntry(document, "the Hermes configuration");
|
|
1018
1066
|
if (entry === undefined)
|
|
1019
1067
|
return undefined;
|
|
1020
1068
|
const value = parseHermesEntry(entry);
|
|
1021
|
-
return isExpectedOmniEntry(target, value) ? value : undefined;
|
|
1069
|
+
return isExpectedOmniEntry(target, value, platform) ? value : undefined;
|
|
1022
1070
|
}
|
|
1023
1071
|
assertNoDuplicateJsonOmniEntries(loaded.serialized);
|
|
1024
1072
|
const value = jsonConfigEntry(parseJsonConfig(loaded));
|
|
1025
|
-
return isExpectedOmniEntry(target, value) ? value : undefined;
|
|
1073
|
+
return isExpectedOmniEntry(target, value, platform) ? value : undefined;
|
|
1026
1074
|
}
|
|
1027
|
-
async function configHasExpectedEntry(target, loaded) {
|
|
1028
|
-
return expectedConfigEntry(target, loaded) !== undefined;
|
|
1075
|
+
async function configHasExpectedEntry(target, loaded, platform) {
|
|
1076
|
+
return expectedConfigEntry(target, loaded, platform) !== undefined;
|
|
1029
1077
|
}
|
|
1030
1078
|
export async function inspectAgentConfigDetails(configPath, environment, target) {
|
|
1031
1079
|
try {
|
|
@@ -1041,7 +1089,7 @@ export async function inspectAgentConfigDetails(configPath, environment, target)
|
|
|
1041
1089
|
if (entry === undefined)
|
|
1042
1090
|
return { status: "not configured" };
|
|
1043
1091
|
const value = parseHermesEntry(entry);
|
|
1044
|
-
const version = expectedBridgeVersion("hermes", value);
|
|
1092
|
+
const version = expectedBridgeVersion("hermes", value, environment?.platform ?? "darwin");
|
|
1045
1093
|
if (version !== undefined)
|
|
1046
1094
|
return { status: "configured", version };
|
|
1047
1095
|
return {
|
|
@@ -1055,7 +1103,7 @@ export async function inspectAgentConfigDetails(configPath, environment, target)
|
|
|
1055
1103
|
const entry = onlyOmniEntry(value.mcpServers, configPath).value;
|
|
1056
1104
|
if (entry === undefined)
|
|
1057
1105
|
return { status: "not configured" };
|
|
1058
|
-
const version = expectedBridgeVersion(resolvedTarget, entry);
|
|
1106
|
+
const version = expectedBridgeVersion(resolvedTarget, entry, environment?.platform ?? "darwin");
|
|
1059
1107
|
if (version !== undefined)
|
|
1060
1108
|
return { status: "configured", version };
|
|
1061
1109
|
return {
|
|
@@ -1133,7 +1181,7 @@ export async function rollbackPreparedAgentConfig(prepared) {
|
|
|
1133
1181
|
existed: true,
|
|
1134
1182
|
serialized: prepared.serializedBefore,
|
|
1135
1183
|
fingerprint: prepared.sourceFingerprint ?? "unused",
|
|
1136
|
-
})
|
|
1184
|
+
}, prepared.environment?.platform ?? "darwin")
|
|
1137
1185
|
: undefined;
|
|
1138
1186
|
if (prepared.existed) {
|
|
1139
1187
|
await atomicReplace(prepared.configPath, prepared.serializedBefore);
|
|
@@ -1192,11 +1240,11 @@ export async function uninstallAgentConfig(target, environment) {
|
|
|
1192
1240
|
return undefined;
|
|
1193
1241
|
await validateUserConfigPath(configPath, environment);
|
|
1194
1242
|
const initial = await readConfig(configPath);
|
|
1195
|
-
if (!initial.existed || !await configHasExpectedEntry(target, initial))
|
|
1243
|
+
if (!initial.existed || !await configHasExpectedEntry(target, initial, environment.platform))
|
|
1196
1244
|
return undefined;
|
|
1197
1245
|
return await withConfigLock(configPath, environment, async () => {
|
|
1198
1246
|
const current = await readConfig(configPath);
|
|
1199
|
-
if (!await configHasExpectedEntry(target, current)) {
|
|
1247
|
+
if (!await configHasExpectedEntry(target, current, environment.platform)) {
|
|
1200
1248
|
throw fileError("The Agent configuration changed before uninstall; no changes were written.");
|
|
1201
1249
|
}
|
|
1202
1250
|
const currentEntry = target === "hermes"
|
package/dist/constants.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare const CUBE_GRANT_PROTOCOL_VERSION = "omni.parse_grant.v1";
|
|
|
6
6
|
export declare const GRANTED_STREAM_PROTOCOL_VERSION = "omni.granted_parse_stream.v1";
|
|
7
7
|
export declare const DEFAULT_CUBE_BASE_URL = "https://mcp.cuecue.cn";
|
|
8
8
|
export declare const DEFAULT_IIIS_GRANTED_BASE_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/";
|
|
9
|
-
export declare const BRIDGE_RELEASE_VERSION = "1.5.
|
|
9
|
+
export declare const BRIDGE_RELEASE_VERSION = "1.5.2";
|
|
10
10
|
export declare const REMOTE_OMNI_MCP_URL = "https://mcp.cuecue.cn/api/omni-reader/mcp/";
|
|
11
11
|
export declare const FOREGROUND_BUDGET_MS = 15000;
|
|
12
12
|
export declare const STATUS_LONG_POLL_MAX_MS = 20000;
|
package/dist/constants.js
CHANGED
|
@@ -6,7 +6,7 @@ export const CUBE_GRANT_PROTOCOL_VERSION = "omni.parse_grant.v1";
|
|
|
6
6
|
export const GRANTED_STREAM_PROTOCOL_VERSION = "omni.granted_parse_stream.v1";
|
|
7
7
|
export const DEFAULT_CUBE_BASE_URL = "https://mcp.cuecue.cn";
|
|
8
8
|
export const DEFAULT_IIIS_GRANTED_BASE_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/";
|
|
9
|
-
export const BRIDGE_RELEASE_VERSION = "1.5.
|
|
9
|
+
export const BRIDGE_RELEASE_VERSION = "1.5.2";
|
|
10
10
|
export const REMOTE_OMNI_MCP_URL = "https://mcp.cuecue.cn/api/omni-reader/mcp/";
|
|
11
11
|
export const FOREGROUND_BUDGET_MS = 15_000;
|
|
12
12
|
export const STATUS_LONG_POLL_MAX_MS = 20_000;
|
|
@@ -760,7 +760,10 @@ function remoteResultUpdate(result, expectedOperationId) {
|
|
|
760
760
|
operationId: result.operation_id,
|
|
761
761
|
errorCode: null,
|
|
762
762
|
parserStarted: true,
|
|
763
|
-
|
|
763
|
+
// Owner ruling: credits are deducted only on successful completion — the public
|
|
764
|
+
// billed flag mirrors the remote settlement facts (zero-charge completion is a
|
|
765
|
+
// settled fact, not an uncharged one). Never write true unconditionally.
|
|
766
|
+
billed: (result.billing?.credits_charged ?? 0) > 0,
|
|
764
767
|
contentReleased: true,
|
|
765
768
|
stage: "completed",
|
|
766
769
|
progressPercent: 100,
|
|
@@ -778,7 +781,11 @@ function remoteResultUpdate(result, expectedOperationId) {
|
|
|
778
781
|
operationId: result.operation_id,
|
|
779
782
|
errorCode: null,
|
|
780
783
|
parserStarted: true,
|
|
781
|
-
|
|
784
|
+
// The cleanup_pending wire carries no settlement fact (the closed v3/v4 contract
|
|
785
|
+
// exposes usage/billing only on released/delivered/delivery_expired terminals) —
|
|
786
|
+
// report false rather than inventing a charge; the journal allows a later
|
|
787
|
+
// false->true completion fact (assertStableTransition only blocks true->false).
|
|
788
|
+
billed: false,
|
|
782
789
|
contentReleased: result.result !== undefined,
|
|
783
790
|
stage: "cleanup_pending",
|
|
784
791
|
progressPercent: result.result === undefined ? 99 : 100,
|
|
@@ -869,7 +876,8 @@ function localResultValue(local) {
|
|
|
869
876
|
operationCreated: true,
|
|
870
877
|
fileUploaded: true,
|
|
871
878
|
parserStarted: true,
|
|
872
|
-
billed:
|
|
879
|
+
// Owner ruling: an integrity failure settled nothing — never report billed:true.
|
|
880
|
+
billed: false,
|
|
873
881
|
contentReleased: true,
|
|
874
882
|
});
|
|
875
883
|
}
|
|
@@ -996,7 +1004,8 @@ function requireBundleResult(retention) {
|
|
|
996
1004
|
operationCreated: true,
|
|
997
1005
|
fileUploaded: true,
|
|
998
1006
|
parserStarted: true,
|
|
999
|
-
billed:
|
|
1007
|
+
// Owner ruling: an integrity failure settled nothing — never report billed:true.
|
|
1008
|
+
billed: false,
|
|
1000
1009
|
contentReleased: false,
|
|
1001
1010
|
});
|
|
1002
1011
|
}
|
|
@@ -1429,12 +1438,32 @@ export function createLocalParseOperationManager(options) {
|
|
|
1429
1438
|
result: processingParse(operationId, stage, latestPercent, patch.contentReleased === true),
|
|
1430
1439
|
};
|
|
1431
1440
|
}
|
|
1441
|
+
const checkpointBilled = snapshot.patch?.billed === true;
|
|
1432
1442
|
return {
|
|
1433
1443
|
update: {
|
|
1434
1444
|
state: "FAILED",
|
|
1435
|
-
patch:
|
|
1445
|
+
patch: {
|
|
1446
|
+
...failurePatch(stable),
|
|
1447
|
+
// The ACK checkpoint may already have recorded a settled charge
|
|
1448
|
+
// (snapshot.patch at :1751 carries resultPatch's billed fact).
|
|
1449
|
+
// Never regress it — assertStableTransition blocks true->false —
|
|
1450
|
+
// the charge happened; this failure is about the local artifact,
|
|
1451
|
+
// not the settlement.
|
|
1452
|
+
billed: checkpointBilled || stable.billed,
|
|
1453
|
+
},
|
|
1454
|
+
},
|
|
1455
|
+
result: {
|
|
1456
|
+
status: "failed",
|
|
1457
|
+
error: {
|
|
1458
|
+
...stable.toJSON(),
|
|
1459
|
+
// Deliberately the checkpoint fact only (not the OR): the failed
|
|
1460
|
+
// public result reports exactly what this run settled — false
|
|
1461
|
+
// when nothing was settled (owner ruling), true when the ACK
|
|
1462
|
+
// checkpoint already recorded the charge and the failure is
|
|
1463
|
+
// about local delivery, not the settlement.
|
|
1464
|
+
billed: checkpointBilled,
|
|
1465
|
+
},
|
|
1436
1466
|
},
|
|
1437
|
-
result: { status: "failed", error: stable.toJSON() },
|
|
1438
1467
|
};
|
|
1439
1468
|
}
|
|
1440
1469
|
finally {
|