@cueai/omni-reader-mcp 1.0.2 → 1.1.1
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 +1324 -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
package/dist/index.js
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFile as execFileCallback } from "node:child_process";
|
|
3
3
|
import { readFile, realpath } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
import { createInterface } from "node:readline/promises";
|
|
6
7
|
import { stdin, stdout as processStdout } from "node:process";
|
|
7
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
|
-
import { ArtifactStore,
|
|
9
|
+
import { ArtifactStore, selectArtifactRoot, } from "./artifact-store.js";
|
|
10
|
+
import { CliUsageError, parseCliArguments } from "./cli/arguments.js";
|
|
9
11
|
import { runClean } from "./cli/clean.js";
|
|
10
|
-
import { runDoctor } from "./cli/doctor.js";
|
|
12
|
+
import { renderDoctor, runDoctor } from "./cli/doctor.js";
|
|
11
13
|
import { runSetup } from "./cli/setup.js";
|
|
14
|
+
import { runUninstall } from "./cli/uninstall.js";
|
|
12
15
|
import { CubeGrantClient } from "./cube-client.js";
|
|
13
16
|
import { IiisClient } from "./iiis-client.js";
|
|
17
|
+
import { createLocalParseOperationManager } from "./operation-manager.js";
|
|
14
18
|
import { OperationJournal } from "./operation-journal.js";
|
|
15
19
|
import { splitAllowedRoots } from "./path-security.js";
|
|
20
|
+
import { HttpRemoteOmniClient } from "./remote-client.js";
|
|
16
21
|
import { createOmniMcpServer } from "./server.js";
|
|
17
22
|
function helpText() {
|
|
18
23
|
return [
|
|
19
|
-
"Usage: omni-reader-mcp [setup|doctor|clean|--help|--version]",
|
|
24
|
+
"Usage: omni-reader-mcp [setup|doctor|clean|uninstall|--help|--version]",
|
|
20
25
|
"",
|
|
21
26
|
"No arguments start the stdio MCP server.",
|
|
22
27
|
"setup Configure a supported user-scope Agent",
|
|
23
28
|
"doctor Check local configuration and protocol health",
|
|
24
29
|
"clean Delete Bridge-created local artifacts and expired records",
|
|
30
|
+
"uninstall Restore a trusted URL-only Agent entry without deleting artifacts",
|
|
25
31
|
"",
|
|
26
32
|
].join("\n");
|
|
27
33
|
}
|
|
@@ -60,16 +66,26 @@ async function installedNpmVersion(env) {
|
|
|
60
66
|
});
|
|
61
67
|
});
|
|
62
68
|
}
|
|
69
|
+
async function artifactSelectionFor(options, env, homeDirectory, cwd, platform) {
|
|
70
|
+
if (options.artifactRoot !== undefined) {
|
|
71
|
+
return { mode: "default", rootDirectory: options.artifactRoot };
|
|
72
|
+
}
|
|
73
|
+
return await selectArtifactRoot({
|
|
74
|
+
platform,
|
|
75
|
+
homeDirectory,
|
|
76
|
+
env,
|
|
77
|
+
projectDirectory: cwd,
|
|
78
|
+
temporaryDirectory: options.temporaryDirectory ?? tmpdir(),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
63
81
|
export async function startStdioServer(options = {}) {
|
|
64
82
|
const env = options.env ?? process.env;
|
|
83
|
+
const homeDirectory = options.homeDirectory ?? (await import("node:os")).homedir();
|
|
65
84
|
const cwd = options.cwd ?? process.cwd();
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
homeDirectory: options.homeDirectory,
|
|
69
|
-
env,
|
|
70
|
-
});
|
|
85
|
+
const platform = options.platform ?? process.platform;
|
|
86
|
+
const artifactSelection = await artifactSelectionFor(options, env, homeDirectory, cwd, platform);
|
|
71
87
|
const artifactStore = await ArtifactStore.open({
|
|
72
|
-
rootDirectory:
|
|
88
|
+
rootDirectory: artifactSelection.rootDirectory,
|
|
73
89
|
projectDirectory: cwd,
|
|
74
90
|
now: options.now,
|
|
75
91
|
});
|
|
@@ -79,12 +95,33 @@ export async function startStdioServer(options = {}) {
|
|
|
79
95
|
environment: { CUE_API_KEY: env.CUE_API_KEY },
|
|
80
96
|
fetchImpl: options.fetchImpl,
|
|
81
97
|
});
|
|
98
|
+
const iiisClient = new IiisClient({
|
|
99
|
+
fetchImpl: options.fetchImpl,
|
|
100
|
+
operationBaseUrl: options.iiisOperationBaseUrl,
|
|
101
|
+
});
|
|
102
|
+
const extraRoots = splitAllowedRoots(env.OMNI_ALLOWED_ROOTS);
|
|
103
|
+
const remoteClient = new HttpRemoteOmniClient({
|
|
104
|
+
apiKey: env.CUE_API_KEY,
|
|
105
|
+
fetchImpl: options.fetchImpl,
|
|
106
|
+
});
|
|
107
|
+
const operationManager = createLocalParseOperationManager({
|
|
108
|
+
journal,
|
|
109
|
+
workspace: cwd,
|
|
110
|
+
extraRoots,
|
|
111
|
+
cubeClient,
|
|
112
|
+
iiisClient,
|
|
113
|
+
artifactStore,
|
|
114
|
+
remoteClient,
|
|
115
|
+
now: options.now,
|
|
116
|
+
});
|
|
82
117
|
const server = createOmniMcpServer({
|
|
83
118
|
workspace: cwd,
|
|
84
|
-
extraRoots
|
|
119
|
+
extraRoots,
|
|
85
120
|
cubeClient,
|
|
86
|
-
iiisClient
|
|
121
|
+
iiisClient,
|
|
87
122
|
artifactStore,
|
|
123
|
+
operationManager,
|
|
124
|
+
remoteClient,
|
|
88
125
|
});
|
|
89
126
|
const close = async () => {
|
|
90
127
|
await server.close().catch(() => undefined);
|
|
@@ -99,7 +136,6 @@ export async function runCli(args, options = {}) {
|
|
|
99
136
|
const homeDirectory = options.homeDirectory ?? (await import("node:os")).homedir();
|
|
100
137
|
const cwd = options.cwd ?? process.cwd();
|
|
101
138
|
const platform = options.platform ?? process.platform;
|
|
102
|
-
const artifactRoot = options.artifactRoot ?? defaultArtifactRoot({ platform, homeDirectory, env });
|
|
103
139
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
104
140
|
const output = options.stdout ?? process.stdout;
|
|
105
141
|
const errorOutput = options.stderr ?? process.stderr;
|
|
@@ -107,57 +143,82 @@ export async function runCli(args, options = {}) {
|
|
|
107
143
|
const write = (text) => { output.write(text); };
|
|
108
144
|
const packageVersion = options.packageVersion ?? await installedPackageVersion();
|
|
109
145
|
try {
|
|
110
|
-
|
|
146
|
+
const parsed = parseCliArguments(args, platform);
|
|
147
|
+
if (parsed.command === "server") {
|
|
111
148
|
await (options.startServer ?? (() => startStdioServer({
|
|
112
149
|
...options,
|
|
113
150
|
env,
|
|
114
151
|
homeDirectory,
|
|
115
152
|
cwd,
|
|
116
153
|
platform,
|
|
117
|
-
artifactRoot,
|
|
118
154
|
fetchImpl,
|
|
119
155
|
})))();
|
|
120
156
|
return 0;
|
|
121
157
|
}
|
|
122
|
-
|
|
123
|
-
if (command === "--help" || command === "-h" || command === "help") {
|
|
158
|
+
if (parsed.command === "help") {
|
|
124
159
|
write(helpText());
|
|
125
160
|
return 0;
|
|
126
161
|
}
|
|
127
|
-
if (command === "
|
|
162
|
+
if (parsed.command === "version") {
|
|
128
163
|
write(`${packageVersion}\n`);
|
|
129
164
|
return 0;
|
|
130
165
|
}
|
|
131
|
-
if (command === "setup") {
|
|
132
|
-
await runSetup({
|
|
166
|
+
if (parsed.command === "setup") {
|
|
167
|
+
await runSetup({
|
|
168
|
+
env,
|
|
169
|
+
homeDirectory,
|
|
170
|
+
platform,
|
|
171
|
+
fetchImpl,
|
|
172
|
+
ask,
|
|
173
|
+
write,
|
|
174
|
+
stdinIsTTY: options.stdinIsTTY ?? stdin.isTTY === true,
|
|
175
|
+
arguments: parsed.arguments,
|
|
176
|
+
});
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
if (parsed.command === "uninstall") {
|
|
180
|
+
await runUninstall({
|
|
181
|
+
args: [
|
|
182
|
+
...(parsed.yes ? ["--yes"] : []),
|
|
183
|
+
...(parsed.json ? ["--json"] : []),
|
|
184
|
+
],
|
|
185
|
+
env,
|
|
186
|
+
homeDirectory,
|
|
187
|
+
platform,
|
|
188
|
+
write,
|
|
189
|
+
});
|
|
133
190
|
return 0;
|
|
134
191
|
}
|
|
135
|
-
if (command === "doctor") {
|
|
136
|
-
const
|
|
192
|
+
if (parsed.command === "doctor") {
|
|
193
|
+
const artifactSelection = await artifactSelectionFor(options, env, homeDirectory, cwd, platform);
|
|
194
|
+
const report = await runDoctor({
|
|
137
195
|
env,
|
|
138
196
|
homeDirectory,
|
|
139
197
|
platform,
|
|
140
|
-
artifactRoot,
|
|
198
|
+
artifactRoot: artifactSelection.rootDirectory,
|
|
199
|
+
cacheMode: artifactSelection.mode,
|
|
141
200
|
fetchImpl,
|
|
142
201
|
npmVersion: options.npmVersion ?? await installedNpmVersion(env),
|
|
143
202
|
packageVersion,
|
|
144
203
|
});
|
|
145
|
-
write(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (command === "clean") {
|
|
149
|
-
const result = await runClean({ artifactRoot, projectDirectory: cwd, now: options.now });
|
|
150
|
-
write(`Removed ${result.removed} Bridge cache item(s).\n`);
|
|
204
|
+
write(parsed.json
|
|
205
|
+
? `${JSON.stringify(report)}\n`
|
|
206
|
+
: `${renderDoctor(report).join("\n")}\n`);
|
|
151
207
|
return 0;
|
|
152
208
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
209
|
+
const artifactSelection = await artifactSelectionFor(options, env, homeDirectory, cwd, platform);
|
|
210
|
+
const result = await runClean({
|
|
211
|
+
artifactRoot: artifactSelection.rootDirectory,
|
|
212
|
+
projectDirectory: cwd,
|
|
213
|
+
now: options.now,
|
|
214
|
+
});
|
|
215
|
+
write(`Removed ${result.removed} Bridge cache item(s).\n`);
|
|
216
|
+
return 0;
|
|
156
217
|
}
|
|
157
218
|
catch (error) {
|
|
158
219
|
const message = error instanceof Error ? error.message : "The Bridge command failed.";
|
|
159
220
|
errorOutput.write(`Error: ${message}\n`);
|
|
160
|
-
return 1;
|
|
221
|
+
return error instanceof CliUsageError ? error.exitCode : 1;
|
|
161
222
|
}
|
|
162
223
|
}
|
|
163
224
|
async function main() {
|
package/dist/multipart-body.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const ONBOARDING_POLICY_URL = "https://cuecue.cn/api/v1/billing/public/onboarding-policy";
|
|
2
|
+
export declare const API_KEY_URL = "https://cuecue.cn/api-key";
|
|
3
|
+
export interface OnboardingPolicy {
|
|
4
|
+
readonly apiKeyUrl: typeof API_KEY_URL;
|
|
5
|
+
readonly firstRegistrationCredits: number;
|
|
6
|
+
readonly freeDailyCredits: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function getOnboardingPolicy(fetchImpl: typeof fetch, signal: AbortSignal): Promise<OnboardingPolicy | undefined>;
|
|
9
|
+
export declare function onboardingGuidance(policy: OnboardingPolicy | undefined): string;
|
|
10
|
+
export declare function getOnboardingPolicyWithTimeout(fetchImpl: typeof fetch, timeoutMs?: number): Promise<OnboardingPolicy | undefined>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export const ONBOARDING_POLICY_URL = "https://cuecue.cn/api/v1/billing/public/onboarding-policy";
|
|
2
|
+
export const API_KEY_URL = "https://cuecue.cn/api-key";
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function boundedCredits(value) {
|
|
7
|
+
return Number.isInteger(value) && Number(value) > 0 && Number(value) <= 1_000_000;
|
|
8
|
+
}
|
|
9
|
+
function normalizeOnboardingPolicy(value) {
|
|
10
|
+
if (!isRecord(value))
|
|
11
|
+
return undefined;
|
|
12
|
+
if (value.api_key_url !== API_KEY_URL ||
|
|
13
|
+
!boundedCredits(value.first_registration) ||
|
|
14
|
+
!boundedCredits(value.free_daily))
|
|
15
|
+
return undefined;
|
|
16
|
+
return {
|
|
17
|
+
apiKeyUrl: API_KEY_URL,
|
|
18
|
+
firstRegistrationCredits: value.first_registration,
|
|
19
|
+
freeDailyCredits: value.free_daily,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export async function getOnboardingPolicy(fetchImpl, signal) {
|
|
23
|
+
try {
|
|
24
|
+
const response = await fetchImpl(ONBOARDING_POLICY_URL, {
|
|
25
|
+
method: "GET",
|
|
26
|
+
headers: { accept: "application/json" },
|
|
27
|
+
signal,
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok)
|
|
30
|
+
return undefined;
|
|
31
|
+
return normalizeOnboardingPolicy(await response.json());
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function onboardingGuidance(policy) {
|
|
38
|
+
const creditLine = policy === undefined
|
|
39
|
+
? `新账号有免费积分可体验,请前往 ${API_KEY_URL} 注册并创建 API Key。`
|
|
40
|
+
: `新账号首次注册赠送 ${policy.firstRegistrationCredits} 积分,免费账号每日有 ${policy.freeDailyCredits} 积分免费额度,可先体验 Omni,无需预先充值。`;
|
|
41
|
+
return [
|
|
42
|
+
"使用 Omni 需要配置 Cue API Key。",
|
|
43
|
+
`获取 API Key:${API_KEY_URL}`,
|
|
44
|
+
creditLine,
|
|
45
|
+
"创建后,请在 Agent 的安全密钥或环境设置中配置 CUE_API_KEY。请勿把 API Key 粘贴到对话中。",
|
|
46
|
+
].join("\n");
|
|
47
|
+
}
|
|
48
|
+
export async function getOnboardingPolicyWithTimeout(fetchImpl, timeoutMs = 3_000) {
|
|
49
|
+
const controller = new AbortController();
|
|
50
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
51
|
+
timer.unref?.();
|
|
52
|
+
try {
|
|
53
|
+
return await getOnboardingPolicy(fetchImpl, controller.signal);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,13 +1,55 @@
|
|
|
1
|
-
export type JournalState = "GRANT_PENDING" | "GRANT_ISSUED";
|
|
1
|
+
export type JournalState = "CREATED" | "GRANT_PENDING" | "GRANT_ISSUED" | "UPLOADING" | "PROCESSING" | "RESULT_READY" | "ACK_PENDING" | "CLEANUP_PENDING" | "COMPLETED" | "FAILED" | "CANCELED" | "EXPIRED";
|
|
2
|
+
export type JournalProgressUnit = "page" | "sheet" | "slide" | "frame" | "segment";
|
|
3
|
+
export type JournalCleanupState = "not_created" | "in_use" | "pending" | "deleted";
|
|
4
|
+
export type JournalDeliveryState = "not_created" | "pending" | "deleted_after_ack";
|
|
5
|
+
export interface JournalProgress {
|
|
6
|
+
readonly unit: JournalProgressUnit;
|
|
7
|
+
readonly completed: number;
|
|
8
|
+
readonly total: number;
|
|
9
|
+
}
|
|
2
10
|
export interface JournalRecord {
|
|
3
11
|
readonly clientRequestId: string;
|
|
4
12
|
readonly requestHash: string;
|
|
13
|
+
readonly sourceLocatorHash: string | null;
|
|
14
|
+
readonly sourceKind: "local" | "url";
|
|
5
15
|
readonly operationId: string | null;
|
|
6
16
|
readonly operationToken: string | null;
|
|
7
17
|
readonly uploadUrl: string | null;
|
|
8
18
|
readonly state: JournalState;
|
|
9
19
|
readonly createdAt: string;
|
|
20
|
+
readonly updatedAt: string;
|
|
10
21
|
readonly expiresAt: string | null;
|
|
22
|
+
readonly stage: string | null;
|
|
23
|
+
readonly progressPercent: number;
|
|
24
|
+
readonly progress: JournalProgress | null;
|
|
25
|
+
readonly fileUploaded: boolean;
|
|
26
|
+
readonly parserStarted: boolean;
|
|
27
|
+
readonly billed: boolean;
|
|
28
|
+
readonly contentReleased: boolean;
|
|
29
|
+
readonly processingCopy: JournalCleanupState;
|
|
30
|
+
readonly temporaryData: JournalCleanupState;
|
|
31
|
+
readonly deliveryResult: JournalDeliveryState;
|
|
32
|
+
readonly resultId: string | null;
|
|
33
|
+
readonly resultExpiresAt: string | null;
|
|
34
|
+
readonly errorCode: string | null;
|
|
35
|
+
}
|
|
36
|
+
export interface JournalPatch {
|
|
37
|
+
readonly operationId?: string | null;
|
|
38
|
+
readonly operationToken?: string | null;
|
|
39
|
+
readonly expiresAt?: string | null;
|
|
40
|
+
readonly stage?: string | null;
|
|
41
|
+
readonly progressPercent?: number;
|
|
42
|
+
readonly progress?: JournalProgress | null;
|
|
43
|
+
readonly fileUploaded?: boolean;
|
|
44
|
+
readonly parserStarted?: boolean;
|
|
45
|
+
readonly billed?: boolean;
|
|
46
|
+
readonly contentReleased?: boolean;
|
|
47
|
+
readonly processingCopy?: JournalCleanupState;
|
|
48
|
+
readonly temporaryData?: JournalCleanupState;
|
|
49
|
+
readonly deliveryResult?: JournalDeliveryState;
|
|
50
|
+
readonly resultId?: string | null;
|
|
51
|
+
readonly resultExpiresAt?: string | null;
|
|
52
|
+
readonly errorCode?: string | null;
|
|
11
53
|
}
|
|
12
54
|
export interface IssuedGrantJournalFields {
|
|
13
55
|
readonly operationId: string;
|
|
@@ -22,6 +64,13 @@ export interface OperationJournalOptions {
|
|
|
22
64
|
export declare class OperationJournal {
|
|
23
65
|
#private;
|
|
24
66
|
constructor(options?: OperationJournalOptions);
|
|
67
|
+
beginIntent(clientRequestId: string, requestHash: string, sourceKind?: "local" | "url", sourceLocatorHash?: string | null): Promise<JournalRecord>;
|
|
68
|
+
transition(clientRequestId: string, expectedState: JournalState, nextState: JournalState, patch: JournalPatch): Promise<JournalRecord>;
|
|
69
|
+
loadByRequestId(clientRequestId: string): Promise<JournalRecord | null>;
|
|
70
|
+
loadByOperationId(operationId: string): Promise<JournalRecord | null>;
|
|
71
|
+
loadLatestByRequestHash(requestHash: string): Promise<JournalRecord | null>;
|
|
72
|
+
loadLatestBySourceLocatorHash(sourceLocatorHash: string): Promise<JournalRecord | null>;
|
|
73
|
+
listRecoverable(): Promise<JournalRecord[]>;
|
|
25
74
|
begin(clientRequestId: string, requestHash: string): Promise<JournalRecord>;
|
|
26
75
|
markGrantIssued(clientRequestId: string, fields: IssuedGrantJournalFields): Promise<JournalRecord>;
|
|
27
76
|
load(clientRequestId: string): Promise<JournalRecord | null>;
|