@cueai/omni-reader-mcp 1.0.2 → 1.1.0
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 +115 -26
- package/dist/artifact-store.d.ts +11 -0
- package/dist/artifact-store.js +94 -48
- package/dist/cli/agent-config.d.ts +29 -4
- package/dist/cli/agent-config.js +910 -107
- package/dist/cli/arguments.d.ts +32 -0
- package/dist/cli/arguments.js +120 -0
- package/dist/cli/doctor.d.ts +42 -1
- package/dist/cli/doctor.js +109 -36
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.js +103 -18
- package/dist/cli/uninstall.d.ts +6 -0
- package/dist/cli/uninstall.js +37 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +7 -0
- package/dist/cube-client.d.ts +5 -3
- package/dist/cube-client.js +16 -11
- package/dist/cursor.js +2 -0
- package/dist/errors.d.ts +32 -1
- package/dist/errors.js +26 -1
- package/dist/iiis-client.d.ts +18 -4
- package/dist/iiis-client.js +194 -40
- package/dist/index.d.ts +3 -0
- package/dist/index.js +93 -32
- package/dist/multipart-body.js +2 -0
- package/dist/onboarding-policy.d.ts +10 -0
- package/dist/onboarding-policy.js +58 -0
- package/dist/operation-journal.d.ts +50 -1
- package/dist/operation-journal.js +473 -114
- package/dist/operation-manager.d.ts +75 -0
- package/dist/operation-manager.js +1311 -0
- package/dist/path-security.d.ts +1 -0
- package/dist/path-security.js +26 -6
- package/dist/progress.d.ts +6 -1
- package/dist/protocol.d.ts +26 -13
- package/dist/protocol.js +34 -10
- package/dist/remote-client.d.ts +17 -0
- package/dist/remote-client.js +233 -0
- package/dist/result-contract.d.ts +199 -0
- package/dist/result-contract.js +235 -0
- package/dist/server.js +21 -4
- package/dist/source.d.ts +8 -0
- package/dist/source.js +37 -0
- package/dist/task-runtime.d.ts +13 -0
- package/dist/task-runtime.js +94 -0
- package/dist/tools.d.ts +19 -1
- package/dist/tools.js +317 -112
- package/package.json +3 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type AgentTarget } from "./agent-config.js";
|
|
2
|
+
export interface SetupArguments {
|
|
3
|
+
readonly client?: AgentTarget;
|
|
4
|
+
readonly allowedRoots: readonly string[];
|
|
5
|
+
readonly addRoots: readonly string[];
|
|
6
|
+
readonly yes: boolean;
|
|
7
|
+
readonly json: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type ParsedCommand = {
|
|
10
|
+
readonly command: "server";
|
|
11
|
+
} | {
|
|
12
|
+
readonly command: "help";
|
|
13
|
+
} | {
|
|
14
|
+
readonly command: "version";
|
|
15
|
+
} | {
|
|
16
|
+
readonly command: "setup";
|
|
17
|
+
readonly arguments: SetupArguments;
|
|
18
|
+
} | {
|
|
19
|
+
readonly command: "doctor";
|
|
20
|
+
readonly json: boolean;
|
|
21
|
+
} | {
|
|
22
|
+
readonly command: "clean";
|
|
23
|
+
} | {
|
|
24
|
+
readonly command: "uninstall";
|
|
25
|
+
readonly yes: boolean;
|
|
26
|
+
readonly json: boolean;
|
|
27
|
+
};
|
|
28
|
+
export declare class CliUsageError extends Error {
|
|
29
|
+
readonly exitCode = 2;
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
export declare function parseCliArguments(argv: readonly string[], platform?: NodeJS.Platform): ParsedCommand;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { parseAgentTarget } from "./agent-config.js";
|
|
3
|
+
export class CliUsageError extends Error {
|
|
4
|
+
exitCode = 2;
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "CliUsageError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function pathsFor(platform) {
|
|
11
|
+
return platform === "win32" ? path.win32 : path.posix;
|
|
12
|
+
}
|
|
13
|
+
function requireNoArguments(command, values) {
|
|
14
|
+
if (values.length > 0)
|
|
15
|
+
throw new CliUsageError(`${command} does not accept arguments.`);
|
|
16
|
+
}
|
|
17
|
+
function parseBooleanFlags(command, values, supported) {
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
for (const value of values) {
|
|
20
|
+
if (!supported.has(value)) {
|
|
21
|
+
throw new CliUsageError(`Unknown ${command} flag: ${value}`);
|
|
22
|
+
}
|
|
23
|
+
if (seen.has(value)) {
|
|
24
|
+
throw new CliUsageError(`Duplicate ${command} flag: ${value}`);
|
|
25
|
+
}
|
|
26
|
+
seen.add(value);
|
|
27
|
+
}
|
|
28
|
+
return seen;
|
|
29
|
+
}
|
|
30
|
+
function parseSetupArguments(values, platform) {
|
|
31
|
+
let client;
|
|
32
|
+
let allowedRoot;
|
|
33
|
+
let addRoot;
|
|
34
|
+
let yes = false;
|
|
35
|
+
let json = false;
|
|
36
|
+
const seen = new Set();
|
|
37
|
+
const paths = pathsFor(platform);
|
|
38
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
39
|
+
const flag = values[index];
|
|
40
|
+
if (!["--client", "--allowed-root", "--add-root", "--yes", "--json"].includes(flag)) {
|
|
41
|
+
throw new CliUsageError(`Unknown setup flag: ${flag}`);
|
|
42
|
+
}
|
|
43
|
+
if (seen.has(flag))
|
|
44
|
+
throw new CliUsageError(`Duplicate setup flag: ${flag}`);
|
|
45
|
+
seen.add(flag);
|
|
46
|
+
if (flag === "--yes") {
|
|
47
|
+
yes = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (flag === "--json") {
|
|
51
|
+
json = true;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const raw = values[index + 1];
|
|
55
|
+
if (raw === undefined || raw.startsWith("--")) {
|
|
56
|
+
throw new CliUsageError(`${flag} requires a value.`);
|
|
57
|
+
}
|
|
58
|
+
index += 1;
|
|
59
|
+
if (flag === "--client") {
|
|
60
|
+
const parsed = parseAgentTarget(raw);
|
|
61
|
+
const normalized = raw.trim().toLowerCase();
|
|
62
|
+
if (parsed === "generic" &&
|
|
63
|
+
normalized !== "generic" &&
|
|
64
|
+
normalized !== "other")
|
|
65
|
+
throw new CliUsageError(`Unsupported Agent client: ${raw}`);
|
|
66
|
+
client = parsed;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (!paths.isAbsolute(raw)) {
|
|
70
|
+
throw new CliUsageError(`${flag} requires an absolute path.`);
|
|
71
|
+
}
|
|
72
|
+
const normalized = paths.normalize(raw);
|
|
73
|
+
if (flag === "--allowed-root")
|
|
74
|
+
allowedRoot = normalized;
|
|
75
|
+
if (flag === "--add-root")
|
|
76
|
+
addRoot = normalized;
|
|
77
|
+
}
|
|
78
|
+
if (allowedRoot !== undefined && addRoot !== undefined) {
|
|
79
|
+
throw new CliUsageError("--allowed-root and --add-root cannot be combined.");
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
...(client === undefined ? {} : { client }),
|
|
83
|
+
allowedRoots: allowedRoot === undefined ? [] : [allowedRoot],
|
|
84
|
+
addRoots: addRoot === undefined ? [] : [addRoot],
|
|
85
|
+
yes,
|
|
86
|
+
json,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export function parseCliArguments(argv, platform = process.platform) {
|
|
90
|
+
if (argv.length === 0)
|
|
91
|
+
return { command: "server" };
|
|
92
|
+
const [command, ...values] = argv;
|
|
93
|
+
if (command === "--help" || command === "-h" || command === "help") {
|
|
94
|
+
requireNoArguments("help", values);
|
|
95
|
+
return { command: "help" };
|
|
96
|
+
}
|
|
97
|
+
if (command === "--version" || command === "-v") {
|
|
98
|
+
requireNoArguments("version", values);
|
|
99
|
+
return { command: "version" };
|
|
100
|
+
}
|
|
101
|
+
if (command === "setup") {
|
|
102
|
+
return { command: "setup", arguments: parseSetupArguments(values, platform) };
|
|
103
|
+
}
|
|
104
|
+
if (command === "doctor") {
|
|
105
|
+
const flags = parseBooleanFlags("doctor", values, new Set(["--json"]));
|
|
106
|
+
return { command: "doctor", json: flags.has("--json") };
|
|
107
|
+
}
|
|
108
|
+
if (command === "clean") {
|
|
109
|
+
requireNoArguments("clean", values);
|
|
110
|
+
return { command: "clean" };
|
|
111
|
+
}
|
|
112
|
+
if (command === "uninstall") {
|
|
113
|
+
const flags = parseBooleanFlags("uninstall", values, new Set(["--yes", "--json"]));
|
|
114
|
+
if (!flags.has("--yes") || !flags.has("--json")) {
|
|
115
|
+
throw new CliUsageError("Uninstall requires: uninstall --yes --json");
|
|
116
|
+
}
|
|
117
|
+
return { command: "uninstall", yes: true, json: true };
|
|
118
|
+
}
|
|
119
|
+
throw new CliUsageError(`Unknown command: ${command}`);
|
|
120
|
+
}
|
package/dist/cli/doctor.d.ts
CHANGED
|
@@ -6,12 +6,53 @@ export interface HealthResult {
|
|
|
6
6
|
export interface DoctorOptions extends AgentConfigEnvironment {
|
|
7
7
|
readonly env: NodeJS.ProcessEnv;
|
|
8
8
|
readonly artifactRoot: string;
|
|
9
|
+
readonly cacheMode: "default" | "fallback";
|
|
9
10
|
readonly fetchImpl: typeof fetch;
|
|
10
11
|
readonly nodeVersion?: string;
|
|
11
12
|
readonly npmVersion?: string;
|
|
12
13
|
readonly packageVersion?: string;
|
|
13
14
|
}
|
|
15
|
+
export interface DoctorReport {
|
|
16
|
+
readonly package_version: string;
|
|
17
|
+
readonly node_version: string;
|
|
18
|
+
readonly npm_version: string;
|
|
19
|
+
readonly client_adapters: Record<string, {
|
|
20
|
+
readonly status: AgentConfigStatusForReport;
|
|
21
|
+
readonly version?: string;
|
|
22
|
+
}>;
|
|
23
|
+
readonly api_key: {
|
|
24
|
+
readonly status: "present" | "absent";
|
|
25
|
+
};
|
|
26
|
+
readonly allowed_roots: {
|
|
27
|
+
readonly count: number;
|
|
28
|
+
readonly safe: boolean;
|
|
29
|
+
};
|
|
30
|
+
readonly endpoints: {
|
|
31
|
+
readonly url_control: string;
|
|
32
|
+
readonly direct_upload: string;
|
|
33
|
+
};
|
|
34
|
+
readonly artifacts: {
|
|
35
|
+
readonly count: number;
|
|
36
|
+
readonly bytes: number;
|
|
37
|
+
readonly earliest_expiry?: string;
|
|
38
|
+
};
|
|
39
|
+
readonly cache: {
|
|
40
|
+
readonly mode: "default" | "fallback";
|
|
41
|
+
readonly safe: true;
|
|
42
|
+
};
|
|
43
|
+
readonly onboarding: {
|
|
44
|
+
readonly status: "current";
|
|
45
|
+
readonly first_registration_credits: number;
|
|
46
|
+
readonly free_daily_credits: number;
|
|
47
|
+
} | {
|
|
48
|
+
readonly status: "unavailable";
|
|
49
|
+
};
|
|
50
|
+
readonly reload_required: boolean;
|
|
51
|
+
}
|
|
52
|
+
type AgentConfigStatusForReport = "configured" | "not configured" | "invalid or unreadable";
|
|
14
53
|
export declare function checkCubeHealth(fetchImpl: typeof fetch, apiKey: string): Promise<string>;
|
|
15
54
|
export declare function checkIiisHealth(fetchImpl: typeof fetch): Promise<string>;
|
|
16
55
|
export declare function checkHealth(fetchImpl: typeof fetch, apiKey: string): Promise<HealthResult>;
|
|
17
|
-
export declare function runDoctor(options: DoctorOptions): Promise<
|
|
56
|
+
export declare function runDoctor(options: DoctorOptions): Promise<DoctorReport>;
|
|
57
|
+
export declare function renderDoctor(report: DoctorReport): string[];
|
|
58
|
+
export {};
|
package/dist/cli/doctor.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { constants as fsConstants } from "node:fs";
|
|
2
2
|
import { lstat, open, readdir } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { DEFAULT_CUBE_BASE_URL, GRANTED_STREAM_PROTOCOL_VERSION, MAX_FILE_BYTES, CUBE_GRANT_PROTOCOL_VERSION, } from "../constants.js";
|
|
4
|
+
import { BRIDGE_RELEASE_VERSION, DEFAULT_CUBE_BASE_URL, GRANTED_STREAM_PROTOCOL_VERSION, MAX_FILE_BYTES, CUBE_GRANT_PROTOCOL_VERSION, } from "../constants.js";
|
|
5
|
+
import { API_KEY_URL, getOnboardingPolicyWithTimeout, onboardingGuidance, } from "../onboarding-policy.js";
|
|
5
6
|
import { agentConfigPath, inspectAgentConfig, } from "./agent-config.js";
|
|
6
7
|
const CUBE_HEALTH_PATH = "/api/omni-reader/direct-upload/v1/health";
|
|
7
|
-
const
|
|
8
|
+
const GRANTED_UPLOAD_HEALTH_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/health";
|
|
8
9
|
function isHealthBody(value) {
|
|
9
10
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
10
11
|
return false;
|
|
@@ -29,16 +30,16 @@ export async function checkCubeHealth(fetchImpl, apiKey) {
|
|
|
29
30
|
const cubeUrl = new URL(CUBE_HEALTH_PATH, DEFAULT_CUBE_BASE_URL).toString();
|
|
30
31
|
const cube = await fetchHealth(fetchImpl, cubeUrl, `Bearer ${apiKey}`);
|
|
31
32
|
if (!cube.enabled || cube.protocol_version !== CUBE_GRANT_PROTOCOL_VERSION) {
|
|
32
|
-
throw new Error("
|
|
33
|
+
throw new Error("Omni URL control is disabled or incompatible");
|
|
33
34
|
}
|
|
34
35
|
return cube.protocol_version;
|
|
35
36
|
}
|
|
36
37
|
export async function checkIiisHealth(fetchImpl) {
|
|
37
|
-
const
|
|
38
|
-
if (!
|
|
39
|
-
throw new Error("
|
|
38
|
+
const granted = await fetchHealth(fetchImpl, GRANTED_UPLOAD_HEALTH_URL);
|
|
39
|
+
if (!granted.enabled || granted.protocol_version !== GRANTED_STREAM_PROTOCOL_VERSION) {
|
|
40
|
+
throw new Error("Omni direct upload is disabled or incompatible");
|
|
40
41
|
}
|
|
41
|
-
return
|
|
42
|
+
return granted.protocol_version;
|
|
42
43
|
}
|
|
43
44
|
export async function checkHealth(fetchImpl, apiKey) {
|
|
44
45
|
const [cubeProtocol, iiisProtocol] = await Promise.all([
|
|
@@ -83,7 +84,7 @@ async function artifactFacts(artifactRoot) {
|
|
|
83
84
|
}
|
|
84
85
|
catch (error) {
|
|
85
86
|
if (error.code === "ENOENT") {
|
|
86
|
-
return { count: 0, bytes: 0
|
|
87
|
+
return { count: 0, bytes: 0 };
|
|
87
88
|
}
|
|
88
89
|
throw error;
|
|
89
90
|
}
|
|
@@ -108,50 +109,122 @@ async function artifactFacts(artifactRoot) {
|
|
|
108
109
|
earliestExpiry = expiresAt;
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
: new Date(earliestExpiry).toISOString()
|
|
116
|
-
|
|
112
|
+
return {
|
|
113
|
+
count,
|
|
114
|
+
bytes,
|
|
115
|
+
...(count > 0 && !unknownExpiry && earliestExpiry !== undefined
|
|
116
|
+
? { expiry: new Date(earliestExpiry).toISOString() }
|
|
117
|
+
: {}),
|
|
118
|
+
};
|
|
117
119
|
}
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
function allowedRootFacts(options) {
|
|
121
|
+
const value = options.env.OMNI_ALLOWED_ROOTS?.trim() ?? "";
|
|
122
|
+
if (value === "")
|
|
123
|
+
return { count: 0, safe: true };
|
|
124
|
+
const paths = options.platform === "win32" ? path.win32 : path.posix;
|
|
125
|
+
const separator = options.platform === "win32" ? ";" : ":";
|
|
126
|
+
const roots = value.split(separator).filter((root) => root.length > 0);
|
|
127
|
+
return {
|
|
128
|
+
count: roots.length,
|
|
129
|
+
safe: roots.length > 0 && roots.every((root) => paths.isAbsolute(root)),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
async function clientAdapterFacts(options) {
|
|
133
|
+
const result = {};
|
|
126
134
|
for (const [label, target] of [
|
|
127
|
-
["
|
|
128
|
-
["
|
|
135
|
+
["hermes", "hermes"],
|
|
136
|
+
["cursor", "cursor"],
|
|
137
|
+
["claude_desktop", "claude-desktop"],
|
|
129
138
|
]) {
|
|
130
139
|
const configPath = agentConfigPath(target, options);
|
|
131
140
|
const status = configPath === undefined
|
|
132
141
|
? "not configured"
|
|
133
|
-
: await inspectAgentConfig(configPath, options);
|
|
134
|
-
|
|
142
|
+
: await inspectAgentConfig(configPath, options, target);
|
|
143
|
+
result[label] = {
|
|
144
|
+
status,
|
|
145
|
+
...(status === "configured" ? { version: BRIDGE_RELEASE_VERSION } : {}),
|
|
146
|
+
};
|
|
135
147
|
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
export async function runDoctor(options) {
|
|
151
|
+
const [clientAdapters, artifacts, onboarding] = await Promise.all([
|
|
152
|
+
clientAdapterFacts(options),
|
|
153
|
+
artifactFacts(options.artifactRoot),
|
|
154
|
+
getOnboardingPolicyWithTimeout(options.fetchImpl),
|
|
155
|
+
]);
|
|
156
|
+
let urlControl = "skipped (Cue API Key absent)";
|
|
136
157
|
if (options.env.CUE_API_KEY) {
|
|
137
158
|
try {
|
|
138
|
-
|
|
159
|
+
urlControl = await checkCubeHealth(options.fetchImpl, options.env.CUE_API_KEY);
|
|
139
160
|
}
|
|
140
161
|
catch {
|
|
141
|
-
|
|
162
|
+
urlControl = "unavailable or incompatible";
|
|
142
163
|
}
|
|
143
164
|
}
|
|
144
|
-
|
|
145
|
-
lines.push("Cube health: skipped (Cue API Key absent)");
|
|
146
|
-
}
|
|
165
|
+
let directUpload;
|
|
147
166
|
try {
|
|
148
|
-
|
|
167
|
+
directUpload = await checkIiisHealth(options.fetchImpl);
|
|
149
168
|
}
|
|
150
169
|
catch {
|
|
151
|
-
|
|
170
|
+
directUpload = "unavailable or incompatible";
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
package_version: options.packageVersion ?? "unknown",
|
|
174
|
+
node_version: options.nodeVersion ?? process.version,
|
|
175
|
+
npm_version: options.npmVersion ?? "unavailable",
|
|
176
|
+
client_adapters: clientAdapters,
|
|
177
|
+
api_key: { status: options.env.CUE_API_KEY ? "present" : "absent" },
|
|
178
|
+
allowed_roots: allowedRootFacts(options),
|
|
179
|
+
endpoints: {
|
|
180
|
+
url_control: urlControl,
|
|
181
|
+
direct_upload: directUpload,
|
|
182
|
+
},
|
|
183
|
+
artifacts: {
|
|
184
|
+
count: artifacts.count,
|
|
185
|
+
bytes: artifacts.bytes,
|
|
186
|
+
...(artifacts.expiry === undefined ? {} : { earliest_expiry: artifacts.expiry }),
|
|
187
|
+
},
|
|
188
|
+
cache: { mode: options.cacheMode, safe: true },
|
|
189
|
+
onboarding: onboarding === undefined
|
|
190
|
+
? { status: "unavailable" }
|
|
191
|
+
: {
|
|
192
|
+
status: "current",
|
|
193
|
+
first_registration_credits: onboarding.firstRegistrationCredits,
|
|
194
|
+
free_daily_credits: onboarding.freeDailyCredits,
|
|
195
|
+
},
|
|
196
|
+
reload_required: false,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
export function renderDoctor(report) {
|
|
200
|
+
const lines = [
|
|
201
|
+
`Node: ${report.node_version}`,
|
|
202
|
+
`npm: ${report.npm_version}`,
|
|
203
|
+
`Package: ${report.package_version}`,
|
|
204
|
+
`Cue API Key: ${report.api_key.status}`,
|
|
205
|
+
`Allowed roots: ${report.allowed_roots.count} (${report.allowed_roots.safe ? "safe" : "invalid"})`,
|
|
206
|
+
];
|
|
207
|
+
for (const [label, key] of [
|
|
208
|
+
["Hermes", "hermes"],
|
|
209
|
+
["Cursor", "cursor"],
|
|
210
|
+
["Claude Desktop", "claude_desktop"],
|
|
211
|
+
]) {
|
|
212
|
+
lines.push(`${label} config: ${report.client_adapters[key].status}`);
|
|
213
|
+
}
|
|
214
|
+
lines.push(`Omni control protocol: ${report.endpoints.url_control}`);
|
|
215
|
+
lines.push(`Omni direct upload protocol: ${report.endpoints.direct_upload}`);
|
|
216
|
+
lines.push(`Artifacts: ${report.artifacts.count} file(s), ${report.artifacts.bytes} byte(s)`);
|
|
217
|
+
lines.push(`Artifact expiry: ${report.artifacts.earliest_expiry ?? (report.artifacts.count === 0 ? "none" : "unknown")}`);
|
|
218
|
+
lines.push(`Cache: ${report.cache.mode}`);
|
|
219
|
+
if (report.api_key.status === "absent") {
|
|
220
|
+
const policy = report.onboarding.status === "current"
|
|
221
|
+
? {
|
|
222
|
+
apiKeyUrl: API_KEY_URL,
|
|
223
|
+
firstRegistrationCredits: report.onboarding.first_registration_credits,
|
|
224
|
+
freeDailyCredits: report.onboarding.free_daily_credits,
|
|
225
|
+
}
|
|
226
|
+
: undefined;
|
|
227
|
+
lines.push(...onboardingGuidance(policy).split("\n"));
|
|
152
228
|
}
|
|
153
|
-
const artifacts = await artifactFacts(options.artifactRoot);
|
|
154
|
-
lines.push(`Artifacts: ${artifacts.count} file(s), ${artifacts.bytes} byte(s)`);
|
|
155
|
-
lines.push(`Artifact expiry: ${artifacts.expiry}`);
|
|
156
229
|
return lines;
|
|
157
230
|
}
|
package/dist/cli/setup.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { type SetupArguments } from "./arguments.js";
|
|
1
2
|
import { type AgentConfigEnvironment } from "./agent-config.js";
|
|
2
3
|
export interface SetupOptions extends AgentConfigEnvironment {
|
|
3
4
|
readonly env: NodeJS.ProcessEnv;
|
|
4
5
|
readonly fetchImpl: typeof fetch;
|
|
5
6
|
readonly ask: (question: string) => Promise<string>;
|
|
6
7
|
readonly write: (text: string) => void;
|
|
8
|
+
readonly stdinIsTTY: boolean;
|
|
9
|
+
readonly arguments: SetupArguments;
|
|
7
10
|
}
|
|
8
11
|
export declare function runSetup(options: SetupOptions): Promise<void>;
|
package/dist/cli/setup.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { BRIDGE_RELEASE_VERSION } from "../constants.js";
|
|
3
|
+
import { getOnboardingPolicyWithTimeout, onboardingGuidance, } from "../onboarding-policy.js";
|
|
4
|
+
import { CliUsageError } from "./arguments.js";
|
|
5
|
+
import { configuredAllowedRoots, detectAgentTargets, parseAgentTarget, prepareAgentConfig, rollbackPreparedAgentConfig, verifyPreparedAgentConfig, writePreparedAgentConfig, } from "./agent-config.js";
|
|
3
6
|
import { checkHealth } from "./doctor.js";
|
|
4
7
|
function parseExtraRoots(input, environment) {
|
|
5
8
|
const separator = environment.platform === "win32" ? ";" : ":";
|
|
@@ -14,46 +17,128 @@ function parseExtraRoots(input, environment) {
|
|
|
14
17
|
? paths.join(environment.homeDirectory, value.slice(2))
|
|
15
18
|
: value;
|
|
16
19
|
if (!paths.isAbsolute(expanded)) {
|
|
17
|
-
throw new
|
|
20
|
+
throw new CliUsageError("Every additional allowed root must be an absolute path.");
|
|
18
21
|
}
|
|
19
22
|
return paths.normalize(expanded);
|
|
20
23
|
});
|
|
21
24
|
}
|
|
22
|
-
|
|
23
|
-
const labels = {
|
|
25
|
+
async function interactiveArguments(options) {
|
|
26
|
+
const labels = {
|
|
27
|
+
hermes: "Hermes",
|
|
28
|
+
cursor: "Cursor",
|
|
29
|
+
"claude-desktop": "Claude Desktop",
|
|
30
|
+
};
|
|
24
31
|
const detected = await detectAgentTargets(options);
|
|
25
32
|
const detectedLabel = detected.length === 0
|
|
26
33
|
? "none"
|
|
27
34
|
: detected.map((target) => labels[target]).join(", ");
|
|
28
|
-
const selected = await options.ask(`Agent (Cursor / Claude Desktop / Other; Detected: ${detectedLabel}): `);
|
|
35
|
+
const selected = await options.ask(`Agent (Hermes / Cursor / Claude Desktop / Other; Detected: ${detectedLabel}): `);
|
|
29
36
|
const target = parseAgentTarget(selected);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const rootInput = await options.ask("Additional allowed roots (optional): ");
|
|
38
|
+
return { target, roots: parseExtraRoots(rootInput, options) };
|
|
39
|
+
}
|
|
40
|
+
async function selectedTargetAndRoots(options) {
|
|
41
|
+
const requested = options.arguments;
|
|
42
|
+
if (requested.client === undefined) {
|
|
43
|
+
if (!options.stdinIsTTY) {
|
|
44
|
+
throw new CliUsageError("Non-interactive setup requires: setup --client hermes --allowed-root <absolute-path> --yes --json");
|
|
45
|
+
}
|
|
46
|
+
const selected = await interactiveArguments(options);
|
|
47
|
+
return { ...selected, interactive: true };
|
|
48
|
+
}
|
|
49
|
+
if (!options.stdinIsTTY && !requested.yes) {
|
|
50
|
+
throw new CliUsageError("Non-interactive setup requires --yes.");
|
|
51
|
+
}
|
|
52
|
+
const existing = await configuredAllowedRoots(requested.client, options);
|
|
53
|
+
const roots = requested.allowedRoots.length > 0
|
|
54
|
+
? requested.allowedRoots
|
|
55
|
+
: requested.addRoots.length > 0
|
|
56
|
+
? [...new Set([...existing, ...requested.addRoots])]
|
|
57
|
+
: existing;
|
|
58
|
+
return { target: requested.client, roots, interactive: !requested.yes };
|
|
59
|
+
}
|
|
60
|
+
function writePreview(options, prepared) {
|
|
33
61
|
options.write(`Target: ${prepared.displayPath}\n`);
|
|
34
62
|
options.write("Before:\n");
|
|
35
63
|
options.write(`${JSON.stringify(prepared.before, null, 2)}\n`);
|
|
36
64
|
options.write("After:\n");
|
|
37
65
|
options.write(`${JSON.stringify(prepared.after, null, 2)}\n`);
|
|
66
|
+
}
|
|
67
|
+
async function confirmSetup(options, prepared, interactive) {
|
|
68
|
+
if (!interactive)
|
|
69
|
+
return true;
|
|
70
|
+
writePreview(options, prepared);
|
|
38
71
|
const confirmation = (await options.ask("Apply this user-scope configuration? Type yes: ")).trim().toLowerCase();
|
|
39
|
-
if (confirmation
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
72
|
+
if (confirmation === "yes")
|
|
73
|
+
return true;
|
|
74
|
+
options.write("No changes written.\n");
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
async function requireApiKey(options) {
|
|
44
78
|
const apiKey = options.env.CUE_API_KEY ?? "";
|
|
45
|
-
if (apiKey.length
|
|
46
|
-
|
|
79
|
+
if (apiKey.length > 0)
|
|
80
|
+
return apiKey;
|
|
81
|
+
const policy = await getOnboardingPolicyWithTimeout(options.fetchImpl);
|
|
82
|
+
throw new Error(onboardingGuidance(policy));
|
|
83
|
+
}
|
|
84
|
+
async function validateConfiguredEnvironment(options, prepared, apiKey) {
|
|
85
|
+
try {
|
|
86
|
+
await checkHealth(options.fetchImpl, apiKey);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
try {
|
|
90
|
+
await rollbackPreparedAgentConfig(prepared);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
throw new Error("Omni 安全解析环境验证失败,且无法确认 Agent 配置已自动恢复;请停止重试并检查 user-scope 配置。");
|
|
94
|
+
}
|
|
95
|
+
throw new Error("Omni 安全解析环境验证失败;原 Agent 配置已自动恢复。");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function writeSuccess(options, prepared, roots) {
|
|
99
|
+
if (options.arguments.json) {
|
|
100
|
+
options.write(`${JSON.stringify({
|
|
101
|
+
status: prepared.configPath === undefined ? "manual_configuration" : "configured",
|
|
102
|
+
target: prepared.target,
|
|
103
|
+
package: "@cueai/omni-reader-mcp",
|
|
104
|
+
version: BRIDGE_RELEASE_VERSION,
|
|
105
|
+
config_path: prepared.displayPath,
|
|
106
|
+
allowed_roots: roots.length,
|
|
107
|
+
reload: prepared.reload,
|
|
108
|
+
})}\n`);
|
|
109
|
+
return;
|
|
47
110
|
}
|
|
48
111
|
options.write("Cue API Key: present\n");
|
|
49
|
-
await checkHealth(options.fetchImpl, apiKey);
|
|
50
112
|
if (prepared.configPath === undefined) {
|
|
51
113
|
options.write("Generic user-scope configuration:\n");
|
|
52
|
-
options.write(`${JSON.stringify({
|
|
114
|
+
options.write(`${JSON.stringify({
|
|
115
|
+
mcpServers: { "omni-reader": prepared.entry },
|
|
116
|
+
}, null, 2)}\n`);
|
|
53
117
|
}
|
|
54
118
|
else {
|
|
55
|
-
await writePreparedAgentConfig(prepared);
|
|
56
119
|
options.write(`Wrote ${prepared.displayPath}\n`);
|
|
120
|
+
options.write(`${prepared.reload}\n`);
|
|
57
121
|
}
|
|
58
122
|
options.write("用 Omni 解析 ./report.pdf\n");
|
|
59
123
|
}
|
|
124
|
+
export async function runSetup(options) {
|
|
125
|
+
const selected = await selectedTargetAndRoots(options);
|
|
126
|
+
const prepared = await prepareAgentConfig(selected.target, selected.roots, options);
|
|
127
|
+
if (!await confirmSetup(options, prepared, selected.interactive))
|
|
128
|
+
return;
|
|
129
|
+
await verifyPreparedAgentConfig(prepared);
|
|
130
|
+
const apiKey = await requireApiKey(options);
|
|
131
|
+
if (prepared.configPath === undefined) {
|
|
132
|
+
try {
|
|
133
|
+
await checkHealth(options.fetchImpl, apiKey);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
throw new Error("Omni 安全解析环境验证失败;未写入 Agent 配置。");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
await writePreparedAgentConfig(prepared);
|
|
141
|
+
await validateConfiguredEnvironment(options, prepared, apiKey);
|
|
142
|
+
}
|
|
143
|
+
writeSuccess(options, prepared, selected.roots);
|
|
144
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type AgentConfigEnvironment } from "./agent-config.js";
|
|
2
|
+
export interface UninstallOptions extends AgentConfigEnvironment {
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
readonly write: (text: string) => void;
|
|
5
|
+
}
|
|
6
|
+
export declare function runUninstall(options: UninstallOptions): Promise<void>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { uninstallAgentConfig, } from "./agent-config.js";
|
|
2
|
+
export async function runUninstall(options) {
|
|
3
|
+
const flags = [...options.args].sort();
|
|
4
|
+
if (flags.length !== 2 ||
|
|
5
|
+
flags[0] !== "--json" ||
|
|
6
|
+
flags[1] !== "--yes") {
|
|
7
|
+
throw new Error("Uninstall requires: uninstall --yes --json");
|
|
8
|
+
}
|
|
9
|
+
const results = [];
|
|
10
|
+
for (const target of ["hermes", "cursor", "claude-desktop"]) {
|
|
11
|
+
const result = await uninstallAgentConfig(target, options);
|
|
12
|
+
if (result !== undefined)
|
|
13
|
+
results.push(result);
|
|
14
|
+
}
|
|
15
|
+
if (results.length === 0) {
|
|
16
|
+
options.write(`${JSON.stringify({
|
|
17
|
+
status: "not_installed",
|
|
18
|
+
restored_remote: false,
|
|
19
|
+
artifacts_preserved: true,
|
|
20
|
+
source_files_unchanged: true,
|
|
21
|
+
})}\n`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const response = {
|
|
25
|
+
status: "uninstalled",
|
|
26
|
+
restored_remote: results.every((result) => result.restoredRemote),
|
|
27
|
+
artifacts_preserved: true,
|
|
28
|
+
source_files_unchanged: true,
|
|
29
|
+
};
|
|
30
|
+
if (results.length === 1) {
|
|
31
|
+
response.target = results[0].target;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
response.targets = results.map((result) => result.target);
|
|
35
|
+
}
|
|
36
|
+
options.write(`${JSON.stringify(response)}\n`);
|
|
37
|
+
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,3 +5,10 @@ export declare const RESULT_CHUNK_MAX_BYTES = 65536;
|
|
|
5
5
|
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
|
+
export declare const DEFAULT_IIIS_GRANTED_BASE_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/";
|
|
9
|
+
export declare const BRIDGE_RELEASE_VERSION = "1.1.0";
|
|
10
|
+
export declare const REMOTE_OMNI_MCP_URL = "https://mcp.cuecue.cn/api/omni-reader/mcp/";
|
|
11
|
+
export declare const FOREGROUND_BUDGET_MS = 15000;
|
|
12
|
+
export declare const STATUS_LONG_POLL_MAX_MS = 20000;
|
|
13
|
+
export declare const STATUS_POLL_AFTER_SECONDS = 5;
|
|
14
|
+
export declare const DELIVERY_TTL_SECONDS = 600;
|
package/dist/constants.js
CHANGED
|
@@ -5,3 +5,10 @@ export const RESULT_CHUNK_MAX_BYTES = 65536;
|
|
|
5
5
|
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
|
+
export const DEFAULT_IIIS_GRANTED_BASE_URL = "https://cubefile.ai.iiis.co:9443/omni/granted/";
|
|
9
|
+
export const BRIDGE_RELEASE_VERSION = "1.1.0";
|
|
10
|
+
export const REMOTE_OMNI_MCP_URL = "https://mcp.cuecue.cn/api/omni-reader/mcp/";
|
|
11
|
+
export const FOREGROUND_BUDGET_MS = 15_000;
|
|
12
|
+
export const STATUS_LONG_POLL_MAX_MS = 20_000;
|
|
13
|
+
export const STATUS_POLL_AFTER_SECONDS = 5;
|
|
14
|
+
export const DELIVERY_TTL_SECONDS = 600;
|
package/dist/cube-client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { BRIDGE_RELEASE_VERSION } from "./constants.js";
|
|
1
2
|
import { OperationJournal } from "./operation-journal.js";
|
|
2
3
|
declare const BRIDGE_PACKAGE = "@cueai/omni-reader-mcp";
|
|
3
|
-
declare const BRIDGE_VERSION = "1.0.2";
|
|
4
4
|
export interface GrantRequestInput {
|
|
5
5
|
readonly contentLength: number;
|
|
6
6
|
readonly contentType: string;
|
|
@@ -35,7 +35,7 @@ interface GrantRequestBody {
|
|
|
35
35
|
readonly output: "markdown";
|
|
36
36
|
readonly bridge: {
|
|
37
37
|
readonly package: typeof BRIDGE_PACKAGE;
|
|
38
|
-
readonly version: typeof
|
|
38
|
+
readonly version: typeof BRIDGE_RELEASE_VERSION;
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
export declare function grantRequestHash(body: GrantRequestBody): string;
|
|
@@ -43,6 +43,8 @@ export declare function createClientRequestId(): string;
|
|
|
43
43
|
export declare class CubeGrantClient {
|
|
44
44
|
#private;
|
|
45
45
|
constructor(options: CubeGrantClientOptions);
|
|
46
|
-
createGrant(input: GrantRequestInput, clientRequestId: string, signal?: AbortSignal
|
|
46
|
+
createGrant(input: GrantRequestInput, clientRequestId: string, signal?: AbortSignal, options?: {
|
|
47
|
+
journal?: boolean;
|
|
48
|
+
}): Promise<GrantedOperation>;
|
|
47
49
|
}
|
|
48
50
|
export {};
|