@claudeink/mcp-server 1.0.0 → 2.0.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/dist/cli.js +780 -986
- package/dist/index.js +526 -745
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -24510,11 +24510,11 @@ var require_core = __commonJS({
|
|
|
24510
24510
|
Ajv2.ValidationError = validation_error_1.default;
|
|
24511
24511
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
24512
24512
|
exports2.default = Ajv2;
|
|
24513
|
-
function checkOptions(checkOpts, options2, msg,
|
|
24513
|
+
function checkOptions(checkOpts, options2, msg, log2 = "error") {
|
|
24514
24514
|
for (const key in checkOpts) {
|
|
24515
24515
|
const opt = key;
|
|
24516
24516
|
if (opt in options2)
|
|
24517
|
-
this.logger[
|
|
24517
|
+
this.logger[log2](`${msg}: option ${key}. ${checkOpts[opt]}`);
|
|
24518
24518
|
}
|
|
24519
24519
|
}
|
|
24520
24520
|
function getSchEnv(keyRef) {
|
|
@@ -27350,8 +27350,8 @@ var init_server2 = __esm({
|
|
|
27350
27350
|
this._loggingLevels = /* @__PURE__ */ new Map();
|
|
27351
27351
|
this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
|
|
27352
27352
|
this.isMessageIgnored = (level, sessionId) => {
|
|
27353
|
-
const
|
|
27354
|
-
return
|
|
27353
|
+
const currentLevel2 = this._loggingLevels.get(sessionId);
|
|
27354
|
+
return currentLevel2 ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel2) : false;
|
|
27355
27355
|
};
|
|
27356
27356
|
this._capabilities = options2?.capabilities ?? {};
|
|
27357
27357
|
this._instructions = options2?.instructions;
|
|
@@ -28746,6 +28746,281 @@ var init_stdio2 = __esm({
|
|
|
28746
28746
|
}
|
|
28747
28747
|
});
|
|
28748
28748
|
|
|
28749
|
+
// src/lib/state.ts
|
|
28750
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
28751
|
+
import { join } from "path";
|
|
28752
|
+
function setWorkDir(dir) {
|
|
28753
|
+
_workDirCache = dir;
|
|
28754
|
+
}
|
|
28755
|
+
function getWorkDir() {
|
|
28756
|
+
return _workDirCache || process.env.CLAUDEINK_WORK_DIR || process.cwd();
|
|
28757
|
+
}
|
|
28758
|
+
function getClaudeinkDir() {
|
|
28759
|
+
return join(getWorkDir(), ".claudeink");
|
|
28760
|
+
}
|
|
28761
|
+
function getStatePath() {
|
|
28762
|
+
return join(getClaudeinkDir(), "state.json");
|
|
28763
|
+
}
|
|
28764
|
+
async function ensureDir() {
|
|
28765
|
+
await mkdir(getClaudeinkDir(), { recursive: true });
|
|
28766
|
+
}
|
|
28767
|
+
async function readState() {
|
|
28768
|
+
const statePath = getStatePath();
|
|
28769
|
+
let raw;
|
|
28770
|
+
try {
|
|
28771
|
+
raw = await readFile(statePath, "utf-8");
|
|
28772
|
+
} catch {
|
|
28773
|
+
const state = { ...DEFAULT_STATE };
|
|
28774
|
+
state.config.workflowDir = getWorkDir();
|
|
28775
|
+
return state;
|
|
28776
|
+
}
|
|
28777
|
+
try {
|
|
28778
|
+
const parsed = JSON.parse(raw);
|
|
28779
|
+
const state = {
|
|
28780
|
+
credentials: parsed.credentials ?? null,
|
|
28781
|
+
config: { ...DEFAULT_STATE.config, ...parsed.config },
|
|
28782
|
+
tagQueue: parsed.tagQueue ?? { ...DEFAULT_STATE.tagQueue },
|
|
28783
|
+
lastSyncAt: parsed.lastSyncAt ?? ""
|
|
28784
|
+
};
|
|
28785
|
+
state.config.workflowDir = getWorkDir();
|
|
28786
|
+
return state;
|
|
28787
|
+
} catch {
|
|
28788
|
+
const backupPath = statePath + ".corrupted." + Date.now();
|
|
28789
|
+
try {
|
|
28790
|
+
await writeFile(backupPath, raw, "utf-8");
|
|
28791
|
+
} catch {
|
|
28792
|
+
}
|
|
28793
|
+
console.error(`[ClaudeInk] state.json corrupted, backed up to ${backupPath}`);
|
|
28794
|
+
const state = { ...DEFAULT_STATE };
|
|
28795
|
+
state.config.workflowDir = getWorkDir();
|
|
28796
|
+
return state;
|
|
28797
|
+
}
|
|
28798
|
+
}
|
|
28799
|
+
async function writeState(state) {
|
|
28800
|
+
await ensureDir();
|
|
28801
|
+
await writeFile(getStatePath(), JSON.stringify(state, null, 2), "utf-8");
|
|
28802
|
+
await chmod(getStatePath(), 384);
|
|
28803
|
+
}
|
|
28804
|
+
async function getCredentials() {
|
|
28805
|
+
const state = await readState();
|
|
28806
|
+
if (!state.credentials) return null;
|
|
28807
|
+
return {
|
|
28808
|
+
licenseKey: state.credentials.licenseKey,
|
|
28809
|
+
token: state.credentials.token,
|
|
28810
|
+
userId: state.credentials.userId,
|
|
28811
|
+
plan: state.credentials.plan,
|
|
28812
|
+
expiresAt: state.credentials.expiresAt
|
|
28813
|
+
};
|
|
28814
|
+
}
|
|
28815
|
+
async function getConfig() {
|
|
28816
|
+
const state = await readState();
|
|
28817
|
+
return state.config;
|
|
28818
|
+
}
|
|
28819
|
+
async function updateLastSyncAt() {
|
|
28820
|
+
const state = await readState();
|
|
28821
|
+
state.lastSyncAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
28822
|
+
await writeState(state);
|
|
28823
|
+
}
|
|
28824
|
+
async function addToTagQueue(item) {
|
|
28825
|
+
const state = await readState();
|
|
28826
|
+
if (state.tagQueue.queue.some((q) => q.knowledgeId === item.knowledgeId)) return;
|
|
28827
|
+
state.tagQueue.queue.push(item);
|
|
28828
|
+
await writeState(state);
|
|
28829
|
+
}
|
|
28830
|
+
var _workDirCache, DEFAULT_STATE;
|
|
28831
|
+
var init_state = __esm({
|
|
28832
|
+
"src/lib/state.ts"() {
|
|
28833
|
+
"use strict";
|
|
28834
|
+
_workDirCache = null;
|
|
28835
|
+
DEFAULT_STATE = {
|
|
28836
|
+
credentials: null,
|
|
28837
|
+
config: {
|
|
28838
|
+
apiBaseUrl: "https://app.claudeink.com",
|
|
28839
|
+
workflowDir: "",
|
|
28840
|
+
logLevel: "INFO"
|
|
28841
|
+
},
|
|
28842
|
+
tagQueue: {
|
|
28843
|
+
queue: [],
|
|
28844
|
+
failed: []
|
|
28845
|
+
},
|
|
28846
|
+
lastSyncAt: ""
|
|
28847
|
+
};
|
|
28848
|
+
}
|
|
28849
|
+
});
|
|
28850
|
+
|
|
28851
|
+
// src/lib/logger.ts
|
|
28852
|
+
import { appendFile, mkdir as mkdir2 } from "fs/promises";
|
|
28853
|
+
import { join as join2 } from "path";
|
|
28854
|
+
function setLogLevel(level) {
|
|
28855
|
+
currentLevel = level;
|
|
28856
|
+
}
|
|
28857
|
+
async function log(level, scope, message) {
|
|
28858
|
+
if (LEVELS[level] > LEVELS[currentLevel]) return;
|
|
28859
|
+
const dir = join2(getClaudeinkDir(), "logs");
|
|
28860
|
+
await mkdir2(dir, { recursive: true });
|
|
28861
|
+
const date3 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
28862
|
+
const line = `${(/* @__PURE__ */ new Date()).toISOString()} [${level}] ${scope} | ${message}
|
|
28863
|
+
`;
|
|
28864
|
+
await appendFile(join2(dir, `mcp-${date3}.log`), line);
|
|
28865
|
+
console.error(`[ClaudeInk] ${line.trim()}`);
|
|
28866
|
+
}
|
|
28867
|
+
var currentLevel, LEVELS;
|
|
28868
|
+
var init_logger = __esm({
|
|
28869
|
+
"src/lib/logger.ts"() {
|
|
28870
|
+
"use strict";
|
|
28871
|
+
init_state();
|
|
28872
|
+
currentLevel = "INFO";
|
|
28873
|
+
LEVELS = { ERROR: 0, WARN: 1, INFO: 2, DEBUG: 3 };
|
|
28874
|
+
}
|
|
28875
|
+
});
|
|
28876
|
+
|
|
28877
|
+
// src/tools/sync.ts
|
|
28878
|
+
async function sync2(input) {
|
|
28879
|
+
if (input.workDir) setWorkDir(input.workDir);
|
|
28880
|
+
const creds = await getCredentials();
|
|
28881
|
+
if (!creds?.token) {
|
|
28882
|
+
return { success: false, message: "\u672A\u6FC0\u6D3B\uFF0C\u8BF7\u5148\u4F7F\u7528 workflow.init \u6FC0\u6D3B License" };
|
|
28883
|
+
}
|
|
28884
|
+
return doPull(creds.token);
|
|
28885
|
+
}
|
|
28886
|
+
async function doPull(token) {
|
|
28887
|
+
const config2 = await getConfig();
|
|
28888
|
+
try {
|
|
28889
|
+
const res = await fetch(`${config2.apiBaseUrl}/api/sync/pull`, {
|
|
28890
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
28891
|
+
});
|
|
28892
|
+
if (!res.ok) {
|
|
28893
|
+
if (res.status === 404) {
|
|
28894
|
+
return { success: true, message: "\u4E91\u7AEF\u65E0\u6570\u636E" };
|
|
28895
|
+
}
|
|
28896
|
+
await log("ERROR", "ink.sync", `pull failed: HTTP ${res.status}`);
|
|
28897
|
+
return { success: false, message: `\u62C9\u53D6\u5931\u8D25: HTTP ${res.status}` };
|
|
28898
|
+
}
|
|
28899
|
+
await updateLastSyncAt();
|
|
28900
|
+
await log("INFO", "ink.sync", "pull completed");
|
|
28901
|
+
return {
|
|
28902
|
+
success: true,
|
|
28903
|
+
message: "\u2705 \u540C\u6B65\u5B8C\u6210"
|
|
28904
|
+
};
|
|
28905
|
+
} catch (err) {
|
|
28906
|
+
return { success: false, message: `\u540C\u6B65\u5931\u8D25: ${err instanceof Error ? err.message : err}` };
|
|
28907
|
+
}
|
|
28908
|
+
}
|
|
28909
|
+
async function syncPull(input) {
|
|
28910
|
+
if (input.workDir) setWorkDir(input.workDir);
|
|
28911
|
+
const creds = await getCredentials();
|
|
28912
|
+
if (!creds?.token) {
|
|
28913
|
+
return { success: false, message: "\u672A\u6FC0\u6D3B" };
|
|
28914
|
+
}
|
|
28915
|
+
return doPull(creds.token);
|
|
28916
|
+
}
|
|
28917
|
+
var syncSchema;
|
|
28918
|
+
var init_sync = __esm({
|
|
28919
|
+
"src/tools/sync.ts"() {
|
|
28920
|
+
"use strict";
|
|
28921
|
+
init_zod();
|
|
28922
|
+
init_state();
|
|
28923
|
+
init_logger();
|
|
28924
|
+
syncSchema = external_exports.object({
|
|
28925
|
+
workDir: external_exports.string().optional().describe("\u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684 workflowDir\uFF09")
|
|
28926
|
+
});
|
|
28927
|
+
}
|
|
28928
|
+
});
|
|
28929
|
+
|
|
28930
|
+
// src/tools/workflow.ts
|
|
28931
|
+
import { mkdir as mkdir3, access, unlink } from "fs/promises";
|
|
28932
|
+
import { join as join3 } from "path";
|
|
28933
|
+
async function workflowInit(input) {
|
|
28934
|
+
const cwd = input.workDir;
|
|
28935
|
+
const results = [];
|
|
28936
|
+
try {
|
|
28937
|
+
setWorkDir(cwd);
|
|
28938
|
+
const claudeinkDir = join3(cwd, ".claudeink");
|
|
28939
|
+
await mkdir3(join3(claudeinkDir, "knowledge"), { recursive: true });
|
|
28940
|
+
results.push("\u2705 \u77E5\u8BC6\u5E93\u76EE\u5F55\u5DF2\u521B\u5EFA");
|
|
28941
|
+
const state = await readState();
|
|
28942
|
+
state.config.workflowDir = cwd;
|
|
28943
|
+
const oldCredsPath = join3(claudeinkDir, "credentials.json");
|
|
28944
|
+
try {
|
|
28945
|
+
await access(oldCredsPath);
|
|
28946
|
+
await unlink(oldCredsPath);
|
|
28947
|
+
results.push("\u{1F9F9} \u5DF2\u6E05\u7406\u65E7\u7248 credentials.json");
|
|
28948
|
+
} catch {
|
|
28949
|
+
}
|
|
28950
|
+
let activated = false;
|
|
28951
|
+
if (input.licenseKey) {
|
|
28952
|
+
try {
|
|
28953
|
+
const res = await fetch(`${DEFAULT_API_BASE_URL}/api/auth/activate`, {
|
|
28954
|
+
method: "POST",
|
|
28955
|
+
headers: { "Content-Type": "application/json" },
|
|
28956
|
+
body: JSON.stringify({ key: input.licenseKey })
|
|
28957
|
+
});
|
|
28958
|
+
const data = await res.json();
|
|
28959
|
+
if (data.userId) {
|
|
28960
|
+
state.credentials = {
|
|
28961
|
+
licenseKey: input.licenseKey,
|
|
28962
|
+
token: data.token,
|
|
28963
|
+
userId: data.userId,
|
|
28964
|
+
plan: data.plan,
|
|
28965
|
+
expiresAt: data.expiresAt
|
|
28966
|
+
};
|
|
28967
|
+
results.push(`\u2705 License \u6FC0\u6D3B\u6210\u529F\uFF08\u5957\u9910: ${data.plan}\uFF09`);
|
|
28968
|
+
activated = true;
|
|
28969
|
+
} else {
|
|
28970
|
+
results.push(`\u26A0\uFE0F License \u6FC0\u6D3B\u5931\u8D25: ${JSON.stringify(data)}`);
|
|
28971
|
+
}
|
|
28972
|
+
} catch (err) {
|
|
28973
|
+
results.push(`\u26A0\uFE0F \u6FC0\u6D3B\u7F51\u7EDC\u9519\u8BEF: ${err instanceof Error ? err.message : err}`);
|
|
28974
|
+
}
|
|
28975
|
+
}
|
|
28976
|
+
await writeState(state);
|
|
28977
|
+
results.push("\u2705 state.json");
|
|
28978
|
+
if (activated) {
|
|
28979
|
+
try {
|
|
28980
|
+
const pullResult = await syncPull({ workDir: cwd });
|
|
28981
|
+
if (pullResult.success) {
|
|
28982
|
+
results.push("\u2705 \u5DF2\u4ECE\u4E91\u7AEF\u540C\u6B65\u6570\u636E");
|
|
28983
|
+
} else {
|
|
28984
|
+
results.push("\u2139\uFE0F \u4E91\u7AEF\u65E0\u5DF2\u6709\u6570\u636E");
|
|
28985
|
+
}
|
|
28986
|
+
} catch {
|
|
28987
|
+
results.push("\u2139\uFE0F \u4E91\u7AEF\u540C\u6B65\u8DF3\u8FC7");
|
|
28988
|
+
}
|
|
28989
|
+
}
|
|
28990
|
+
return {
|
|
28991
|
+
success: true,
|
|
28992
|
+
message: [
|
|
28993
|
+
"\u{1F389} ClaudeInk \u77E5\u8BC6\u5E93\u521D\u59CB\u5316\u5B8C\u6210\uFF01",
|
|
28994
|
+
"",
|
|
28995
|
+
...results,
|
|
28996
|
+
"",
|
|
28997
|
+
"\u{1F3AF} \u4E0B\u4E00\u6B65\uFF1A",
|
|
28998
|
+
"1. \u5728\u5BF9\u8BDD\u4E2D\u8BF4\u300C\u5E2E\u6211\u5B58\u4E00\u4E0B\u300D\u4FDD\u5B58\u6709\u4EF7\u503C\u5185\u5BB9",
|
|
28999
|
+
"2. \u7528\u300C\u627E\u4E00\u4E0B\u5173\u4E8E XX \u7684\u300D\u68C0\u7D22\u77E5\u8BC6\u5E93"
|
|
29000
|
+
].join("\n")
|
|
29001
|
+
};
|
|
29002
|
+
} catch (err) {
|
|
29003
|
+
return {
|
|
29004
|
+
success: false,
|
|
29005
|
+
message: `\u521D\u59CB\u5316\u5931\u8D25: ${err instanceof Error ? err.message : err}`
|
|
29006
|
+
};
|
|
29007
|
+
}
|
|
29008
|
+
}
|
|
29009
|
+
var DEFAULT_API_BASE_URL, workflowInitSchema;
|
|
29010
|
+
var init_workflow = __esm({
|
|
29011
|
+
"src/tools/workflow.ts"() {
|
|
29012
|
+
"use strict";
|
|
29013
|
+
init_zod();
|
|
29014
|
+
init_state();
|
|
29015
|
+
init_sync();
|
|
29016
|
+
DEFAULT_API_BASE_URL = "https://app.claudeink.com";
|
|
29017
|
+
workflowInitSchema = external_exports.object({
|
|
29018
|
+
workDir: external_exports.string().describe("\u5DE5\u4F5C\u6D41\u521D\u59CB\u5316\u76EE\u6807\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09"),
|
|
29019
|
+
licenseKey: external_exports.string().optional().describe("License Key\uFF08\u53EF\u9009\uFF0C\u4F20\u5165\u5219\u81EA\u52A8\u6FC0\u6D3B\uFF09")
|
|
29020
|
+
});
|
|
29021
|
+
}
|
|
29022
|
+
});
|
|
29023
|
+
|
|
28749
29024
|
// ../node_modules/kind-of/index.js
|
|
28750
29025
|
var require_kind_of = __commonJS({
|
|
28751
29026
|
"../node_modules/kind-of/index.js"(exports2, module2) {
|
|
@@ -32230,110 +32505,9 @@ var require_gray_matter = __commonJS({
|
|
|
32230
32505
|
}
|
|
32231
32506
|
});
|
|
32232
32507
|
|
|
32233
|
-
// src/lib/state.ts
|
|
32234
|
-
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
32235
|
-
import { join } from "path";
|
|
32236
|
-
function setWorkDir(dir) {
|
|
32237
|
-
_workDirCache = dir;
|
|
32238
|
-
}
|
|
32239
|
-
function getWorkDir() {
|
|
32240
|
-
return _workDirCache || process.env.CLAUDEINK_WORK_DIR || process.cwd();
|
|
32241
|
-
}
|
|
32242
|
-
function getClaudeinkDir() {
|
|
32243
|
-
return join(getWorkDir(), ".claudeink");
|
|
32244
|
-
}
|
|
32245
|
-
function getStatePath() {
|
|
32246
|
-
return join(getClaudeinkDir(), "state.json");
|
|
32247
|
-
}
|
|
32248
|
-
async function ensureDir() {
|
|
32249
|
-
await mkdir(getClaudeinkDir(), { recursive: true });
|
|
32250
|
-
}
|
|
32251
|
-
async function readState() {
|
|
32252
|
-
const statePath = getStatePath();
|
|
32253
|
-
let raw;
|
|
32254
|
-
try {
|
|
32255
|
-
raw = await readFile(statePath, "utf-8");
|
|
32256
|
-
} catch {
|
|
32257
|
-
const state = { ...DEFAULT_STATE };
|
|
32258
|
-
state.config.workflowDir = getWorkDir();
|
|
32259
|
-
return state;
|
|
32260
|
-
}
|
|
32261
|
-
try {
|
|
32262
|
-
const parsed = JSON.parse(raw);
|
|
32263
|
-
const state = {
|
|
32264
|
-
credentials: parsed.credentials ?? null,
|
|
32265
|
-
config: { ...DEFAULT_STATE.config, ...parsed.config },
|
|
32266
|
-
tagQueue: parsed.tagQueue ?? { ...DEFAULT_STATE.tagQueue },
|
|
32267
|
-
lastSyncAt: parsed.lastSyncAt ?? ""
|
|
32268
|
-
};
|
|
32269
|
-
state.config.workflowDir = getWorkDir();
|
|
32270
|
-
return state;
|
|
32271
|
-
} catch {
|
|
32272
|
-
const backupPath = statePath + ".corrupted." + Date.now();
|
|
32273
|
-
try {
|
|
32274
|
-
await writeFile(backupPath, raw, "utf-8");
|
|
32275
|
-
} catch {
|
|
32276
|
-
}
|
|
32277
|
-
console.error(`[ClaudeInk] state.json corrupted, backed up to ${backupPath}`);
|
|
32278
|
-
const state = { ...DEFAULT_STATE };
|
|
32279
|
-
state.config.workflowDir = getWorkDir();
|
|
32280
|
-
return state;
|
|
32281
|
-
}
|
|
32282
|
-
}
|
|
32283
|
-
async function writeState(state) {
|
|
32284
|
-
await ensureDir();
|
|
32285
|
-
await writeFile(getStatePath(), JSON.stringify(state, null, 2), "utf-8");
|
|
32286
|
-
await chmod(getStatePath(), 384);
|
|
32287
|
-
}
|
|
32288
|
-
async function getCredentials() {
|
|
32289
|
-
const state = await readState();
|
|
32290
|
-
if (!state.credentials) return null;
|
|
32291
|
-
return {
|
|
32292
|
-
licenseKey: state.credentials.licenseKey,
|
|
32293
|
-
token: state.credentials.token,
|
|
32294
|
-
userId: state.credentials.userId,
|
|
32295
|
-
plan: state.credentials.plan,
|
|
32296
|
-
expiresAt: state.credentials.expiresAt
|
|
32297
|
-
};
|
|
32298
|
-
}
|
|
32299
|
-
async function getConfig() {
|
|
32300
|
-
const state = await readState();
|
|
32301
|
-
return state.config;
|
|
32302
|
-
}
|
|
32303
|
-
async function updateLastSyncAt() {
|
|
32304
|
-
const state = await readState();
|
|
32305
|
-
state.lastSyncAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
32306
|
-
await writeState(state);
|
|
32307
|
-
}
|
|
32308
|
-
async function addToTagQueue(item) {
|
|
32309
|
-
const state = await readState();
|
|
32310
|
-
if (state.tagQueue.queue.some((q) => q.knowledgeId === item.knowledgeId)) return;
|
|
32311
|
-
state.tagQueue.queue.push(item);
|
|
32312
|
-
await writeState(state);
|
|
32313
|
-
}
|
|
32314
|
-
var _workDirCache, DEFAULT_STATE;
|
|
32315
|
-
var init_state = __esm({
|
|
32316
|
-
"src/lib/state.ts"() {
|
|
32317
|
-
"use strict";
|
|
32318
|
-
_workDirCache = null;
|
|
32319
|
-
DEFAULT_STATE = {
|
|
32320
|
-
credentials: null,
|
|
32321
|
-
config: {
|
|
32322
|
-
apiBaseUrl: "https://app.claudeink.com",
|
|
32323
|
-
workflowDir: ""
|
|
32324
|
-
},
|
|
32325
|
-
tagQueue: {
|
|
32326
|
-
queue: [],
|
|
32327
|
-
failed: []
|
|
32328
|
-
},
|
|
32329
|
-
lastSyncAt: ""
|
|
32330
|
-
};
|
|
32331
|
-
}
|
|
32332
|
-
});
|
|
32333
|
-
|
|
32334
32508
|
// src/lib/knowledge.ts
|
|
32335
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as
|
|
32336
|
-
import { join as
|
|
32509
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir4, unlink as unlink2 } from "fs/promises";
|
|
32510
|
+
import { join as join4 } from "path";
|
|
32337
32511
|
function withIndexLock(fn) {
|
|
32338
32512
|
const prev = _lockPromise;
|
|
32339
32513
|
let resolve;
|
|
@@ -32343,10 +32517,10 @@ function withIndexLock(fn) {
|
|
|
32343
32517
|
return prev.then(fn).finally(() => resolve());
|
|
32344
32518
|
}
|
|
32345
32519
|
function getKnowledgeDir() {
|
|
32346
|
-
return
|
|
32520
|
+
return join4(getWorkDir(), ".claudeink", "knowledge");
|
|
32347
32521
|
}
|
|
32348
32522
|
function getIndexPath() {
|
|
32349
|
-
return
|
|
32523
|
+
return join4(getWorkDir(), ".claudeink", "knowledge", "index.json");
|
|
32350
32524
|
}
|
|
32351
32525
|
async function generateIdInternal(index) {
|
|
32352
32526
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -32379,17 +32553,17 @@ async function readIndex() {
|
|
|
32379
32553
|
async function saveIndex(index) {
|
|
32380
32554
|
index.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
32381
32555
|
const dir = getKnowledgeDir();
|
|
32382
|
-
await
|
|
32556
|
+
await mkdir4(dir, { recursive: true });
|
|
32383
32557
|
await writeFile2(getIndexPath(), JSON.stringify(index, null, 2), "utf-8");
|
|
32384
32558
|
}
|
|
32385
32559
|
async function writeKnowledgeFile(meta, content) {
|
|
32386
32560
|
const now = /* @__PURE__ */ new Date();
|
|
32387
32561
|
const monthDir = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
32388
|
-
const dir =
|
|
32389
|
-
await
|
|
32562
|
+
const dir = join4(getKnowledgeDir(), monthDir);
|
|
32563
|
+
await mkdir4(dir, { recursive: true });
|
|
32390
32564
|
const slug = toSlug(meta.title) || meta.id;
|
|
32391
32565
|
const filename = `${now.toISOString().slice(0, 10)}-${slug}.md`;
|
|
32392
|
-
const filePath =
|
|
32566
|
+
const filePath = join4(dir, filename);
|
|
32393
32567
|
const frontmatter = {
|
|
32394
32568
|
id: meta.id,
|
|
32395
32569
|
title: meta.title,
|
|
@@ -32402,13 +32576,13 @@ async function writeKnowledgeFile(meta, content) {
|
|
|
32402
32576
|
if (meta.url) frontmatter.url = meta.url;
|
|
32403
32577
|
const output = import_gray_matter.default.stringify(content, frontmatter);
|
|
32404
32578
|
await writeFile2(filePath, output, "utf-8");
|
|
32405
|
-
return
|
|
32579
|
+
return join4(monthDir, filename);
|
|
32406
32580
|
}
|
|
32407
32581
|
async function readKnowledgeFile(id) {
|
|
32408
32582
|
const index = await readIndex();
|
|
32409
32583
|
const entry = index.entries[id];
|
|
32410
32584
|
if (!entry) return null;
|
|
32411
|
-
const filePath =
|
|
32585
|
+
const filePath = join4(getKnowledgeDir(), entry.file_path);
|
|
32412
32586
|
try {
|
|
32413
32587
|
const raw = await readFile2(filePath, "utf-8");
|
|
32414
32588
|
const { data, content } = (0, import_gray_matter.default)(raw);
|
|
@@ -32493,9 +32667,9 @@ async function deleteKnowledgeFile(id) {
|
|
|
32493
32667
|
const index = await readIndex();
|
|
32494
32668
|
const entry = index.entries[id];
|
|
32495
32669
|
if (!entry) return false;
|
|
32496
|
-
const filePath =
|
|
32670
|
+
const filePath = join4(getKnowledgeDir(), entry.file_path);
|
|
32497
32671
|
try {
|
|
32498
|
-
await
|
|
32672
|
+
await unlink2(filePath);
|
|
32499
32673
|
} catch {
|
|
32500
32674
|
}
|
|
32501
32675
|
delete index.entries[id];
|
|
@@ -32503,55 +32677,6 @@ async function deleteKnowledgeFile(id) {
|
|
|
32503
32677
|
return true;
|
|
32504
32678
|
});
|
|
32505
32679
|
}
|
|
32506
|
-
function searchKnowledge(index, filters) {
|
|
32507
|
-
let entries = Object.values(index.entries);
|
|
32508
|
-
if (filters.tags && filters.tags.length > 0) {
|
|
32509
|
-
const filterTags = filters.tags.map((t) => t.toLowerCase());
|
|
32510
|
-
entries = entries.filter(
|
|
32511
|
-
(e) => e.tags.some((t) => filterTags.includes(t.toLowerCase()))
|
|
32512
|
-
);
|
|
32513
|
-
}
|
|
32514
|
-
if (filters.category) {
|
|
32515
|
-
entries = entries.filter((e) => e.category === filters.category);
|
|
32516
|
-
}
|
|
32517
|
-
if (filters.date_from) {
|
|
32518
|
-
entries = entries.filter((e) => e.created_at >= filters.date_from);
|
|
32519
|
-
}
|
|
32520
|
-
if (filters.date_to) {
|
|
32521
|
-
entries = entries.filter((e) => e.created_at <= filters.date_to);
|
|
32522
|
-
}
|
|
32523
|
-
if (filters.query) {
|
|
32524
|
-
const q = filters.query.toLowerCase();
|
|
32525
|
-
entries = entries.map((e) => {
|
|
32526
|
-
let score = 0;
|
|
32527
|
-
if (e.title.toLowerCase().includes(q)) score += 10;
|
|
32528
|
-
if (e.preview.toLowerCase().includes(q)) score += 5;
|
|
32529
|
-
if (e.tags.some((t) => t.toLowerCase().includes(q))) score += 3;
|
|
32530
|
-
return { ...e, _score: score };
|
|
32531
|
-
}).filter((e) => e._score > 0).sort((a, b) => b._score - a._score);
|
|
32532
|
-
} else {
|
|
32533
|
-
entries.sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
32534
|
-
}
|
|
32535
|
-
const total = entries.length;
|
|
32536
|
-
const limit = filters.limit || 10;
|
|
32537
|
-
const results = entries.slice(0, limit).map((e) => ({
|
|
32538
|
-
id: e.id,
|
|
32539
|
-
title: e.title,
|
|
32540
|
-
tags: e.tags,
|
|
32541
|
-
category: e.category,
|
|
32542
|
-
created_at: e.created_at,
|
|
32543
|
-
preview: e.preview
|
|
32544
|
-
}));
|
|
32545
|
-
return { results, total };
|
|
32546
|
-
}
|
|
32547
|
-
async function readMultipleKnowledgeFiles(ids) {
|
|
32548
|
-
const results = [];
|
|
32549
|
-
for (const id of ids) {
|
|
32550
|
-
const file = await readKnowledgeFile(id);
|
|
32551
|
-
if (file) results.push(file);
|
|
32552
|
-
}
|
|
32553
|
-
return results;
|
|
32554
|
-
}
|
|
32555
32680
|
function getAllTags(index) {
|
|
32556
32681
|
const tagCounts = {};
|
|
32557
32682
|
for (const entry of Object.values(index.entries)) {
|
|
@@ -32570,7 +32695,7 @@ async function renameTag(oldTag, newTag) {
|
|
|
32570
32695
|
if (idx !== -1) {
|
|
32571
32696
|
entry.tags[idx] = newTag;
|
|
32572
32697
|
count++;
|
|
32573
|
-
const filePath =
|
|
32698
|
+
const filePath = join4(getKnowledgeDir(), entry.file_path);
|
|
32574
32699
|
try {
|
|
32575
32700
|
const raw = await readFile2(filePath, "utf-8");
|
|
32576
32701
|
const { data, content } = (0, import_gray_matter.default)(raw);
|
|
@@ -32605,7 +32730,7 @@ async function mergeTags(sourceTags, targetTag) {
|
|
|
32605
32730
|
}
|
|
32606
32731
|
entry.tags = newTags;
|
|
32607
32732
|
count++;
|
|
32608
|
-
const filePath =
|
|
32733
|
+
const filePath = join4(getKnowledgeDir(), entry.file_path);
|
|
32609
32734
|
try {
|
|
32610
32735
|
const raw = await readFile2(filePath, "utf-8");
|
|
32611
32736
|
const { data, content } = (0, import_gray_matter.default)(raw);
|
|
@@ -32645,6 +32770,7 @@ async function doPush(partial2) {
|
|
|
32645
32770
|
knowledge: partial2.knowledge || [],
|
|
32646
32771
|
crawlerSources: partial2.crawlerSources || []
|
|
32647
32772
|
};
|
|
32773
|
+
await log("DEBUG", "push", `payload: ${partial2.knowledge?.length || 0} knowledge, ${partial2.crawlerSources?.length || 0} sources`);
|
|
32648
32774
|
try {
|
|
32649
32775
|
await fetch(`${config2.apiBaseUrl}/api/sync/batch`, {
|
|
32650
32776
|
method: "POST",
|
|
@@ -32655,742 +32781,172 @@ async function doPush(partial2) {
|
|
|
32655
32781
|
body: JSON.stringify(payload)
|
|
32656
32782
|
});
|
|
32657
32783
|
} catch (err) {
|
|
32658
|
-
|
|
32784
|
+
await log("WARN", "push", `failed: ${err instanceof Error ? err.message : err}`);
|
|
32659
32785
|
}
|
|
32660
32786
|
}
|
|
32661
32787
|
var init_push = __esm({
|
|
32662
32788
|
"src/lib/push.ts"() {
|
|
32663
32789
|
"use strict";
|
|
32664
32790
|
init_state();
|
|
32791
|
+
init_logger();
|
|
32665
32792
|
}
|
|
32666
32793
|
});
|
|
32667
32794
|
|
|
32668
|
-
// src/tools/
|
|
32795
|
+
// src/tools/ink.ts
|
|
32669
32796
|
import { readFile as readFile3 } from "fs/promises";
|
|
32670
|
-
import {
|
|
32671
|
-
|
|
32672
|
-
import { execSync } from "child_process";
|
|
32673
|
-
async function sourceCrawl(input) {
|
|
32674
|
-
const config2 = await getConfig();
|
|
32675
|
-
const crawlerDir = join3(config2.workflowDir || process.cwd(), "tools", "crawler");
|
|
32676
|
-
const configPath = join3(crawlerDir, "config.json");
|
|
32677
|
-
let crawlerConfig;
|
|
32797
|
+
import { extname } from "path";
|
|
32798
|
+
async function inkSave(input) {
|
|
32678
32799
|
try {
|
|
32679
|
-
|
|
32680
|
-
|
|
32681
|
-
|
|
32682
|
-
|
|
32683
|
-
|
|
32684
|
-
|
|
32685
|
-
|
|
32686
|
-
|
|
32687
|
-
|
|
32800
|
+
if (input.id) {
|
|
32801
|
+
const result = await updateKnowledgeFile(input.id, {
|
|
32802
|
+
title: input.title,
|
|
32803
|
+
content: input.content,
|
|
32804
|
+
tags: input.tags,
|
|
32805
|
+
category: input.category
|
|
32806
|
+
});
|
|
32807
|
+
if (!result) {
|
|
32808
|
+
return { success: false, message: `\u672A\u627E\u5230 ID \u4E3A ${input.id} \u7684\u77E5\u8BC6\u7247\u6BB5` };
|
|
32809
|
+
}
|
|
32810
|
+
fireAndForgetPush({
|
|
32811
|
+
knowledge: [{
|
|
32812
|
+
id: result.meta.id,
|
|
32813
|
+
title: result.meta.title,
|
|
32814
|
+
tags: result.meta.tags,
|
|
32815
|
+
category: result.meta.category,
|
|
32816
|
+
source_type: result.meta.source_type,
|
|
32817
|
+
url: result.meta.url,
|
|
32818
|
+
created_at: result.meta.created_at,
|
|
32819
|
+
updated_at: result.meta.updated_at
|
|
32820
|
+
}]
|
|
32821
|
+
});
|
|
32822
|
+
await log("INFO", "ink.save", `updated id=${input.id} title="${input.title}"`);
|
|
32823
|
+
return {
|
|
32824
|
+
success: true,
|
|
32825
|
+
message: `\u5DF2\u66F4\u65B0\u300C${result.meta.title}\u300D`,
|
|
32826
|
+
data: { id: result.meta.id }
|
|
32827
|
+
};
|
|
32828
|
+
}
|
|
32829
|
+
const { id } = await saveKnowledge({
|
|
32830
|
+
content: input.content,
|
|
32831
|
+
title: input.title,
|
|
32832
|
+
tags: input.tags,
|
|
32833
|
+
category: input.category,
|
|
32834
|
+
source_type: input.source_type,
|
|
32835
|
+
url: input.url
|
|
32836
|
+
});
|
|
32837
|
+
fireAndForgetPush({
|
|
32838
|
+
knowledge: [{
|
|
32839
|
+
id,
|
|
32840
|
+
title: input.title,
|
|
32841
|
+
tags: input.tags,
|
|
32842
|
+
category: input.category,
|
|
32843
|
+
source_type: input.source_type,
|
|
32844
|
+
url: input.url,
|
|
32845
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32846
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
32847
|
+
}]
|
|
32848
|
+
});
|
|
32849
|
+
await log("INFO", "ink.save", `created id=${id} title="${input.title}" tags=${JSON.stringify(input.tags)}`);
|
|
32688
32850
|
return {
|
|
32689
|
-
success:
|
|
32690
|
-
message:
|
|
32851
|
+
success: true,
|
|
32852
|
+
message: `\u5DF2\u4FDD\u5B58\u300C${input.title}\u300D`,
|
|
32853
|
+
data: { id }
|
|
32691
32854
|
};
|
|
32855
|
+
} catch (err) {
|
|
32856
|
+
await log("ERROR", "ink.save", `failed: ${err.message}`);
|
|
32857
|
+
return { success: false, message: `\u4FDD\u5B58\u5931\u8D25\uFF1A${err.message}` };
|
|
32692
32858
|
}
|
|
32693
|
-
|
|
32694
|
-
|
|
32859
|
+
}
|
|
32860
|
+
async function inkDelete(input) {
|
|
32695
32861
|
try {
|
|
32696
|
-
|
|
32697
|
-
|
|
32698
|
-
|
|
32699
|
-
|
|
32700
|
-
|
|
32701
|
-
});
|
|
32702
|
-
let saved = 0;
|
|
32703
|
-
let queued = 0;
|
|
32704
|
-
for (const target of targets) {
|
|
32705
|
-
const sourceDir = join3(config2.workflowDir, "sources", "articles", target.id);
|
|
32706
|
-
let files;
|
|
32707
|
-
try {
|
|
32708
|
-
files = readdirSync2(sourceDir).filter((f) => f.endsWith(".md"));
|
|
32709
|
-
} catch {
|
|
32710
|
-
continue;
|
|
32862
|
+
if (!input.confirm) {
|
|
32863
|
+
const index = await readIndex();
|
|
32864
|
+
const entry = index.entries[input.id];
|
|
32865
|
+
if (!entry) {
|
|
32866
|
+
return { success: false, message: `\u672A\u627E\u5230 ID \u4E3A ${input.id} \u7684\u77E5\u8BC6\u7247\u6BB5` };
|
|
32711
32867
|
}
|
|
32712
|
-
|
|
32713
|
-
|
|
32714
|
-
|
|
32715
|
-
|
|
32716
|
-
|
|
32717
|
-
|
|
32718
|
-
|
|
32719
|
-
|
|
32720
|
-
|
|
32721
|
-
|
|
32722
|
-
|
|
32723
|
-
|
|
32724
|
-
|
|
32725
|
-
|
|
32726
|
-
|
|
32727
|
-
|
|
32728
|
-
|
|
32729
|
-
|
|
32730
|
-
|
|
32731
|
-
|
|
32732
|
-
|
|
32733
|
-
|
|
32734
|
-
|
|
32735
|
-
|
|
32736
|
-
|
|
32737
|
-
|
|
32738
|
-
|
|
32739
|
-
|
|
32740
|
-
|
|
32741
|
-
|
|
32742
|
-
|
|
32743
|
-
|
|
32744
|
-
|
|
32745
|
-
|
|
32746
|
-
|
|
32747
|
-
|
|
32748
|
-
|
|
32749
|
-
|
|
32750
|
-
|
|
32868
|
+
return {
|
|
32869
|
+
success: false,
|
|
32870
|
+
message: `\u786E\u8BA4\u5220\u9664\u300C${entry.title}\u300D\uFF1F\u8BF7\u5C06 confirm \u8BBE\u4E3A true \u4EE5\u786E\u8BA4\u5220\u9664\u3002`,
|
|
32871
|
+
data: { id: entry.id, title: entry.title, category: entry.category, tags: entry.tags }
|
|
32872
|
+
};
|
|
32873
|
+
}
|
|
32874
|
+
const deleted = await deleteKnowledgeFile(input.id);
|
|
32875
|
+
if (!deleted) {
|
|
32876
|
+
return { success: false, message: `\u672A\u627E\u5230 ID \u4E3A ${input.id} \u7684\u77E5\u8BC6\u7247\u6BB5` };
|
|
32877
|
+
}
|
|
32878
|
+
fireAndForgetPush({
|
|
32879
|
+
knowledge: [{
|
|
32880
|
+
id: input.id,
|
|
32881
|
+
title: "",
|
|
32882
|
+
tags: [],
|
|
32883
|
+
category: "reference",
|
|
32884
|
+
source_type: "conversation",
|
|
32885
|
+
created_at: "",
|
|
32886
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
32887
|
+
}]
|
|
32888
|
+
});
|
|
32889
|
+
await log("INFO", "ink.delete", `deleted id=${input.id}`);
|
|
32890
|
+
return { success: true, message: `\u5DF2\u5220\u9664\u77E5\u8BC6\u7247\u6BB5 ${input.id}`, data: { id: input.id } };
|
|
32891
|
+
} catch (err) {
|
|
32892
|
+
await log("ERROR", "ink.delete", `failed: ${err.message}`);
|
|
32893
|
+
return { success: false, message: `\u5220\u9664\u5931\u8D25\uFF1A${err.message}` };
|
|
32894
|
+
}
|
|
32895
|
+
}
|
|
32896
|
+
async function inkWrite(input) {
|
|
32897
|
+
const creds = await getCredentials();
|
|
32898
|
+
if (!creds?.token) return { success: false, message: "\u672A\u8BA4\u8BC1\uFF0C\u8BF7\u5148\u8FD0\u884C ink.init" };
|
|
32899
|
+
const config2 = await getConfig();
|
|
32900
|
+
try {
|
|
32901
|
+
let coverUrl = input.cover || null;
|
|
32902
|
+
if (coverUrl) {
|
|
32903
|
+
if (coverUrl.startsWith("http://") || coverUrl.startsWith("https://")) {
|
|
32904
|
+
const uploadResult = await uploadImageFromUrl(coverUrl, "cover", creds.token, config2.apiBaseUrl);
|
|
32905
|
+
if (uploadResult.success) coverUrl = uploadResult.url;
|
|
32906
|
+
} else {
|
|
32907
|
+
const uploadResult = await uploadImage(coverUrl, "cover", creds.token, config2.apiBaseUrl);
|
|
32908
|
+
if (uploadResult.success) {
|
|
32909
|
+
coverUrl = uploadResult.url;
|
|
32910
|
+
} else {
|
|
32911
|
+
await log("WARN", "ink.write", `cover upload failed: ${uploadResult.error}`);
|
|
32912
|
+
coverUrl = null;
|
|
32751
32913
|
}
|
|
32752
32914
|
}
|
|
32753
32915
|
}
|
|
32916
|
+
const slug = `${Date.now().toString(36)}-${input.title.toLowerCase().replace(/[^a-z0-9\u4e00-\u9fff]+/g, "-").replace(/^-|-$/g, "").slice(0, 60)}`;
|
|
32917
|
+
const excerpt = input.excerpt || input.content.replace(/^#+\s.+$/gm, "").replace(/\n+/g, " ").trim().slice(0, 200);
|
|
32918
|
+
const res = await fetch(`${config2.apiBaseUrl}/api/blog/manage`, {
|
|
32919
|
+
method: "POST",
|
|
32920
|
+
headers: {
|
|
32921
|
+
"Content-Type": "application/json",
|
|
32922
|
+
Authorization: `Bearer ${creds.token}`
|
|
32923
|
+
},
|
|
32924
|
+
body: JSON.stringify({
|
|
32925
|
+
title: input.title,
|
|
32926
|
+
slug,
|
|
32927
|
+
content: input.content,
|
|
32928
|
+
cover_url: coverUrl,
|
|
32929
|
+
tags: input.tags,
|
|
32930
|
+
category: input.category,
|
|
32931
|
+
excerpt,
|
|
32932
|
+
source_ids: input.source_ids
|
|
32933
|
+
})
|
|
32934
|
+
});
|
|
32935
|
+
if (!res.ok) {
|
|
32936
|
+
const err = await res.text();
|
|
32937
|
+
await log("ERROR", "ink.write", `save failed: ${err}`);
|
|
32938
|
+
return { success: false, message: `\u4FDD\u5B58\u5931\u8D25: ${err}` };
|
|
32939
|
+
}
|
|
32940
|
+
const data = await res.json();
|
|
32941
|
+
await log("INFO", "ink.write", `saved article="${input.title}" id=${data.id} slug=${data.slug}`);
|
|
32754
32942
|
return {
|
|
32755
32943
|
success: true,
|
|
32756
|
-
message:
|
|
32757
|
-
|
|
32758
|
-
` \u76EE\u6807\u6E90: ${targets.map((t) => t.name).join(", ")}`,
|
|
32759
|
-
` \u4FDD\u5B58\u5230\u77E5\u8BC6\u5E93: ${saved} \u7BC7`,
|
|
32760
|
-
queued > 0 ? ` \u52A0\u5165\u6807\u7B7E\u961F\u5217: ${queued} \u7BC7\uFF08\u7B49\u5F85 AI \u6253\u6807\u7B7E\uFF09` : ""
|
|
32761
|
-
].filter(Boolean).join("\n"),
|
|
32762
|
-
data: { sources: targets.map((t) => t.name), saved, queued }
|
|
32763
|
-
};
|
|
32764
|
-
} catch (err) {
|
|
32765
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
32766
|
-
if (message.includes("ETIMEDOUT") || message.includes("timed out")) {
|
|
32767
|
-
return { success: false, message: "\u722C\u53D6\u8D85\u65F6\uFF085 \u5206\u949F\u9650\u5236\uFF09\u3002\u8BF7\u5C1D\u8BD5\u6307\u5B9A\u5355\u4E2A\u6E90: source.crawl({ sourceId: 'xxx' })" };
|
|
32768
|
-
}
|
|
32769
|
-
return { success: false, message: `\u722C\u53D6\u5931\u8D25: ${message.slice(0, 200)}` };
|
|
32770
|
-
}
|
|
32771
|
-
}
|
|
32772
|
-
var import_gray_matter2, sourceCrawlSchema;
|
|
32773
|
-
var init_source = __esm({
|
|
32774
|
-
"src/tools/source.ts"() {
|
|
32775
|
-
"use strict";
|
|
32776
|
-
init_zod();
|
|
32777
|
-
import_gray_matter2 = __toESM(require_gray_matter(), 1);
|
|
32778
|
-
init_state();
|
|
32779
|
-
init_knowledge();
|
|
32780
|
-
init_push();
|
|
32781
|
-
sourceCrawlSchema = external_exports.object({
|
|
32782
|
-
sourceId: external_exports.string().optional().describe("\u6307\u5B9A\u722C\u866B\u6E90\u540D\u79F0\uFF0C\u4E0D\u4F20\u5219\u5168\u91CF")
|
|
32783
|
-
});
|
|
32784
|
-
}
|
|
32785
|
-
});
|
|
32786
|
-
|
|
32787
|
-
// src/tools/subscribe.ts
|
|
32788
|
-
import { readFile as readFile4, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
32789
|
-
import { join as join4 } from "path";
|
|
32790
|
-
async function readCrawlerConfig(configPath) {
|
|
32791
|
-
try {
|
|
32792
|
-
return JSON.parse(await readFile4(configPath, "utf-8"));
|
|
32793
|
-
} catch {
|
|
32794
|
-
return { sources: [] };
|
|
32795
|
-
}
|
|
32796
|
-
}
|
|
32797
|
-
async function sourceSubscribe(input) {
|
|
32798
|
-
const config2 = await getConfig();
|
|
32799
|
-
const crawlerDir = join4(config2.workflowDir || process.cwd(), "tools", "crawler");
|
|
32800
|
-
await mkdir3(crawlerDir, { recursive: true });
|
|
32801
|
-
const configPath = join4(crawlerDir, "config.json");
|
|
32802
|
-
const crawlerConfig = await readCrawlerConfig(configPath);
|
|
32803
|
-
if (input.action === "list") {
|
|
32804
|
-
return {
|
|
32805
|
-
success: true,
|
|
32806
|
-
message: `\u5171 ${crawlerConfig.sources.length} \u4E2A\u8BA2\u9605\u6E90`,
|
|
32807
|
-
data: crawlerConfig.sources
|
|
32808
|
-
};
|
|
32809
|
-
}
|
|
32810
|
-
if (input.action === "add") {
|
|
32811
|
-
if (!input.id || !input.name || !input.url) {
|
|
32812
|
-
return { success: false, message: "\u6DFB\u52A0\u8BA2\u9605\u6E90\u9700\u8981 id, name, url \u53C2\u6570" };
|
|
32813
|
-
}
|
|
32814
|
-
if (crawlerConfig.sources.some((s) => s.id === input.id)) {
|
|
32815
|
-
return { success: false, message: `\u8BA2\u9605\u6E90 ${input.id} \u5DF2\u5B58\u5728` };
|
|
32816
|
-
}
|
|
32817
|
-
const newSource = {
|
|
32818
|
-
id: input.id,
|
|
32819
|
-
name: input.name,
|
|
32820
|
-
blogUrl: input.url,
|
|
32821
|
-
type: input.type === "blog" ? "paginated" : input.type || "rss",
|
|
32822
|
-
icon: input.icon || "",
|
|
32823
|
-
enabled: true
|
|
32824
|
-
};
|
|
32825
|
-
if (input.crawlConfig) {
|
|
32826
|
-
newSource.articleSelector = input.crawlConfig.articleSelector;
|
|
32827
|
-
if (input.crawlConfig.articleUrlPattern) newSource.articleUrlPattern = input.crawlConfig.articleUrlPattern;
|
|
32828
|
-
if (input.crawlConfig.pagination) newSource.pagination = input.crawlConfig.pagination;
|
|
32829
|
-
if (input.crawlConfig.excludePatterns) newSource.excludePatterns = input.crawlConfig.excludePatterns;
|
|
32830
|
-
if (input.crawlConfig.maxArticles) newSource.maxArticles = input.crawlConfig.maxArticles;
|
|
32831
|
-
}
|
|
32832
|
-
crawlerConfig.sources.push(newSource);
|
|
32833
|
-
await writeFile3(configPath, JSON.stringify(crawlerConfig, null, 2));
|
|
32834
|
-
fireAndForgetPush({
|
|
32835
|
-
crawlerSources: crawlerConfig.sources.map((s) => ({
|
|
32836
|
-
id: s.id,
|
|
32837
|
-
name: s.name,
|
|
32838
|
-
url: s.blogUrl || s.url,
|
|
32839
|
-
type: s.type,
|
|
32840
|
-
icon: s.icon || "",
|
|
32841
|
-
enabled: s.enabled !== false
|
|
32842
|
-
}))
|
|
32843
|
-
});
|
|
32844
|
-
return { success: true, message: `\u8BA2\u9605\u6E90 ${input.name} \u5DF2\u6DFB\u52A0` };
|
|
32845
|
-
}
|
|
32846
|
-
if (input.action === "remove") {
|
|
32847
|
-
if (!input.id) {
|
|
32848
|
-
return { success: false, message: "\u5220\u9664\u8BA2\u9605\u6E90\u9700\u8981 id \u53C2\u6570" };
|
|
32849
|
-
}
|
|
32850
|
-
crawlerConfig.sources = crawlerConfig.sources.filter((s) => s.id !== input.id);
|
|
32851
|
-
await writeFile3(configPath, JSON.stringify(crawlerConfig, null, 2));
|
|
32852
|
-
fireAndForgetPush({
|
|
32853
|
-
crawlerSources: crawlerConfig.sources.map((s) => ({
|
|
32854
|
-
id: s.id,
|
|
32855
|
-
name: s.name,
|
|
32856
|
-
url: s.blogUrl || s.url,
|
|
32857
|
-
type: s.type,
|
|
32858
|
-
icon: s.icon || "",
|
|
32859
|
-
enabled: s.enabled !== false
|
|
32860
|
-
}))
|
|
32861
|
-
});
|
|
32862
|
-
return { success: true, message: `\u8BA2\u9605\u6E90 ${input.id} \u5DF2\u5220\u9664` };
|
|
32863
|
-
}
|
|
32864
|
-
return { success: false, message: "\u672A\u77E5\u64CD\u4F5C" };
|
|
32865
|
-
}
|
|
32866
|
-
var sourceSubscribeSchema;
|
|
32867
|
-
var init_subscribe = __esm({
|
|
32868
|
-
"src/tools/subscribe.ts"() {
|
|
32869
|
-
"use strict";
|
|
32870
|
-
init_zod();
|
|
32871
|
-
init_state();
|
|
32872
|
-
init_push();
|
|
32873
|
-
sourceSubscribeSchema = external_exports.object({
|
|
32874
|
-
action: external_exports.enum(["add", "remove", "list"]).describe("\u64CD\u4F5C\u7C7B\u578B"),
|
|
32875
|
-
id: external_exports.string().optional().describe("\u8BA2\u9605\u6E90 ID"),
|
|
32876
|
-
name: external_exports.string().optional().describe("\u8BA2\u9605\u6E90\u540D\u79F0"),
|
|
32877
|
-
url: external_exports.string().optional().describe("RSS/\u535A\u5BA2 URL"),
|
|
32878
|
-
type: external_exports.enum(["rss", "blog", "sitemap"]).optional().describe("\u6E90\u7C7B\u578B"),
|
|
32879
|
-
icon: external_exports.string().optional().describe("\u6765\u6E90 icon URL"),
|
|
32880
|
-
crawlConfig: external_exports.object({
|
|
32881
|
-
articleSelector: external_exports.string(),
|
|
32882
|
-
articleUrlPattern: external_exports.string().optional(),
|
|
32883
|
-
pagination: external_exports.object({
|
|
32884
|
-
pattern: external_exports.string(),
|
|
32885
|
-
startPage: external_exports.number(),
|
|
32886
|
-
maxPages: external_exports.number()
|
|
32887
|
-
}).optional(),
|
|
32888
|
-
excludePatterns: external_exports.array(external_exports.string()).optional(),
|
|
32889
|
-
maxArticles: external_exports.number().optional()
|
|
32890
|
-
}).optional().describe("\u722C\u53D6\u9002\u914D\u89C4\u5219\uFF08Claude \u5206\u6790\u751F\u6210\uFF09")
|
|
32891
|
-
});
|
|
32892
|
-
}
|
|
32893
|
-
});
|
|
32894
|
-
|
|
32895
|
-
// src/tools/sync.ts
|
|
32896
|
-
async function sync2(input) {
|
|
32897
|
-
if (input.workDir) setWorkDir(input.workDir);
|
|
32898
|
-
const creds = await getCredentials();
|
|
32899
|
-
if (!creds?.token) {
|
|
32900
|
-
return { success: false, message: "\u672A\u6FC0\u6D3B\uFF0C\u8BF7\u5148\u4F7F\u7528 workflow.init \u6FC0\u6D3B License" };
|
|
32901
|
-
}
|
|
32902
|
-
return doPull(creds.token);
|
|
32903
|
-
}
|
|
32904
|
-
async function doPull(token) {
|
|
32905
|
-
const config2 = await getConfig();
|
|
32906
|
-
try {
|
|
32907
|
-
const res = await fetch(`${config2.apiBaseUrl}/api/sync/pull`, {
|
|
32908
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
32909
|
-
});
|
|
32910
|
-
if (!res.ok) {
|
|
32911
|
-
if (res.status === 404) {
|
|
32912
|
-
return { success: true, message: "\u4E91\u7AEF\u65E0\u6570\u636E" };
|
|
32913
|
-
}
|
|
32914
|
-
return { success: false, message: `\u62C9\u53D6\u5931\u8D25: HTTP ${res.status}` };
|
|
32915
|
-
}
|
|
32916
|
-
await updateLastSyncAt();
|
|
32917
|
-
return {
|
|
32918
|
-
success: true,
|
|
32919
|
-
message: "\u2705 \u540C\u6B65\u5B8C\u6210"
|
|
32944
|
+
message: `\u6587\u7AE0\u300C${input.title}\u300D\u5DF2\u4FDD\u5B58\u4E3A\u8349\u7A3F\uFF0C\u8BF7\u5230 Dashboard \u53D1\u5E03`,
|
|
32945
|
+
data: { id: data.id, slug: data.slug, status: data.status }
|
|
32920
32946
|
};
|
|
32921
32947
|
} catch (err) {
|
|
32922
|
-
|
|
32923
|
-
|
|
32924
|
-
}
|
|
32925
|
-
async function syncPull(input) {
|
|
32926
|
-
if (input.workDir) setWorkDir(input.workDir);
|
|
32927
|
-
const creds = await getCredentials();
|
|
32928
|
-
if (!creds?.token) {
|
|
32929
|
-
return { success: false, message: "\u672A\u6FC0\u6D3B" };
|
|
32930
|
-
}
|
|
32931
|
-
return doPull(creds.token);
|
|
32932
|
-
}
|
|
32933
|
-
var syncSchema;
|
|
32934
|
-
var init_sync = __esm({
|
|
32935
|
-
"src/tools/sync.ts"() {
|
|
32936
|
-
"use strict";
|
|
32937
|
-
init_zod();
|
|
32938
|
-
init_state();
|
|
32939
|
-
syncSchema = external_exports.object({
|
|
32940
|
-
workDir: external_exports.string().optional().describe("\u5DE5\u4F5C\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4F7F\u7528\u914D\u7F6E\u4E2D\u7684 workflowDir\uFF09")
|
|
32941
|
-
});
|
|
32942
|
-
}
|
|
32943
|
-
});
|
|
32944
|
-
|
|
32945
|
-
// src/tools/workflow.ts
|
|
32946
|
-
import { mkdir as mkdir4, access, unlink as unlink2 } from "fs/promises";
|
|
32947
|
-
import { join as join5 } from "path";
|
|
32948
|
-
async function workflowInit(input) {
|
|
32949
|
-
const cwd = input.workDir;
|
|
32950
|
-
const results = [];
|
|
32951
|
-
try {
|
|
32952
|
-
setWorkDir(cwd);
|
|
32953
|
-
const claudeinkDir = join5(cwd, ".claudeink");
|
|
32954
|
-
await mkdir4(join5(claudeinkDir, "knowledge"), { recursive: true });
|
|
32955
|
-
results.push("\u2705 \u77E5\u8BC6\u5E93\u76EE\u5F55\u5DF2\u521B\u5EFA");
|
|
32956
|
-
const state = await readState();
|
|
32957
|
-
state.config.workflowDir = cwd;
|
|
32958
|
-
const oldCredsPath = join5(claudeinkDir, "credentials.json");
|
|
32959
|
-
try {
|
|
32960
|
-
await access(oldCredsPath);
|
|
32961
|
-
await unlink2(oldCredsPath);
|
|
32962
|
-
results.push("\u{1F9F9} \u5DF2\u6E05\u7406\u65E7\u7248 credentials.json");
|
|
32963
|
-
} catch {
|
|
32964
|
-
}
|
|
32965
|
-
let activated = false;
|
|
32966
|
-
if (input.licenseKey) {
|
|
32967
|
-
try {
|
|
32968
|
-
const res = await fetch(`${DEFAULT_API_BASE_URL}/api/auth/activate`, {
|
|
32969
|
-
method: "POST",
|
|
32970
|
-
headers: { "Content-Type": "application/json" },
|
|
32971
|
-
body: JSON.stringify({ key: input.licenseKey })
|
|
32972
|
-
});
|
|
32973
|
-
const data = await res.json();
|
|
32974
|
-
if (data.userId) {
|
|
32975
|
-
state.credentials = {
|
|
32976
|
-
licenseKey: input.licenseKey,
|
|
32977
|
-
token: data.token,
|
|
32978
|
-
userId: data.userId,
|
|
32979
|
-
plan: data.plan,
|
|
32980
|
-
expiresAt: data.expiresAt
|
|
32981
|
-
};
|
|
32982
|
-
results.push(`\u2705 License \u6FC0\u6D3B\u6210\u529F\uFF08\u5957\u9910: ${data.plan}\uFF09`);
|
|
32983
|
-
activated = true;
|
|
32984
|
-
} else {
|
|
32985
|
-
results.push(`\u26A0\uFE0F License \u6FC0\u6D3B\u5931\u8D25: ${JSON.stringify(data)}`);
|
|
32986
|
-
}
|
|
32987
|
-
} catch (err) {
|
|
32988
|
-
results.push(`\u26A0\uFE0F \u6FC0\u6D3B\u7F51\u7EDC\u9519\u8BEF: ${err instanceof Error ? err.message : err}`);
|
|
32989
|
-
}
|
|
32990
|
-
}
|
|
32991
|
-
await writeState(state);
|
|
32992
|
-
results.push("\u2705 state.json");
|
|
32993
|
-
if (activated) {
|
|
32994
|
-
try {
|
|
32995
|
-
const pullResult = await syncPull({ workDir: cwd });
|
|
32996
|
-
if (pullResult.success) {
|
|
32997
|
-
results.push("\u2705 \u5DF2\u4ECE\u4E91\u7AEF\u540C\u6B65\u6570\u636E");
|
|
32998
|
-
} else {
|
|
32999
|
-
results.push("\u2139\uFE0F \u4E91\u7AEF\u65E0\u5DF2\u6709\u6570\u636E");
|
|
33000
|
-
}
|
|
33001
|
-
} catch {
|
|
33002
|
-
results.push("\u2139\uFE0F \u4E91\u7AEF\u540C\u6B65\u8DF3\u8FC7");
|
|
33003
|
-
}
|
|
33004
|
-
}
|
|
33005
|
-
return {
|
|
33006
|
-
success: true,
|
|
33007
|
-
message: [
|
|
33008
|
-
"\u{1F389} ClaudeInk \u77E5\u8BC6\u5E93\u521D\u59CB\u5316\u5B8C\u6210\uFF01",
|
|
33009
|
-
"",
|
|
33010
|
-
...results,
|
|
33011
|
-
"",
|
|
33012
|
-
"\u{1F3AF} \u4E0B\u4E00\u6B65\uFF1A",
|
|
33013
|
-
"1. \u5728\u5BF9\u8BDD\u4E2D\u8BF4\u300C\u5E2E\u6211\u5B58\u4E00\u4E0B\u300D\u4FDD\u5B58\u6709\u4EF7\u503C\u5185\u5BB9",
|
|
33014
|
-
"2. \u7528\u300C\u627E\u4E00\u4E0B\u5173\u4E8E XX \u7684\u300D\u68C0\u7D22\u77E5\u8BC6\u5E93"
|
|
33015
|
-
].join("\n")
|
|
33016
|
-
};
|
|
33017
|
-
} catch (err) {
|
|
33018
|
-
return {
|
|
33019
|
-
success: false,
|
|
33020
|
-
message: `\u521D\u59CB\u5316\u5931\u8D25: ${err instanceof Error ? err.message : err}`
|
|
33021
|
-
};
|
|
33022
|
-
}
|
|
33023
|
-
}
|
|
33024
|
-
var DEFAULT_API_BASE_URL, workflowInitSchema;
|
|
33025
|
-
var init_workflow = __esm({
|
|
33026
|
-
"src/tools/workflow.ts"() {
|
|
33027
|
-
"use strict";
|
|
33028
|
-
init_zod();
|
|
33029
|
-
init_state();
|
|
33030
|
-
init_sync();
|
|
33031
|
-
DEFAULT_API_BASE_URL = "https://app.claudeink.com";
|
|
33032
|
-
workflowInitSchema = external_exports.object({
|
|
33033
|
-
workDir: external_exports.string().describe("\u5DE5\u4F5C\u6D41\u521D\u59CB\u5316\u76EE\u6807\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09"),
|
|
33034
|
-
licenseKey: external_exports.string().optional().describe("License Key\uFF08\u53EF\u9009\uFF0C\u4F20\u5165\u5219\u81EA\u52A8\u6FC0\u6D3B\uFF09")
|
|
33035
|
-
});
|
|
33036
|
-
}
|
|
33037
|
-
});
|
|
33038
|
-
|
|
33039
|
-
// src/tools/ink.ts
|
|
33040
|
-
async function inkSave(input) {
|
|
33041
|
-
try {
|
|
33042
|
-
const { id } = await saveKnowledge({
|
|
33043
|
-
content: input.content,
|
|
33044
|
-
title: input.title,
|
|
33045
|
-
tags: input.tags,
|
|
33046
|
-
category: input.category,
|
|
33047
|
-
source_type: input.source_type,
|
|
33048
|
-
url: input.url
|
|
33049
|
-
});
|
|
33050
|
-
const categoryNames = {
|
|
33051
|
-
insight: "\u6D1E\u5BDF",
|
|
33052
|
-
decision: "\u51B3\u7B56",
|
|
33053
|
-
analysis: "\u5206\u6790",
|
|
33054
|
-
idea: "\u60F3\u6CD5",
|
|
33055
|
-
reference: "\u53C2\u8003",
|
|
33056
|
-
action: "\u884C\u52A8"
|
|
33057
|
-
};
|
|
33058
|
-
const catName = categoryNames[input.category] || input.category;
|
|
33059
|
-
const tagStr = input.tags.length > 0 ? input.tags.join("\u3001") : "\u65E0\u6807\u7B7E";
|
|
33060
|
-
fireAndForgetPush({
|
|
33061
|
-
knowledge: [{
|
|
33062
|
-
id,
|
|
33063
|
-
title: input.title,
|
|
33064
|
-
tags: input.tags,
|
|
33065
|
-
category: input.category,
|
|
33066
|
-
source_type: input.source_type,
|
|
33067
|
-
url: input.url,
|
|
33068
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33069
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
33070
|
-
}]
|
|
33071
|
-
});
|
|
33072
|
-
return {
|
|
33073
|
-
success: true,
|
|
33074
|
-
message: `\u5DF2\u4FDD\u5B58\u5230\u300C${catName}\u300D\uFF0C\u6807\u7B7E\uFF1A${tagStr}`,
|
|
33075
|
-
data: { id }
|
|
33076
|
-
};
|
|
33077
|
-
} catch (err) {
|
|
33078
|
-
return {
|
|
33079
|
-
success: false,
|
|
33080
|
-
message: `\u4FDD\u5B58\u5931\u8D25\uFF1A${err.message}`
|
|
33081
|
-
};
|
|
33082
|
-
}
|
|
33083
|
-
}
|
|
33084
|
-
async function inkSearch(input) {
|
|
33085
|
-
try {
|
|
33086
|
-
const index = await readIndex();
|
|
33087
|
-
const { results, total } = searchKnowledge(index, {
|
|
33088
|
-
query: input.query,
|
|
33089
|
-
tags: input.tags,
|
|
33090
|
-
category: input.category,
|
|
33091
|
-
date_from: input.date_from,
|
|
33092
|
-
date_to: input.date_to,
|
|
33093
|
-
limit: input.limit
|
|
33094
|
-
});
|
|
33095
|
-
if (total === 0) {
|
|
33096
|
-
return {
|
|
33097
|
-
success: true,
|
|
33098
|
-
message: "\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u77E5\u8BC6\u7247\u6BB5",
|
|
33099
|
-
data: { results: [], total: 0 }
|
|
33100
|
-
};
|
|
33101
|
-
}
|
|
33102
|
-
return {
|
|
33103
|
-
success: true,
|
|
33104
|
-
message: `\u627E\u5230 ${total} \u6761\u76F8\u5173\u8BB0\u5F55${total > results.length ? `\uFF0C\u663E\u793A\u524D ${results.length} \u6761` : ""}`,
|
|
33105
|
-
data: { results, total }
|
|
33106
|
-
};
|
|
33107
|
-
} catch (err) {
|
|
33108
|
-
return {
|
|
33109
|
-
success: false,
|
|
33110
|
-
message: `\u641C\u7D22\u5931\u8D25\uFF1A${err.message}`
|
|
33111
|
-
};
|
|
33112
|
-
}
|
|
33113
|
-
}
|
|
33114
|
-
async function inkGet(input) {
|
|
33115
|
-
try {
|
|
33116
|
-
const file = await readKnowledgeFile(input.id);
|
|
33117
|
-
if (!file) {
|
|
33118
|
-
return {
|
|
33119
|
-
success: false,
|
|
33120
|
-
message: `\u672A\u627E\u5230 ID \u4E3A ${input.id} \u7684\u77E5\u8BC6\u7247\u6BB5`
|
|
33121
|
-
};
|
|
33122
|
-
}
|
|
33123
|
-
return {
|
|
33124
|
-
success: true,
|
|
33125
|
-
message: file.meta.title,
|
|
33126
|
-
data: {
|
|
33127
|
-
id: file.meta.id,
|
|
33128
|
-
title: file.meta.title,
|
|
33129
|
-
content: file.content,
|
|
33130
|
-
tags: file.meta.tags,
|
|
33131
|
-
category: file.meta.category,
|
|
33132
|
-
source_type: file.meta.source_type,
|
|
33133
|
-
url: file.meta.url,
|
|
33134
|
-
created_at: file.meta.created_at,
|
|
33135
|
-
updated_at: file.meta.updated_at
|
|
33136
|
-
}
|
|
33137
|
-
};
|
|
33138
|
-
} catch (err) {
|
|
33139
|
-
return {
|
|
33140
|
-
success: false,
|
|
33141
|
-
message: `\u83B7\u53D6\u5931\u8D25\uFF1A${err.message}`
|
|
33142
|
-
};
|
|
33143
|
-
}
|
|
33144
|
-
}
|
|
33145
|
-
async function inkReview(input) {
|
|
33146
|
-
try {
|
|
33147
|
-
const index = await readIndex();
|
|
33148
|
-
const entries = Object.values(index.entries);
|
|
33149
|
-
const now = /* @__PURE__ */ new Date();
|
|
33150
|
-
let dateFrom;
|
|
33151
|
-
let dateTo = now.toISOString();
|
|
33152
|
-
switch (input.period) {
|
|
33153
|
-
case "today":
|
|
33154
|
-
dateFrom = new Date(now.getFullYear(), now.getMonth(), now.getDate()).toISOString();
|
|
33155
|
-
break;
|
|
33156
|
-
case "week": {
|
|
33157
|
-
const weekAgo = new Date(now);
|
|
33158
|
-
weekAgo.setDate(weekAgo.getDate() - 7);
|
|
33159
|
-
dateFrom = weekAgo.toISOString();
|
|
33160
|
-
break;
|
|
33161
|
-
}
|
|
33162
|
-
case "month": {
|
|
33163
|
-
const monthAgo = new Date(now);
|
|
33164
|
-
monthAgo.setMonth(monthAgo.getMonth() - 1);
|
|
33165
|
-
dateFrom = monthAgo.toISOString();
|
|
33166
|
-
break;
|
|
33167
|
-
}
|
|
33168
|
-
case "custom":
|
|
33169
|
-
dateFrom = input.date_from || (/* @__PURE__ */ new Date(0)).toISOString();
|
|
33170
|
-
dateTo = input.date_to || now.toISOString();
|
|
33171
|
-
break;
|
|
33172
|
-
}
|
|
33173
|
-
let filtered = entries.filter(
|
|
33174
|
-
(e) => e.created_at >= dateFrom && e.created_at <= dateTo
|
|
33175
|
-
);
|
|
33176
|
-
if (input.category) {
|
|
33177
|
-
filtered = filtered.filter((e) => e.category === input.category);
|
|
33178
|
-
}
|
|
33179
|
-
filtered.sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
33180
|
-
const byCategory = {};
|
|
33181
|
-
for (const e of filtered) {
|
|
33182
|
-
byCategory[e.category] = (byCategory[e.category] || 0) + 1;
|
|
33183
|
-
}
|
|
33184
|
-
const tagCounts = {};
|
|
33185
|
-
for (const e of filtered) {
|
|
33186
|
-
for (const t of e.tags) {
|
|
33187
|
-
tagCounts[t] = (tagCounts[t] || 0) + 1;
|
|
33188
|
-
}
|
|
33189
|
-
}
|
|
33190
|
-
const topTags = Object.entries(tagCounts).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([tag, count]) => ({ tag, count }));
|
|
33191
|
-
const categoryNames = {
|
|
33192
|
-
insight: "\u6D1E\u5BDF",
|
|
33193
|
-
decision: "\u51B3\u7B56",
|
|
33194
|
-
analysis: "\u5206\u6790",
|
|
33195
|
-
idea: "\u60F3\u6CD5",
|
|
33196
|
-
reference: "\u53C2\u8003",
|
|
33197
|
-
action: "\u884C\u52A8"
|
|
33198
|
-
};
|
|
33199
|
-
const periodNames = {
|
|
33200
|
-
today: "\u4ECA\u65E5",
|
|
33201
|
-
week: "\u672C\u5468",
|
|
33202
|
-
month: "\u672C\u6708",
|
|
33203
|
-
custom: "\u81EA\u5B9A\u4E49\u65F6\u6BB5"
|
|
33204
|
-
};
|
|
33205
|
-
return {
|
|
33206
|
-
success: true,
|
|
33207
|
-
message: `${periodNames[input.period]}\u77E5\u8BC6\u56DE\u987E\uFF1A\u5171 ${filtered.length} \u6761\u8BB0\u5F55`,
|
|
33208
|
-
data: {
|
|
33209
|
-
period: input.period,
|
|
33210
|
-
date_from: dateFrom,
|
|
33211
|
-
date_to: dateTo,
|
|
33212
|
-
total: filtered.length,
|
|
33213
|
-
by_category: Object.entries(byCategory).map(([cat, count]) => ({
|
|
33214
|
-
category: cat,
|
|
33215
|
-
label: categoryNames[cat] || cat,
|
|
33216
|
-
count
|
|
33217
|
-
})),
|
|
33218
|
-
top_tags: topTags,
|
|
33219
|
-
items: filtered.map((e) => ({
|
|
33220
|
-
id: e.id,
|
|
33221
|
-
title: e.title,
|
|
33222
|
-
category: e.category,
|
|
33223
|
-
tags: e.tags,
|
|
33224
|
-
created_at: e.created_at,
|
|
33225
|
-
preview: e.preview
|
|
33226
|
-
}))
|
|
33227
|
-
}
|
|
33228
|
-
};
|
|
33229
|
-
} catch (err) {
|
|
33230
|
-
return {
|
|
33231
|
-
success: false,
|
|
33232
|
-
message: `\u56DE\u987E\u5931\u8D25\uFF1A${err.message}`
|
|
33233
|
-
};
|
|
33234
|
-
}
|
|
33235
|
-
}
|
|
33236
|
-
async function inkUpdate(input) {
|
|
33237
|
-
try {
|
|
33238
|
-
const { id, ...updates } = input;
|
|
33239
|
-
if (!updates.title && !updates.content && !updates.tags && !updates.category) {
|
|
33240
|
-
return {
|
|
33241
|
-
success: false,
|
|
33242
|
-
message: "\u8BF7\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u8981\u66F4\u65B0\u7684\u5B57\u6BB5\uFF08title / content / tags / category\uFF09"
|
|
33243
|
-
};
|
|
33244
|
-
}
|
|
33245
|
-
const result = await updateKnowledgeFile(id, updates);
|
|
33246
|
-
if (!result) {
|
|
33247
|
-
return {
|
|
33248
|
-
success: false,
|
|
33249
|
-
message: `\u672A\u627E\u5230 ID \u4E3A ${id} \u7684\u77E5\u8BC6\u7247\u6BB5`
|
|
33250
|
-
};
|
|
33251
|
-
}
|
|
33252
|
-
const changed = Object.keys(updates).filter(
|
|
33253
|
-
(k) => updates[k] !== void 0
|
|
33254
|
-
);
|
|
33255
|
-
fireAndForgetPush({
|
|
33256
|
-
knowledge: [{
|
|
33257
|
-
id: result.meta.id,
|
|
33258
|
-
title: result.meta.title,
|
|
33259
|
-
tags: result.meta.tags,
|
|
33260
|
-
category: result.meta.category,
|
|
33261
|
-
source_type: result.meta.source_type,
|
|
33262
|
-
url: result.meta.url,
|
|
33263
|
-
created_at: result.meta.created_at,
|
|
33264
|
-
updated_at: result.meta.updated_at
|
|
33265
|
-
}]
|
|
33266
|
-
});
|
|
33267
|
-
return {
|
|
33268
|
-
success: true,
|
|
33269
|
-
message: `\u5DF2\u66F4\u65B0\u300C${result.meta.title}\u300D\u7684 ${changed.join("\u3001")}`,
|
|
33270
|
-
data: {
|
|
33271
|
-
id: result.meta.id,
|
|
33272
|
-
title: result.meta.title,
|
|
33273
|
-
tags: result.meta.tags,
|
|
33274
|
-
category: result.meta.category,
|
|
33275
|
-
updated_at: result.meta.updated_at
|
|
33276
|
-
}
|
|
33277
|
-
};
|
|
33278
|
-
} catch (err) {
|
|
33279
|
-
return {
|
|
33280
|
-
success: false,
|
|
33281
|
-
message: `\u66F4\u65B0\u5931\u8D25\uFF1A${err.message}`
|
|
33282
|
-
};
|
|
33283
|
-
}
|
|
33284
|
-
}
|
|
33285
|
-
async function inkDelete(input) {
|
|
33286
|
-
try {
|
|
33287
|
-
if (!input.confirm) {
|
|
33288
|
-
const index = await readIndex();
|
|
33289
|
-
const entry = index.entries[input.id];
|
|
33290
|
-
if (!entry) {
|
|
33291
|
-
return {
|
|
33292
|
-
success: false,
|
|
33293
|
-
message: `\u672A\u627E\u5230 ID \u4E3A ${input.id} \u7684\u77E5\u8BC6\u7247\u6BB5`
|
|
33294
|
-
};
|
|
33295
|
-
}
|
|
33296
|
-
return {
|
|
33297
|
-
success: false,
|
|
33298
|
-
message: `\u786E\u8BA4\u5220\u9664\u300C${entry.title}\u300D\uFF1F\u8BF7\u5C06 confirm \u8BBE\u4E3A true \u4EE5\u786E\u8BA4\u5220\u9664\u3002`,
|
|
33299
|
-
data: {
|
|
33300
|
-
id: entry.id,
|
|
33301
|
-
title: entry.title,
|
|
33302
|
-
category: entry.category,
|
|
33303
|
-
tags: entry.tags,
|
|
33304
|
-
created_at: entry.created_at
|
|
33305
|
-
}
|
|
33306
|
-
};
|
|
33307
|
-
}
|
|
33308
|
-
const deleted = await deleteKnowledgeFile(input.id);
|
|
33309
|
-
if (!deleted) {
|
|
33310
|
-
return {
|
|
33311
|
-
success: false,
|
|
33312
|
-
message: `\u672A\u627E\u5230 ID \u4E3A ${input.id} \u7684\u77E5\u8BC6\u7247\u6BB5`
|
|
33313
|
-
};
|
|
33314
|
-
}
|
|
33315
|
-
fireAndForgetPush({
|
|
33316
|
-
knowledge: [{
|
|
33317
|
-
id: input.id,
|
|
33318
|
-
title: "",
|
|
33319
|
-
tags: [],
|
|
33320
|
-
category: "reference",
|
|
33321
|
-
source_type: "conversation",
|
|
33322
|
-
created_at: "",
|
|
33323
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
33324
|
-
}]
|
|
33325
|
-
});
|
|
33326
|
-
return {
|
|
33327
|
-
success: true,
|
|
33328
|
-
message: `\u5DF2\u5220\u9664\u77E5\u8BC6\u7247\u6BB5 ${input.id}`,
|
|
33329
|
-
data: { id: input.id }
|
|
33330
|
-
};
|
|
33331
|
-
} catch (err) {
|
|
33332
|
-
return {
|
|
33333
|
-
success: false,
|
|
33334
|
-
message: `\u5220\u9664\u5931\u8D25\uFF1A${err.message}`
|
|
33335
|
-
};
|
|
33336
|
-
}
|
|
33337
|
-
}
|
|
33338
|
-
async function inkCompile(input) {
|
|
33339
|
-
try {
|
|
33340
|
-
let ids = [];
|
|
33341
|
-
if (input.ids && input.ids.length > 0) {
|
|
33342
|
-
ids = input.ids;
|
|
33343
|
-
} else if (input.query || input.tags && input.tags.length > 0) {
|
|
33344
|
-
const index = await readIndex();
|
|
33345
|
-
const { results } = searchKnowledge(index, {
|
|
33346
|
-
query: input.query,
|
|
33347
|
-
tags: input.tags,
|
|
33348
|
-
limit: 20
|
|
33349
|
-
});
|
|
33350
|
-
ids = results.map((r) => r.id);
|
|
33351
|
-
}
|
|
33352
|
-
if (ids.length === 0) {
|
|
33353
|
-
return {
|
|
33354
|
-
success: false,
|
|
33355
|
-
message: "\u6CA1\u6709\u627E\u5230\u8981\u6574\u5408\u7684\u77E5\u8BC6\u7247\u6BB5\uFF0C\u8BF7\u6307\u5B9A ids \u6216\u63D0\u4F9B\u641C\u7D22\u6761\u4EF6"
|
|
33356
|
-
};
|
|
33357
|
-
}
|
|
33358
|
-
const files = await readMultipleKnowledgeFiles(ids);
|
|
33359
|
-
if (files.length === 0) {
|
|
33360
|
-
return {
|
|
33361
|
-
success: false,
|
|
33362
|
-
message: "\u672A\u80FD\u8BFB\u53D6\u4EFB\u4F55\u77E5\u8BC6\u7247\u6BB5\u5185\u5BB9"
|
|
33363
|
-
};
|
|
33364
|
-
}
|
|
33365
|
-
const sections = files.map((f, i) => {
|
|
33366
|
-
const tagStr = f.meta.tags.length > 0 ? ` [${f.meta.tags.join(", ")}]` : "";
|
|
33367
|
-
return `### ${i + 1}. ${f.meta.title}${tagStr}
|
|
33368
|
-
> ${f.meta.category} | ${f.meta.created_at.slice(0, 10)}
|
|
33369
|
-
|
|
33370
|
-
${f.content}`;
|
|
33371
|
-
});
|
|
33372
|
-
const formatLabels = {
|
|
33373
|
-
outline: "\u5927\u7EB2",
|
|
33374
|
-
article: "\u6587\u7AE0",
|
|
33375
|
-
summary: "\u6458\u8981"
|
|
33376
|
-
};
|
|
33377
|
-
const compiled = sections.join("\n\n---\n\n");
|
|
33378
|
-
return {
|
|
33379
|
-
success: true,
|
|
33380
|
-
message: `\u5DF2\u6574\u5408 ${files.length} \u6761\u77E5\u8BC6\u7247\u6BB5\uFF0C\u683C\u5F0F\uFF1A${formatLabels[input.format]}`,
|
|
33381
|
-
data: {
|
|
33382
|
-
source_count: files.length,
|
|
33383
|
-
source_ids: files.map((f) => f.meta.id),
|
|
33384
|
-
format: input.format,
|
|
33385
|
-
instruction: input.instruction || null,
|
|
33386
|
-
compiled_content: compiled
|
|
33387
|
-
}
|
|
33388
|
-
};
|
|
33389
|
-
} catch (err) {
|
|
33390
|
-
return {
|
|
33391
|
-
success: false,
|
|
33392
|
-
message: `\u6574\u5408\u5931\u8D25\uFF1A${err.message}`
|
|
33393
|
-
};
|
|
32948
|
+
await log("ERROR", "ink.write", `failed: ${err.message}`);
|
|
32949
|
+
return { success: false, message: `\u5199\u6587\u7AE0\u5931\u8D25: ${err.message}` };
|
|
33394
32950
|
}
|
|
33395
32951
|
}
|
|
33396
32952
|
async function inkTags(input) {
|
|
@@ -33407,18 +32963,13 @@ async function inkTags(input) {
|
|
|
33407
32963
|
}
|
|
33408
32964
|
case "rename": {
|
|
33409
32965
|
if (!input.tag || !input.new_tag) {
|
|
33410
|
-
return {
|
|
33411
|
-
success: false,
|
|
33412
|
-
message: "rename \u64CD\u4F5C\u9700\u8981\u63D0\u4F9B tag\uFF08\u539F\u6807\u7B7E\uFF09\u548C new_tag\uFF08\u65B0\u6807\u7B7E\u540D\uFF09"
|
|
33413
|
-
};
|
|
32966
|
+
return { success: false, message: "rename \u9700\u8981 tag\uFF08\u539F\u6807\u7B7E\uFF09\u548C new_tag\uFF08\u65B0\u6807\u7B7E\u540D\uFF09" };
|
|
33414
32967
|
}
|
|
33415
32968
|
const count = await renameTag(input.tag, input.new_tag);
|
|
33416
32969
|
if (count === 0) {
|
|
33417
|
-
return {
|
|
33418
|
-
success: false,
|
|
33419
|
-
message: `\u672A\u627E\u5230\u4F7F\u7528\u6807\u7B7E\u300C${input.tag}\u300D\u7684\u77E5\u8BC6\u7247\u6BB5`
|
|
33420
|
-
};
|
|
32970
|
+
return { success: false, message: `\u672A\u627E\u5230\u4F7F\u7528\u6807\u7B7E\u300C${input.tag}\u300D\u7684\u77E5\u8BC6\u7247\u6BB5` };
|
|
33421
32971
|
}
|
|
32972
|
+
await log("INFO", "ink.tags", `renamed "${input.tag}" \u2192 "${input.new_tag}", affected=${count}`);
|
|
33422
32973
|
return {
|
|
33423
32974
|
success: true,
|
|
33424
32975
|
message: `\u5DF2\u5C06 ${count} \u6761\u77E5\u8BC6\u7247\u6BB5\u7684\u6807\u7B7E\u300C${input.tag}\u300D\u91CD\u547D\u540D\u4E3A\u300C${input.new_tag}\u300D`,
|
|
@@ -33427,85 +32978,110 @@ async function inkTags(input) {
|
|
|
33427
32978
|
}
|
|
33428
32979
|
case "merge": {
|
|
33429
32980
|
if (!input.source_tags || input.source_tags.length === 0 || !input.new_tag) {
|
|
33430
|
-
return {
|
|
33431
|
-
success: false,
|
|
33432
|
-
message: "merge \u64CD\u4F5C\u9700\u8981\u63D0\u4F9B source_tags\uFF08\u6E90\u6807\u7B7E\u5217\u8868\uFF09\u548C new_tag\uFF08\u76EE\u6807\u6807\u7B7E\uFF09"
|
|
33433
|
-
};
|
|
32981
|
+
return { success: false, message: "merge \u9700\u8981 source_tags\uFF08\u6E90\u6807\u7B7E\u5217\u8868\uFF09\u548C new_tag\uFF08\u76EE\u6807\u6807\u7B7E\uFF09" };
|
|
33434
32982
|
}
|
|
33435
32983
|
const count = await mergeTags(input.source_tags, input.new_tag);
|
|
33436
32984
|
if (count === 0) {
|
|
33437
|
-
return {
|
|
33438
|
-
success: false,
|
|
33439
|
-
message: `\u672A\u627E\u5230\u4F7F\u7528\u8FD9\u4E9B\u6807\u7B7E\u7684\u77E5\u8BC6\u7247\u6BB5`
|
|
33440
|
-
};
|
|
32985
|
+
return { success: false, message: "\u672A\u627E\u5230\u4F7F\u7528\u8FD9\u4E9B\u6807\u7B7E\u7684\u77E5\u8BC6\u7247\u6BB5" };
|
|
33441
32986
|
}
|
|
32987
|
+
await log("INFO", "ink.tags", `merged [${input.source_tags.join(",")}] \u2192 "${input.new_tag}", affected=${count}`);
|
|
33442
32988
|
return {
|
|
33443
32989
|
success: true,
|
|
33444
32990
|
message: `\u5DF2\u5C06 ${count} \u6761\u77E5\u8BC6\u7247\u6BB5\u7684\u6807\u7B7E\u5408\u5E76\u4E3A\u300C${input.new_tag}\u300D`,
|
|
33445
|
-
data: {
|
|
33446
|
-
source_tags: input.source_tags,
|
|
33447
|
-
target_tag: input.new_tag,
|
|
33448
|
-
affected: count
|
|
33449
|
-
}
|
|
32991
|
+
data: { source_tags: input.source_tags, target_tag: input.new_tag, affected: count }
|
|
33450
32992
|
};
|
|
33451
32993
|
}
|
|
33452
32994
|
}
|
|
33453
32995
|
} catch (err) {
|
|
33454
|
-
|
|
33455
|
-
|
|
33456
|
-
|
|
33457
|
-
|
|
32996
|
+
await log("ERROR", "ink.tags", `failed: ${err.message}`);
|
|
32997
|
+
return { success: false, message: `\u6807\u7B7E\u64CD\u4F5C\u5931\u8D25\uFF1A${err.message}` };
|
|
32998
|
+
}
|
|
32999
|
+
}
|
|
33000
|
+
async function uploadImage(localPath, type, token, apiBase) {
|
|
33001
|
+
try {
|
|
33002
|
+
const fileBuffer = await readFile3(localPath);
|
|
33003
|
+
const ext2 = extname(localPath) || ".jpg";
|
|
33004
|
+
const extMap = {
|
|
33005
|
+
".jpg": "image/jpeg",
|
|
33006
|
+
".jpeg": "image/jpeg",
|
|
33007
|
+
".png": "image/png",
|
|
33008
|
+
".webp": "image/webp",
|
|
33009
|
+
".gif": "image/gif"
|
|
33010
|
+
};
|
|
33011
|
+
const contentType = extMap[ext2.toLowerCase()] || "application/octet-stream";
|
|
33012
|
+
const filename = `${type}-${Date.now()}${ext2}`;
|
|
33013
|
+
const res = await fetch(`${apiBase}/api/blog/upload-image`, {
|
|
33014
|
+
method: "POST",
|
|
33015
|
+
headers: {
|
|
33016
|
+
Authorization: `Bearer ${token}`,
|
|
33017
|
+
"Content-Type": contentType,
|
|
33018
|
+
"X-Filename": filename,
|
|
33019
|
+
"X-Image-Type": type
|
|
33020
|
+
},
|
|
33021
|
+
body: fileBuffer
|
|
33022
|
+
});
|
|
33023
|
+
if (!res.ok) return { success: false, error: await res.text() };
|
|
33024
|
+
const { url } = await res.json();
|
|
33025
|
+
return { success: true, url };
|
|
33026
|
+
} catch (err) {
|
|
33027
|
+
return { success: false, error: err.message };
|
|
33458
33028
|
}
|
|
33459
33029
|
}
|
|
33460
|
-
|
|
33030
|
+
async function uploadImageFromUrl(imageUrl, type, token, apiBase) {
|
|
33031
|
+
try {
|
|
33032
|
+
const res = await fetch(imageUrl);
|
|
33033
|
+
if (!res.ok) return { success: false, error: `download failed: HTTP ${res.status}` };
|
|
33034
|
+
const fileBuffer = Buffer.from(await res.arrayBuffer());
|
|
33035
|
+
const ext2 = extname(new URL(imageUrl).pathname) || ".jpg";
|
|
33036
|
+
const contentType = res.headers.get("content-type") || "image/jpeg";
|
|
33037
|
+
const filename = `${type}-${Date.now()}${ext2}`;
|
|
33038
|
+
const uploadRes = await fetch(`${apiBase}/api/blog/upload-image`, {
|
|
33039
|
+
method: "POST",
|
|
33040
|
+
headers: {
|
|
33041
|
+
Authorization: `Bearer ${token}`,
|
|
33042
|
+
"Content-Type": contentType,
|
|
33043
|
+
"X-Filename": filename,
|
|
33044
|
+
"X-Image-Type": type
|
|
33045
|
+
},
|
|
33046
|
+
body: fileBuffer
|
|
33047
|
+
});
|
|
33048
|
+
if (!uploadRes.ok) return { success: false, error: await uploadRes.text() };
|
|
33049
|
+
const { url } = await uploadRes.json();
|
|
33050
|
+
return { success: true, url };
|
|
33051
|
+
} catch (err) {
|
|
33052
|
+
return { success: false, error: err.message };
|
|
33053
|
+
}
|
|
33054
|
+
}
|
|
33055
|
+
var inkSaveSchema, inkDeleteSchema, inkWriteSchema, inkTagsSchema;
|
|
33461
33056
|
var init_ink = __esm({
|
|
33462
33057
|
"src/tools/ink.ts"() {
|
|
33463
33058
|
"use strict";
|
|
33464
33059
|
init_zod();
|
|
33465
33060
|
init_knowledge();
|
|
33466
33061
|
init_push();
|
|
33062
|
+
init_state();
|
|
33063
|
+
init_logger();
|
|
33467
33064
|
inkSaveSchema = external_exports.object({
|
|
33065
|
+
id: external_exports.string().optional().describe("\u77E5\u8BC6\u7247\u6BB5 ID\uFF08\u63D0\u4F9B\u5219\u66F4\u65B0\uFF0C\u4E0D\u63D0\u4F9B\u5219\u65B0\u5EFA\uFF09"),
|
|
33468
33066
|
content: external_exports.string().describe("\u8981\u4FDD\u5B58\u7684\u5185\u5BB9\uFF08\u5FC5\u586B\uFF09"),
|
|
33469
33067
|
title: external_exports.string().describe("\u6807\u9898\uFF08Claude \u81EA\u52A8\u751F\u6210\uFF09"),
|
|
33470
|
-
tags: external_exports.array(external_exports.string()).optional().default([]).describe("\u6807\u7B7E
|
|
33471
|
-
category: external_exports.enum(["insight", "decision", "analysis", "idea", "reference", "action"]).optional().default("reference").describe("\u5206\u7C7B
|
|
33472
|
-
source_type: external_exports.enum(["conversation", "url", "manual"]).optional().default("conversation").describe("\u6765\u6E90\u7C7B\u578B
|
|
33473
|
-
url: external_exports.string().optional().describe("\u6765\u6E90 URL
|
|
33474
|
-
});
|
|
33475
|
-
inkSearchSchema = external_exports.object({
|
|
33476
|
-
query: external_exports.string().optional().describe("\u641C\u7D22\u5173\u952E\u8BCD"),
|
|
33477
|
-
tags: external_exports.array(external_exports.string()).optional().describe("\u6309\u6807\u7B7E\u8FC7\u6EE4"),
|
|
33478
|
-
category: external_exports.enum(["insight", "decision", "analysis", "idea", "reference", "action"]).optional().describe("\u6309\u5206\u7C7B\u8FC7\u6EE4"),
|
|
33479
|
-
date_from: external_exports.string().optional().describe("\u8D77\u59CB\u65E5\u671F\uFF08ISO \u683C\u5F0F\uFF09"),
|
|
33480
|
-
date_to: external_exports.string().optional().describe("\u622A\u6B62\u65E5\u671F\uFF08ISO \u683C\u5F0F\uFF09"),
|
|
33481
|
-
limit: external_exports.number().optional().default(10).describe("\u8FD4\u56DE\u6570\u91CF\uFF0C\u9ED8\u8BA4 10")
|
|
33482
|
-
});
|
|
33483
|
-
inkGetSchema = external_exports.object({
|
|
33484
|
-
id: external_exports.string().describe("\u77E5\u8BC6\u7247\u6BB5 ID")
|
|
33485
|
-
});
|
|
33486
|
-
inkReviewSchema = external_exports.object({
|
|
33487
|
-
period: external_exports.enum(["today", "week", "month", "custom"]).optional().default("week").describe("\u56DE\u987E\u65F6\u95F4\u6BB5\uFF1Atoday / week / month / custom"),
|
|
33488
|
-
date_from: external_exports.string().optional().describe("\u81EA\u5B9A\u4E49\u8D77\u59CB\u65E5\u671F\uFF08ISO \u683C\u5F0F\uFF0Cperiod=custom \u65F6\u4F7F\u7528\uFF09"),
|
|
33489
|
-
date_to: external_exports.string().optional().describe("\u81EA\u5B9A\u4E49\u622A\u6B62\u65E5\u671F\uFF08ISO \u683C\u5F0F\uFF0Cperiod=custom \u65F6\u4F7F\u7528\uFF09"),
|
|
33490
|
-
category: external_exports.enum(["insight", "decision", "analysis", "idea", "reference", "action"]).optional().describe("\u6309\u5206\u7C7B\u8FC7\u6EE4")
|
|
33491
|
-
});
|
|
33492
|
-
inkUpdateSchema = external_exports.object({
|
|
33493
|
-
id: external_exports.string().describe("\u77E5\u8BC6\u7247\u6BB5 ID"),
|
|
33494
|
-
title: external_exports.string().optional().describe("\u65B0\u6807\u9898"),
|
|
33495
|
-
content: external_exports.string().optional().describe("\u65B0\u5185\u5BB9"),
|
|
33496
|
-
tags: external_exports.array(external_exports.string()).optional().describe("\u65B0\u6807\u7B7E\uFF08\u5B8C\u6574\u66FF\u6362\uFF09"),
|
|
33497
|
-
category: external_exports.enum(["insight", "decision", "analysis", "idea", "reference", "action"]).optional().describe("\u65B0\u5206\u7C7B")
|
|
33068
|
+
tags: external_exports.array(external_exports.string()).optional().default([]).describe("\u6807\u7B7E"),
|
|
33069
|
+
category: external_exports.enum(["insight", "decision", "analysis", "idea", "reference", "action"]).optional().default("reference").describe("\u5206\u7C7B"),
|
|
33070
|
+
source_type: external_exports.enum(["conversation", "url", "manual"]).optional().default("conversation").describe("\u6765\u6E90\u7C7B\u578B"),
|
|
33071
|
+
url: external_exports.string().optional().describe("\u6765\u6E90 URL")
|
|
33498
33072
|
});
|
|
33499
33073
|
inkDeleteSchema = external_exports.object({
|
|
33500
33074
|
id: external_exports.string().describe("\u77E5\u8BC6\u7247\u6BB5 ID"),
|
|
33501
33075
|
confirm: external_exports.boolean().optional().default(false).describe("\u786E\u8BA4\u5220\u9664\uFF08\u5FC5\u987B\u4E3A true \u624D\u4F1A\u6267\u884C\u5220\u9664\uFF09")
|
|
33502
33076
|
});
|
|
33503
|
-
|
|
33504
|
-
|
|
33505
|
-
|
|
33506
|
-
|
|
33507
|
-
|
|
33508
|
-
|
|
33077
|
+
inkWriteSchema = external_exports.object({
|
|
33078
|
+
title: external_exports.string().describe("\u6587\u7AE0\u6807\u9898"),
|
|
33079
|
+
content: external_exports.string().describe("Markdown \u5168\u6587"),
|
|
33080
|
+
cover: external_exports.string().optional().describe("\u5C01\u9762\u56FE\uFF08\u672C\u5730\u8DEF\u5F84\u6216 URL\uFF0C\u81EA\u52A8\u4E0A\u4F20\uFF09"),
|
|
33081
|
+
tags: external_exports.array(external_exports.string()).optional().default([]).describe("\u6587\u7AE0\u6807\u7B7E"),
|
|
33082
|
+
category: external_exports.string().optional().describe("\u6587\u7AE0\u5206\u7C7B"),
|
|
33083
|
+
excerpt: external_exports.string().optional().describe("\u6458\u8981\uFF08\u4E0D\u586B\u81EA\u52A8\u622A\u53D6\u524D 200 \u5B57\uFF09"),
|
|
33084
|
+
source_ids: external_exports.array(external_exports.string()).optional().describe("\u5173\u8054\u7684\u7D20\u6750 ink ID\uFF08\u6EAF\u6E90\uFF09")
|
|
33509
33085
|
});
|
|
33510
33086
|
inkTagsSchema = external_exports.object({
|
|
33511
33087
|
action: external_exports.enum(["list", "rename", "merge"]).describe("\u64CD\u4F5C\uFF1Alist\uFF08\u5217\u51FA\u6240\u6709\u6807\u7B7E\uFF09/ rename\uFF08\u91CD\u547D\u540D\uFF09/ merge\uFF08\u5408\u5E76\uFF09"),
|
|
@@ -33516,6 +33092,233 @@ var init_ink = __esm({
|
|
|
33516
33092
|
}
|
|
33517
33093
|
});
|
|
33518
33094
|
|
|
33095
|
+
// src/tools/source.ts
|
|
33096
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
33097
|
+
import { join as join5 } from "path";
|
|
33098
|
+
import { readdirSync as readdirSync2 } from "fs";
|
|
33099
|
+
import { execSync } from "child_process";
|
|
33100
|
+
async function sourceCrawl(input) {
|
|
33101
|
+
const config2 = await getConfig();
|
|
33102
|
+
const crawlerDir = join5(config2.workflowDir || process.cwd(), "tools", "crawler");
|
|
33103
|
+
const configPath = join5(crawlerDir, "config.json");
|
|
33104
|
+
let crawlerConfig;
|
|
33105
|
+
try {
|
|
33106
|
+
crawlerConfig = JSON.parse(await readFile4(configPath, "utf-8"));
|
|
33107
|
+
} catch {
|
|
33108
|
+
crawlerConfig = { sources: [] };
|
|
33109
|
+
}
|
|
33110
|
+
if (crawlerConfig.sources.length === 0) {
|
|
33111
|
+
return { success: false, message: "\u6682\u65E0\u914D\u7F6E\u722C\u866B\u6E90\u3002\u8BF7\u5148\u7528 source.subscribe \u6DFB\u52A0\u3002" };
|
|
33112
|
+
}
|
|
33113
|
+
const targets = input.sourceId ? crawlerConfig.sources.filter((s) => s.id === input.sourceId) : crawlerConfig.sources.filter((s) => s.enabled !== false);
|
|
33114
|
+
if (targets.length === 0) {
|
|
33115
|
+
return {
|
|
33116
|
+
success: false,
|
|
33117
|
+
message: input.sourceId ? `\u672A\u627E\u5230\u722C\u866B\u6E90: ${input.sourceId}` : "\u6CA1\u6709\u5DF2\u542F\u7528\u7684\u722C\u866B\u6E90"
|
|
33118
|
+
};
|
|
33119
|
+
}
|
|
33120
|
+
const crawlScript = join5(crawlerDir, "crawl.mjs");
|
|
33121
|
+
const args2 = input.sourceId ? `--source ${input.sourceId}` : "";
|
|
33122
|
+
try {
|
|
33123
|
+
execSync(`node "${crawlScript}" ${args2}`, {
|
|
33124
|
+
cwd: crawlerDir,
|
|
33125
|
+
encoding: "utf-8",
|
|
33126
|
+
timeout: 5 * 60 * 1e3,
|
|
33127
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
33128
|
+
});
|
|
33129
|
+
let saved = 0;
|
|
33130
|
+
let queued = 0;
|
|
33131
|
+
for (const target of targets) {
|
|
33132
|
+
const sourceDir = join5(config2.workflowDir, "sources", "articles", target.id);
|
|
33133
|
+
let files;
|
|
33134
|
+
try {
|
|
33135
|
+
files = readdirSync2(sourceDir).filter((f) => f.endsWith(".md"));
|
|
33136
|
+
} catch {
|
|
33137
|
+
continue;
|
|
33138
|
+
}
|
|
33139
|
+
for (const f of files) {
|
|
33140
|
+
const filePath = join5(sourceDir, f);
|
|
33141
|
+
try {
|
|
33142
|
+
const raw = await readFile4(filePath, "utf-8");
|
|
33143
|
+
const { data, content } = (0, import_gray_matter2.default)(raw);
|
|
33144
|
+
const title = data.title || f.replace(/^\d{4}-\d{2}-\d{2}-/, "").replace(/\.md$/, "").replace(/-/g, " ");
|
|
33145
|
+
const url = data.url || "";
|
|
33146
|
+
const { id } = await saveKnowledge({
|
|
33147
|
+
content: content.trim(),
|
|
33148
|
+
title,
|
|
33149
|
+
tags: data.tags || [],
|
|
33150
|
+
category: "reference",
|
|
33151
|
+
source_type: "url",
|
|
33152
|
+
url
|
|
33153
|
+
});
|
|
33154
|
+
saved++;
|
|
33155
|
+
if (!data.tags || data.tags.length === 0) {
|
|
33156
|
+
await addToTagQueue({
|
|
33157
|
+
knowledgeId: id,
|
|
33158
|
+
title,
|
|
33159
|
+
addedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33160
|
+
source: "crawl",
|
|
33161
|
+
retryCount: 0
|
|
33162
|
+
});
|
|
33163
|
+
queued++;
|
|
33164
|
+
}
|
|
33165
|
+
fireAndForgetPush({
|
|
33166
|
+
knowledge: [{
|
|
33167
|
+
id,
|
|
33168
|
+
title,
|
|
33169
|
+
tags: data.tags || [],
|
|
33170
|
+
category: "reference",
|
|
33171
|
+
source_type: "url",
|
|
33172
|
+
url,
|
|
33173
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33174
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
33175
|
+
}]
|
|
33176
|
+
});
|
|
33177
|
+
} catch {
|
|
33178
|
+
}
|
|
33179
|
+
}
|
|
33180
|
+
}
|
|
33181
|
+
return {
|
|
33182
|
+
success: true,
|
|
33183
|
+
message: [
|
|
33184
|
+
`\u2705 \u722C\u53D6\u5B8C\u6210`,
|
|
33185
|
+
` \u76EE\u6807\u6E90: ${targets.map((t) => t.name).join(", ")}`,
|
|
33186
|
+
` \u4FDD\u5B58\u5230\u77E5\u8BC6\u5E93: ${saved} \u7BC7`,
|
|
33187
|
+
queued > 0 ? ` \u52A0\u5165\u6807\u7B7E\u961F\u5217: ${queued} \u7BC7\uFF08\u7B49\u5F85 AI \u6253\u6807\u7B7E\uFF09` : ""
|
|
33188
|
+
].filter(Boolean).join("\n"),
|
|
33189
|
+
data: { sources: targets.map((t) => t.name), saved, queued }
|
|
33190
|
+
};
|
|
33191
|
+
} catch (err) {
|
|
33192
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
33193
|
+
if (message.includes("ETIMEDOUT") || message.includes("timed out")) {
|
|
33194
|
+
return { success: false, message: "\u722C\u53D6\u8D85\u65F6\uFF085 \u5206\u949F\u9650\u5236\uFF09\u3002\u8BF7\u5C1D\u8BD5\u6307\u5B9A\u5355\u4E2A\u6E90: source.crawl({ sourceId: 'xxx' })" };
|
|
33195
|
+
}
|
|
33196
|
+
return { success: false, message: `\u722C\u53D6\u5931\u8D25: ${message.slice(0, 200)}` };
|
|
33197
|
+
}
|
|
33198
|
+
}
|
|
33199
|
+
var import_gray_matter2, sourceCrawlSchema;
|
|
33200
|
+
var init_source = __esm({
|
|
33201
|
+
"src/tools/source.ts"() {
|
|
33202
|
+
"use strict";
|
|
33203
|
+
init_zod();
|
|
33204
|
+
import_gray_matter2 = __toESM(require_gray_matter(), 1);
|
|
33205
|
+
init_state();
|
|
33206
|
+
init_knowledge();
|
|
33207
|
+
init_push();
|
|
33208
|
+
sourceCrawlSchema = external_exports.object({
|
|
33209
|
+
sourceId: external_exports.string().optional().describe("\u6307\u5B9A\u722C\u866B\u6E90\u540D\u79F0\uFF0C\u4E0D\u4F20\u5219\u5168\u91CF")
|
|
33210
|
+
});
|
|
33211
|
+
}
|
|
33212
|
+
});
|
|
33213
|
+
|
|
33214
|
+
// src/tools/subscribe.ts
|
|
33215
|
+
import { readFile as readFile5, writeFile as writeFile3, mkdir as mkdir5 } from "fs/promises";
|
|
33216
|
+
import { join as join6 } from "path";
|
|
33217
|
+
async function readCrawlerConfig(configPath) {
|
|
33218
|
+
try {
|
|
33219
|
+
return JSON.parse(await readFile5(configPath, "utf-8"));
|
|
33220
|
+
} catch {
|
|
33221
|
+
return { sources: [] };
|
|
33222
|
+
}
|
|
33223
|
+
}
|
|
33224
|
+
async function sourceSubscribe(input) {
|
|
33225
|
+
const config2 = await getConfig();
|
|
33226
|
+
const crawlerDir = join6(config2.workflowDir || process.cwd(), "tools", "crawler");
|
|
33227
|
+
await mkdir5(crawlerDir, { recursive: true });
|
|
33228
|
+
const configPath = join6(crawlerDir, "config.json");
|
|
33229
|
+
const crawlerConfig = await readCrawlerConfig(configPath);
|
|
33230
|
+
if (input.action === "list") {
|
|
33231
|
+
return {
|
|
33232
|
+
success: true,
|
|
33233
|
+
message: `\u5171 ${crawlerConfig.sources.length} \u4E2A\u8BA2\u9605\u6E90`,
|
|
33234
|
+
data: crawlerConfig.sources
|
|
33235
|
+
};
|
|
33236
|
+
}
|
|
33237
|
+
if (input.action === "add") {
|
|
33238
|
+
if (!input.id || !input.name || !input.url) {
|
|
33239
|
+
return { success: false, message: "\u6DFB\u52A0\u8BA2\u9605\u6E90\u9700\u8981 id, name, url \u53C2\u6570" };
|
|
33240
|
+
}
|
|
33241
|
+
if (crawlerConfig.sources.some((s) => s.id === input.id)) {
|
|
33242
|
+
return { success: false, message: `\u8BA2\u9605\u6E90 ${input.id} \u5DF2\u5B58\u5728` };
|
|
33243
|
+
}
|
|
33244
|
+
const newSource = {
|
|
33245
|
+
id: input.id,
|
|
33246
|
+
name: input.name,
|
|
33247
|
+
blogUrl: input.url,
|
|
33248
|
+
type: input.type === "blog" ? "paginated" : input.type || "rss",
|
|
33249
|
+
icon: input.icon || "",
|
|
33250
|
+
enabled: true
|
|
33251
|
+
};
|
|
33252
|
+
if (input.crawlConfig) {
|
|
33253
|
+
newSource.articleSelector = input.crawlConfig.articleSelector;
|
|
33254
|
+
if (input.crawlConfig.articleUrlPattern) newSource.articleUrlPattern = input.crawlConfig.articleUrlPattern;
|
|
33255
|
+
if (input.crawlConfig.pagination) newSource.pagination = input.crawlConfig.pagination;
|
|
33256
|
+
if (input.crawlConfig.excludePatterns) newSource.excludePatterns = input.crawlConfig.excludePatterns;
|
|
33257
|
+
if (input.crawlConfig.maxArticles) newSource.maxArticles = input.crawlConfig.maxArticles;
|
|
33258
|
+
}
|
|
33259
|
+
crawlerConfig.sources.push(newSource);
|
|
33260
|
+
await writeFile3(configPath, JSON.stringify(crawlerConfig, null, 2));
|
|
33261
|
+
fireAndForgetPush({
|
|
33262
|
+
crawlerSources: crawlerConfig.sources.map((s) => ({
|
|
33263
|
+
id: s.id,
|
|
33264
|
+
name: s.name,
|
|
33265
|
+
url: s.blogUrl || s.url,
|
|
33266
|
+
type: s.type,
|
|
33267
|
+
icon: s.icon || "",
|
|
33268
|
+
enabled: s.enabled !== false
|
|
33269
|
+
}))
|
|
33270
|
+
});
|
|
33271
|
+
return { success: true, message: `\u8BA2\u9605\u6E90 ${input.name} \u5DF2\u6DFB\u52A0` };
|
|
33272
|
+
}
|
|
33273
|
+
if (input.action === "remove") {
|
|
33274
|
+
if (!input.id) {
|
|
33275
|
+
return { success: false, message: "\u5220\u9664\u8BA2\u9605\u6E90\u9700\u8981 id \u53C2\u6570" };
|
|
33276
|
+
}
|
|
33277
|
+
crawlerConfig.sources = crawlerConfig.sources.filter((s) => s.id !== input.id);
|
|
33278
|
+
await writeFile3(configPath, JSON.stringify(crawlerConfig, null, 2));
|
|
33279
|
+
fireAndForgetPush({
|
|
33280
|
+
crawlerSources: crawlerConfig.sources.map((s) => ({
|
|
33281
|
+
id: s.id,
|
|
33282
|
+
name: s.name,
|
|
33283
|
+
url: s.blogUrl || s.url,
|
|
33284
|
+
type: s.type,
|
|
33285
|
+
icon: s.icon || "",
|
|
33286
|
+
enabled: s.enabled !== false
|
|
33287
|
+
}))
|
|
33288
|
+
});
|
|
33289
|
+
return { success: true, message: `\u8BA2\u9605\u6E90 ${input.id} \u5DF2\u5220\u9664` };
|
|
33290
|
+
}
|
|
33291
|
+
return { success: false, message: "\u672A\u77E5\u64CD\u4F5C" };
|
|
33292
|
+
}
|
|
33293
|
+
var sourceSubscribeSchema;
|
|
33294
|
+
var init_subscribe = __esm({
|
|
33295
|
+
"src/tools/subscribe.ts"() {
|
|
33296
|
+
"use strict";
|
|
33297
|
+
init_zod();
|
|
33298
|
+
init_state();
|
|
33299
|
+
init_push();
|
|
33300
|
+
sourceSubscribeSchema = external_exports.object({
|
|
33301
|
+
action: external_exports.enum(["add", "remove", "list"]).describe("\u64CD\u4F5C\u7C7B\u578B"),
|
|
33302
|
+
id: external_exports.string().optional().describe("\u8BA2\u9605\u6E90 ID"),
|
|
33303
|
+
name: external_exports.string().optional().describe("\u8BA2\u9605\u6E90\u540D\u79F0"),
|
|
33304
|
+
url: external_exports.string().optional().describe("RSS/\u535A\u5BA2 URL"),
|
|
33305
|
+
type: external_exports.enum(["rss", "blog", "sitemap"]).optional().describe("\u6E90\u7C7B\u578B"),
|
|
33306
|
+
icon: external_exports.string().optional().describe("\u6765\u6E90 icon URL"),
|
|
33307
|
+
crawlConfig: external_exports.object({
|
|
33308
|
+
articleSelector: external_exports.string(),
|
|
33309
|
+
articleUrlPattern: external_exports.string().optional(),
|
|
33310
|
+
pagination: external_exports.object({
|
|
33311
|
+
pattern: external_exports.string(),
|
|
33312
|
+
startPage: external_exports.number(),
|
|
33313
|
+
maxPages: external_exports.number()
|
|
33314
|
+
}).optional(),
|
|
33315
|
+
excludePatterns: external_exports.array(external_exports.string()).optional(),
|
|
33316
|
+
maxArticles: external_exports.number().optional()
|
|
33317
|
+
}).optional().describe("\u722C\u53D6\u9002\u914D\u89C4\u5219\uFF08Claude \u5206\u6790\u751F\u6210\uFF09")
|
|
33318
|
+
});
|
|
33319
|
+
}
|
|
33320
|
+
});
|
|
33321
|
+
|
|
33519
33322
|
// src/index.ts
|
|
33520
33323
|
var index_exports = {};
|
|
33521
33324
|
async function main() {
|
|
@@ -33523,13 +33326,13 @@ async function main() {
|
|
|
33523
33326
|
const state = await readState();
|
|
33524
33327
|
if (state.config.workflowDir) {
|
|
33525
33328
|
setWorkDir(state.config.workflowDir);
|
|
33526
|
-
console.error(`[ClaudeInk MCP] workDir restored: ${state.config.workflowDir}`);
|
|
33527
33329
|
}
|
|
33330
|
+
setLogLevel(state.config.logLevel || "INFO");
|
|
33528
33331
|
} catch {
|
|
33529
33332
|
}
|
|
33530
33333
|
const transport = new StdioServerTransport();
|
|
33531
33334
|
await server.connect(transport);
|
|
33532
|
-
|
|
33335
|
+
await log("INFO", "server", "started (8 tools)");
|
|
33533
33336
|
}
|
|
33534
33337
|
var server;
|
|
33535
33338
|
var init_index = __esm({
|
|
@@ -33537,80 +33340,68 @@ var init_index = __esm({
|
|
|
33537
33340
|
"use strict";
|
|
33538
33341
|
init_mcp();
|
|
33539
33342
|
init_stdio2();
|
|
33540
|
-
init_source();
|
|
33541
|
-
init_subscribe();
|
|
33542
|
-
init_sync();
|
|
33543
33343
|
init_workflow();
|
|
33344
|
+
init_sync();
|
|
33544
33345
|
init_ink();
|
|
33346
|
+
init_source();
|
|
33347
|
+
init_subscribe();
|
|
33545
33348
|
init_state();
|
|
33349
|
+
init_logger();
|
|
33546
33350
|
server = new McpServer({
|
|
33547
33351
|
name: "ClaudeInk",
|
|
33548
|
-
version: "
|
|
33352
|
+
version: "2.0.2"
|
|
33549
33353
|
});
|
|
33550
|
-
server.tool("
|
|
33354
|
+
server.tool("ink.init", "\u521D\u59CB\u5316\u77E5\u8BC6\u5E93\uFF08\u521B\u5EFA\u76EE\u5F55 + \u6FC0\u6D3B License + \u540C\u6B65\u4E91\u7AEF\uFF09", workflowInitSchema.shape, async (input) => {
|
|
33551
33355
|
const result = await workflowInit(input);
|
|
33552
33356
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33553
33357
|
});
|
|
33554
|
-
server.tool("sync", "\u4ECE\u4E91\u7AEF\u540C\u6B65\u77E5\u8BC6\u5143\u6570\u636E", syncSchema.shape, async (input) => {
|
|
33358
|
+
server.tool("ink.sync", "\u4ECE\u4E91\u7AEF\u540C\u6B65\u77E5\u8BC6\u5143\u6570\u636E", syncSchema.shape, async (input) => {
|
|
33555
33359
|
const result = await sync2(input);
|
|
33556
33360
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33557
33361
|
});
|
|
33558
|
-
server.tool("ink.save", "\u4FDD\u5B58\
|
|
33362
|
+
server.tool("ink.save", "\u4FDD\u5B58\u6216\u66F4\u65B0\u77E5\u8BC6\u7D20\u6750\uFF08\u6709 id \u66F4\u65B0\uFF0C\u65E0 id \u65B0\u5EFA\uFF09", inkSaveSchema.shape, async (input) => {
|
|
33559
33363
|
const result = await inkSave(input);
|
|
33560
33364
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33561
33365
|
});
|
|
33562
|
-
server.tool("ink.search", "\u641C\u7D22\u77E5\u8BC6\u5E93\uFF08\u652F\u6301\u5173\u952E\u8BCD\u3001\u6807\u7B7E\u3001\u5206\u7C7B\u3001\u65F6\u95F4\u8303\u56F4\u8FC7\u6EE4\uFF09", inkSearchSchema.shape, async (input) => {
|
|
33563
|
-
const result = await inkSearch(input);
|
|
33564
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33565
|
-
});
|
|
33566
|
-
server.tool("ink.get", "\u83B7\u53D6\u77E5\u8BC6\u7247\u6BB5\u5B8C\u6574\u5185\u5BB9", inkGetSchema.shape, async (input) => {
|
|
33567
|
-
const result = await inkGet(input);
|
|
33568
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33569
|
-
});
|
|
33570
|
-
server.tool("ink.review", "\u6309\u65F6\u95F4\u6BB5\u56DE\u987E\u77E5\u8BC6\u5E93\uFF08\u7EDF\u8BA1 + \u5217\u8868\uFF09", inkReviewSchema.shape, async (input) => {
|
|
33571
|
-
const result = await inkReview(input);
|
|
33572
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33573
|
-
});
|
|
33574
|
-
server.tool("ink.update", "\u66F4\u65B0\u5DF2\u4FDD\u5B58\u7684\u77E5\u8BC6\u7247\u6BB5\uFF08\u6807\u9898/\u5185\u5BB9/\u6807\u7B7E/\u5206\u7C7B\uFF09", inkUpdateSchema.shape, async (input) => {
|
|
33575
|
-
const result = await inkUpdate(input);
|
|
33576
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33577
|
-
});
|
|
33578
33366
|
server.tool("ink.delete", "\u5220\u9664\u77E5\u8BC6\u7247\u6BB5\uFF08\u9700\u786E\u8BA4\uFF09", inkDeleteSchema.shape, async (input) => {
|
|
33579
33367
|
const result = await inkDelete(input);
|
|
33580
33368
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33581
33369
|
});
|
|
33582
|
-
server.tool("ink.
|
|
33583
|
-
const result = await
|
|
33370
|
+
server.tool("ink.write", "\u5199\u6587\u7AE0\u4FDD\u5B58\u4E3A\u8349\u7A3F\u3002Claude \u5199\u5B8C\u535A\u5BA2\u6587\u7AE0\u540E\u81EA\u52A8\u8C03\u7528\uFF0C\u63D0\u4F9B\u6807\u9898\u3001Markdown \u5185\u5BB9\u3001\u5C01\u9762\u56FE\u548C\u6807\u7B7E\u3002", inkWriteSchema.shape, async (input) => {
|
|
33371
|
+
const result = await inkWrite(input);
|
|
33584
33372
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33585
33373
|
});
|
|
33586
33374
|
server.tool("ink.tags", "\u6807\u7B7E\u7BA1\u7406\uFF08\u5217\u51FA / \u91CD\u547D\u540D / \u5408\u5E76\u6807\u7B7E\uFF09", inkTagsSchema.shape, async (input) => {
|
|
33587
33375
|
const result = await inkTags(input);
|
|
33588
33376
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33589
33377
|
});
|
|
33590
|
-
server.tool("
|
|
33378
|
+
server.tool("ink.crawl", "\u89E6\u53D1\u722C\u866B\u6293\u53D6\uFF08\u5185\u5BB9\u81EA\u52A8\u5B58\u5165\u77E5\u8BC6\u5E93\uFF09", sourceCrawlSchema.shape, async (input) => {
|
|
33591
33379
|
const result = await sourceCrawl(input);
|
|
33592
33380
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33593
33381
|
});
|
|
33594
|
-
server.tool("
|
|
33382
|
+
server.tool("ink.subscribe", "\u7BA1\u7406\u8BA2\u9605\u6E90\uFF08\u6DFB\u52A0/\u5220\u9664/\u5217\u51FA\u722C\u866B\u6E90\uFF09", sourceSubscribeSchema.shape, async (input) => {
|
|
33595
33383
|
const result = await sourceSubscribe(input);
|
|
33596
33384
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33597
33385
|
});
|
|
33598
|
-
|
|
33599
|
-
console.error(
|
|
33386
|
+
process.on("unhandledRejection", (err) => {
|
|
33387
|
+
console.error(`[ClaudeInk] Unhandled rejection: ${err}`);
|
|
33388
|
+
});
|
|
33389
|
+
main().catch(async (err) => {
|
|
33390
|
+
await log("ERROR", "server", `fatal: ${err.message || err}`);
|
|
33600
33391
|
process.exit(1);
|
|
33601
33392
|
});
|
|
33602
33393
|
}
|
|
33603
33394
|
});
|
|
33604
33395
|
|
|
33605
33396
|
// src/cli.ts
|
|
33606
|
-
import { writeFile as writeFile4, readFile as
|
|
33607
|
-
import { join as
|
|
33397
|
+
import { writeFile as writeFile4, readFile as readFile6, mkdir as mkdir6, cp, access as access2 } from "fs/promises";
|
|
33398
|
+
import { join as join7, dirname } from "path";
|
|
33608
33399
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
33609
33400
|
var args = process.argv.slice(2);
|
|
33610
33401
|
var command = args[0];
|
|
33611
33402
|
var __filename = fileURLToPath3(import.meta.url);
|
|
33612
33403
|
var __dirname = dirname(__filename);
|
|
33613
|
-
var WORKFLOW_SRC =
|
|
33404
|
+
var WORKFLOW_SRC = join7(__dirname, "..", "workflow");
|
|
33614
33405
|
async function init() {
|
|
33615
33406
|
const keyIdx = args.indexOf("--key");
|
|
33616
33407
|
const key = keyIdx >= 0 ? args[keyIdx + 1] : void 0;
|
|
@@ -33626,8 +33417,8 @@ async function init() {
|
|
|
33626
33417
|
console.log("\u{1F4E6} \u91CA\u653E\u5DE5\u4F5C\u6D41\u6A21\u677F...");
|
|
33627
33418
|
const items = ["CLAUDE.md", "base-rules.md", "platforms", "accounts", "tools"];
|
|
33628
33419
|
for (const item of items) {
|
|
33629
|
-
const src =
|
|
33630
|
-
const dest =
|
|
33420
|
+
const src = join7(WORKFLOW_SRC, item);
|
|
33421
|
+
const dest = join7(cwd, item);
|
|
33631
33422
|
try {
|
|
33632
33423
|
await access2(dest);
|
|
33633
33424
|
console.log(` \u23ED\uFE0F ${item} \u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7`);
|
|
@@ -33647,14 +33438,14 @@ async function init() {
|
|
|
33647
33438
|
".claudeink"
|
|
33648
33439
|
];
|
|
33649
33440
|
for (const dir of dirs) {
|
|
33650
|
-
await
|
|
33441
|
+
await mkdir6(join7(cwd, dir), { recursive: true });
|
|
33651
33442
|
}
|
|
33652
33443
|
console.log(" \u2705 sources/, templates/, .claudeink/");
|
|
33653
33444
|
const { glob: glob2 } = await Promise.resolve().then(() => (init_esm5(), esm_exports));
|
|
33654
33445
|
const yamlFiles = await glob2("accounts/*.yaml", { cwd, ignore: "accounts/_template.yaml" });
|
|
33655
33446
|
for (const yamlFile of yamlFiles) {
|
|
33656
33447
|
try {
|
|
33657
|
-
const content = await
|
|
33448
|
+
const content = await readFile6(join7(cwd, yamlFile), "utf-8");
|
|
33658
33449
|
const idMatch = content.match(/^id:\s*"?([^"\n]+)"?/m);
|
|
33659
33450
|
if (idMatch) {
|
|
33660
33451
|
const id = idMatch[1].trim();
|
|
@@ -33664,9 +33455,9 @@ async function init() {
|
|
|
33664
33455
|
const drafts = (draftsMatch?.[1] || `accounts/${id}/drafts/`).replace("{id}", id).trim();
|
|
33665
33456
|
const published = (publishedMatch?.[1] || `accounts/${id}/published/`).replace("{id}", id).trim();
|
|
33666
33457
|
const assets = (assetsMatch?.[1] || `accounts/${id}/assets/`).replace("{id}", id).trim();
|
|
33667
|
-
await
|
|
33668
|
-
await
|
|
33669
|
-
await
|
|
33458
|
+
await mkdir6(join7(cwd, drafts), { recursive: true });
|
|
33459
|
+
await mkdir6(join7(cwd, published), { recursive: true });
|
|
33460
|
+
await mkdir6(join7(cwd, assets), { recursive: true });
|
|
33670
33461
|
console.log(` \u2705 \u8D26\u53F7 ${id}: ${drafts}, ${published}, ${assets}`);
|
|
33671
33462
|
}
|
|
33672
33463
|
} catch {
|
|
@@ -33682,7 +33473,7 @@ async function init() {
|
|
|
33682
33473
|
const data = await res.json();
|
|
33683
33474
|
if (data.userId) {
|
|
33684
33475
|
await writeFile4(
|
|
33685
|
-
|
|
33476
|
+
join7(cwd, ".claudeink", "credentials.json"),
|
|
33686
33477
|
JSON.stringify(data, null, 2),
|
|
33687
33478
|
{ mode: 384 }
|
|
33688
33479
|
);
|
|
@@ -33696,11 +33487,11 @@ async function init() {
|
|
|
33696
33487
|
console.log(" \u53EF\u7A0D\u540E\u624B\u52A8\u6FC0\u6D3B\u3002");
|
|
33697
33488
|
}
|
|
33698
33489
|
try {
|
|
33699
|
-
await access2(
|
|
33490
|
+
await access2(join7(cwd, "tools", "crawler", "package.json"));
|
|
33700
33491
|
console.log("\n\u{1F4E6} \u5B89\u88C5\u722C\u866B\u4F9D\u8D56...");
|
|
33701
33492
|
const { execSync: execSync2 } = await import("child_process");
|
|
33702
33493
|
execSync2("npm install --silent", {
|
|
33703
|
-
cwd:
|
|
33494
|
+
cwd: join7(cwd, "tools", "crawler"),
|
|
33704
33495
|
stdio: "pipe"
|
|
33705
33496
|
});
|
|
33706
33497
|
console.log(" \u2705 \u722C\u866B\u4F9D\u8D56\u5DF2\u5B89\u88C5");
|
|
@@ -33735,7 +33526,10 @@ switch (command) {
|
|
|
33735
33526
|
console.log("@claudeink/mcp-server v0.0.3");
|
|
33736
33527
|
break;
|
|
33737
33528
|
default:
|
|
33738
|
-
Promise.resolve().then(() => init_index())
|
|
33529
|
+
Promise.resolve().then(() => (init_index(), index_exports)).catch((err) => {
|
|
33530
|
+
console.error(`[ClaudeInk] Fatal: ${err?.message || err}`);
|
|
33531
|
+
process.exit(1);
|
|
33532
|
+
});
|
|
33739
33533
|
break;
|
|
33740
33534
|
}
|
|
33741
33535
|
/*! Bundled license information:
|