@biaoo/tiangong-wiki 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -1
- package/README.zh-CN.md +106 -1
- package/dist/commands/create.js +3 -0
- package/dist/commands/sync.js +3 -0
- package/dist/commands/template.js +3 -0
- package/dist/core/codex-workflow.js +37 -15
- package/dist/core/db.js +19 -0
- package/dist/core/onboarding.js +35 -1
- package/dist/core/page-source.js +25 -0
- package/dist/core/paths.js +10 -0
- package/dist/core/workflow-result.js +5 -0
- package/dist/daemon/audit-log.js +18 -0
- package/dist/daemon/client.js +1 -1
- package/dist/daemon/git-journal.js +114 -0
- package/dist/daemon/server.js +446 -124
- package/dist/daemon/write-actor.js +60 -0
- package/dist/daemon/write-queue.js +360 -0
- package/dist/operations/dashboard.js +4 -9
- package/dist/operations/write.js +93 -5
- package/mcp-server/dist/daemon-client.js +90 -0
- package/mcp-server/dist/index.js +26 -0
- package/mcp-server/dist/server.js +525 -0
- package/package.json +11 -5
- package/references/centralized-service-deployment.md +482 -0
- package/references/examples/centralized-service/centralized.env.example +25 -0
- package/references/examples/centralized-service/nginx-centralized-wiki.conf +68 -0
- package/references/examples/centralized-service/tiangong-wiki-daemon.service +17 -0
- package/references/examples/centralized-service/tiangong-wiki-mcp.service +18 -0
- package/references/troubleshooting.md +22 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathExistsSync } from "../utils/fs.js";
|
|
4
|
+
import { AppError } from "../utils/errors.js";
|
|
5
|
+
function buildGitEnv(actor) {
|
|
6
|
+
const emailLocalPart = actor.actorId.replace(/[^A-Za-z0-9._-]+/g, "_");
|
|
7
|
+
return {
|
|
8
|
+
...process.env,
|
|
9
|
+
GIT_AUTHOR_NAME: actor.actorId,
|
|
10
|
+
GIT_AUTHOR_EMAIL: `${emailLocalPart}@tiangong-wiki.local`,
|
|
11
|
+
GIT_COMMITTER_NAME: actor.actorId,
|
|
12
|
+
GIT_COMMITTER_EMAIL: `${emailLocalPart}@tiangong-wiki.local`,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function runGit(paths, actor, args) {
|
|
16
|
+
const result = spawnSync("git", ["-C", paths.wikiRoot, ...args], {
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
env: buildGitEnv(actor),
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
status: result.status,
|
|
22
|
+
stdout: result.stdout ?? "",
|
|
23
|
+
stderr: result.stderr ?? "",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function collectStageTargets(paths) {
|
|
27
|
+
return [
|
|
28
|
+
path.relative(paths.wikiRoot, paths.wikiPath),
|
|
29
|
+
path.relative(paths.wikiRoot, paths.dbPath),
|
|
30
|
+
path.relative(paths.wikiRoot, paths.templatesPath),
|
|
31
|
+
path.relative(paths.wikiRoot, paths.configPath),
|
|
32
|
+
path.relative(paths.wikiRoot, paths.queueArtifactsPath),
|
|
33
|
+
].filter((entry, index, values) => entry && !entry.startsWith("..") && values.indexOf(entry) === index && pathExistsSync(path.join(paths.wikiRoot, entry)));
|
|
34
|
+
}
|
|
35
|
+
export function commitWriteJournal(paths, actor, input) {
|
|
36
|
+
const gitRoot = runGit(paths, actor, ["rev-parse", "--show-toplevel"]);
|
|
37
|
+
if (gitRoot.status !== 0) {
|
|
38
|
+
throw new AppError("Git repository not initialized for wiki root.", "runtime", {
|
|
39
|
+
code: "git_commit_failed",
|
|
40
|
+
stderr: gitRoot.stderr.trim() || gitRoot.stdout.trim(),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const targets = collectStageTargets(paths);
|
|
44
|
+
const addResult = runGit(paths, actor, ["add", "-A", "--", ...targets]);
|
|
45
|
+
if (addResult.status !== 0) {
|
|
46
|
+
throw new AppError("Failed to stage wiki changes for Git commit.", "runtime", {
|
|
47
|
+
code: "git_commit_failed",
|
|
48
|
+
stderr: addResult.stderr.trim() || addResult.stdout.trim(),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const diffResult = runGit(paths, actor, ["diff", "--cached", "--quiet", "--exit-code"]);
|
|
52
|
+
if (diffResult.status === 0) {
|
|
53
|
+
return {
|
|
54
|
+
status: "no_changes",
|
|
55
|
+
commitHash: null,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (diffResult.status !== 1) {
|
|
59
|
+
throw new AppError("Failed to inspect staged Git changes.", "runtime", {
|
|
60
|
+
code: "git_commit_failed",
|
|
61
|
+
stderr: diffResult.stderr.trim() || diffResult.stdout.trim(),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const commitMessage = `wiki: ${input.operation} ${input.resourceId ?? "*"} by ${actor.actorId}`;
|
|
65
|
+
const commitResult = runGit(paths, actor, ["commit", "-m", commitMessage]);
|
|
66
|
+
if (commitResult.status !== 0) {
|
|
67
|
+
throw new AppError("Failed to create Git journal commit.", "runtime", {
|
|
68
|
+
code: "git_commit_failed",
|
|
69
|
+
stderr: commitResult.stderr.trim() || commitResult.stdout.trim(),
|
|
70
|
+
commitMessage,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const hashResult = runGit(paths, actor, ["rev-parse", "HEAD"]);
|
|
74
|
+
if (hashResult.status !== 0) {
|
|
75
|
+
throw new AppError("Failed to resolve Git commit hash.", "runtime", {
|
|
76
|
+
code: "git_commit_failed",
|
|
77
|
+
stderr: hashResult.stderr.trim() || hashResult.stdout.trim(),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
status: "committed",
|
|
82
|
+
commitHash: hashResult.stdout.trim(),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export class GitPushScheduler {
|
|
86
|
+
paths;
|
|
87
|
+
log;
|
|
88
|
+
enabled;
|
|
89
|
+
delayMs;
|
|
90
|
+
remote;
|
|
91
|
+
timer = null;
|
|
92
|
+
constructor(paths, log, env = process.env) {
|
|
93
|
+
this.paths = paths;
|
|
94
|
+
this.log = log;
|
|
95
|
+
this.enabled = (env.WIKI_GIT_AUTO_PUSH ?? "").trim().toLowerCase() === "true";
|
|
96
|
+
this.delayMs = Number.parseInt(env.WIKI_GIT_PUSH_DELAY_MS ?? "3000", 10) || 3000;
|
|
97
|
+
this.remote = env.WIKI_GIT_PUSH_REMOTE?.trim() || "origin";
|
|
98
|
+
}
|
|
99
|
+
schedule(actor) {
|
|
100
|
+
if (!this.enabled || this.timer) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
this.timer = setTimeout(() => {
|
|
104
|
+
this.timer = null;
|
|
105
|
+
const result = runGit(this.paths, actor, ["push", this.remote, "HEAD"]);
|
|
106
|
+
if (result.status === 0) {
|
|
107
|
+
this.log(`git push ok remote=${this.remote}`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.log(`git push failed remote=${this.remote}: ${result.stderr.trim() || result.stdout.trim()}`);
|
|
111
|
+
}, this.delayMs);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|