jishushell 0.4.30 → 0.5.15

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.
Files changed (182) hide show
  1. package/apps/anythingllm-container.yaml +287 -0
  2. package/apps/browserless-chromium-container.yaml +18 -6
  3. package/apps/filebrowser-container.yaml +163 -0
  4. package/apps/openclaw-binary.yaml +8 -0
  5. package/apps/openclaw-container.yaml +9 -1
  6. package/apps/openclaw-with-searxng-container.yaml +4 -0
  7. package/apps/searxng-container.yaml +5 -4
  8. package/apps/weknora-container.yaml +471 -0
  9. package/dist/cli/panel.js.map +1 -1
  10. package/dist/config.d.ts +19 -0
  11. package/dist/config.js +99 -1
  12. package/dist/config.js.map +1 -1
  13. package/dist/install.js +3 -3
  14. package/dist/install.js.map +1 -1
  15. package/dist/routes/auth.js +2 -2
  16. package/dist/routes/auth.js.map +1 -1
  17. package/dist/routes/backup.js +64 -11
  18. package/dist/routes/backup.js.map +1 -1
  19. package/dist/routes/external-mounts.d.ts +17 -0
  20. package/dist/routes/external-mounts.js +73 -0
  21. package/dist/routes/external-mounts.js.map +1 -0
  22. package/dist/routes/file-mounts.d.ts +13 -0
  23. package/dist/routes/file-mounts.js +90 -0
  24. package/dist/routes/file-mounts.js.map +1 -0
  25. package/dist/routes/files-organize.d.ts +28 -0
  26. package/dist/routes/files-organize.js +167 -0
  27. package/dist/routes/files-organize.js.map +1 -0
  28. package/dist/routes/files.d.ts +31 -0
  29. package/dist/routes/files.js +321 -0
  30. package/dist/routes/files.js.map +1 -0
  31. package/dist/routes/instances.js +45 -7
  32. package/dist/routes/instances.js.map +1 -1
  33. package/dist/routes/internal.d.ts +2 -0
  34. package/dist/routes/internal.js +59 -0
  35. package/dist/routes/internal.js.map +1 -0
  36. package/dist/routes/setup.js +9 -9
  37. package/dist/routes/setup.js.map +1 -1
  38. package/dist/routes/system.js +1 -1
  39. package/dist/routes/system.js.map +1 -1
  40. package/dist/routes/webdav.d.ts +17 -0
  41. package/dist/routes/webdav.js +114 -0
  42. package/dist/routes/webdav.js.map +1 -0
  43. package/dist/server.js +341 -3
  44. package/dist/server.js.map +1 -1
  45. package/dist/services/app/app-compiler.d.ts +1 -1
  46. package/dist/services/app/app-compiler.js +5 -5
  47. package/dist/services/app/app-compiler.js.map +1 -1
  48. package/dist/services/app/app-manager.d.ts +1 -0
  49. package/dist/services/app/app-manager.js +172 -41
  50. package/dist/services/app/app-manager.js.map +1 -1
  51. package/dist/services/app/custom-manager.js.map +1 -1
  52. package/dist/services/app/hermes-agent-manager.js +1 -0
  53. package/dist/services/app/hermes-agent-manager.js.map +1 -1
  54. package/dist/services/app/ollama-manager.js +1 -1
  55. package/dist/services/app/ollama-manager.js.map +1 -1
  56. package/dist/services/app/openclaw-manager.js +20 -3
  57. package/dist/services/app/openclaw-manager.js.map +1 -1
  58. package/dist/services/app/platform-transform.d.ts +32 -0
  59. package/dist/services/app/platform-transform.js +65 -0
  60. package/dist/services/app/platform-transform.js.map +1 -0
  61. package/dist/services/app-passwords.d.ts +61 -0
  62. package/dist/services/app-passwords.js +173 -0
  63. package/dist/services/app-passwords.js.map +1 -0
  64. package/dist/services/backup-manager.d.ts +11 -0
  65. package/dist/services/backup-manager.js +177 -4
  66. package/dist/services/backup-manager.js.map +1 -1
  67. package/dist/services/connection-apply.d.ts +2 -0
  68. package/dist/services/connection-apply.js +55 -1
  69. package/dist/services/connection-apply.js.map +1 -1
  70. package/dist/services/connection-resolver.js +1 -1
  71. package/dist/services/connection-resolver.js.map +1 -1
  72. package/dist/services/connection-transactor.d.ts +2 -0
  73. package/dist/services/connection-transactor.js +12 -2
  74. package/dist/services/connection-transactor.js.map +1 -1
  75. package/dist/services/external-mounts.d.ts +40 -0
  76. package/dist/services/external-mounts.js +187 -0
  77. package/dist/services/external-mounts.js.map +1 -0
  78. package/dist/services/files-manager.d.ts +252 -0
  79. package/dist/services/files-manager.js +1075 -0
  80. package/dist/services/files-manager.js.map +1 -0
  81. package/dist/services/files-mounts.d.ts +42 -0
  82. package/dist/services/files-mounts.js +207 -0
  83. package/dist/services/files-mounts.js.map +1 -0
  84. package/dist/services/instance-manager.js +1 -23
  85. package/dist/services/instance-manager.js.map +1 -1
  86. package/dist/services/llm-proxy/index.js.map +1 -1
  87. package/dist/services/llm-proxy/ssrf.js +6 -2
  88. package/dist/services/llm-proxy/ssrf.js.map +1 -1
  89. package/dist/services/nomad-manager.d.ts +4 -0
  90. package/dist/services/nomad-manager.js +53 -19
  91. package/dist/services/nomad-manager.js.map +1 -1
  92. package/dist/services/organize/applier.d.ts +46 -0
  93. package/dist/services/organize/applier.js +218 -0
  94. package/dist/services/organize/applier.js.map +1 -0
  95. package/dist/services/organize/rules.d.ts +57 -0
  96. package/dist/services/organize/rules.js +286 -0
  97. package/dist/services/organize/rules.js.map +1 -0
  98. package/dist/services/organize/scanner.d.ts +50 -0
  99. package/dist/services/organize/scanner.js +366 -0
  100. package/dist/services/organize/scanner.js.map +1 -0
  101. package/dist/services/organize/store.d.ts +14 -0
  102. package/dist/services/organize/store.js +82 -0
  103. package/dist/services/organize/store.js.map +1 -0
  104. package/dist/services/panel-manager.js +20 -1
  105. package/dist/services/panel-manager.js.map +1 -1
  106. package/dist/services/process-manager.js +3 -2
  107. package/dist/services/process-manager.js.map +1 -1
  108. package/dist/services/runtime/adapters/hermes.js +1 -1
  109. package/dist/services/runtime/adapters/hermes.js.map +1 -1
  110. package/dist/services/runtime/adapters/openclaw-routes.d.ts +8 -2
  111. package/dist/services/runtime/adapters/openclaw-routes.js +68 -0
  112. package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -1
  113. package/dist/services/runtime/adapters/openclaw.d.ts +90 -0
  114. package/dist/services/runtime/adapters/openclaw.js +957 -45
  115. package/dist/services/runtime/adapters/openclaw.js.map +1 -1
  116. package/dist/services/runtime/instance.d.ts +1 -1
  117. package/dist/services/runtime/instance.js +1 -1
  118. package/dist/services/runtime/instance.js.map +1 -1
  119. package/dist/services/runtime/mcp-shims/anythingllm-shim.d.ts +46 -0
  120. package/dist/services/runtime/mcp-shims/anythingllm-shim.js +281 -0
  121. package/dist/services/runtime/mcp-shims/anythingllm-shim.js.map +1 -0
  122. package/dist/services/runtime/mcp-shims/drive-shim.d.ts +54 -0
  123. package/dist/services/runtime/mcp-shims/drive-shim.js +489 -0
  124. package/dist/services/runtime/mcp-shims/drive-shim.js.map +1 -0
  125. package/dist/services/runtime/types.d.ts +31 -0
  126. package/dist/services/setup-manager.js +93 -18
  127. package/dist/services/setup-manager.js.map +1 -1
  128. package/dist/services/suggestions.js.map +1 -1
  129. package/dist/services/webdav/server.d.ts +24 -0
  130. package/dist/services/webdav/server.js +420 -0
  131. package/dist/services/webdav/server.js.map +1 -0
  132. package/dist/services/webdav/xml-builder.d.ts +73 -0
  133. package/dist/services/webdav/xml-builder.js +156 -0
  134. package/dist/services/webdav/xml-builder.js.map +1 -0
  135. package/dist/services/workspace-builder.d.ts +29 -0
  136. package/dist/services/workspace-builder.js +188 -0
  137. package/dist/services/workspace-builder.js.map +1 -0
  138. package/dist/types.d.ts +60 -0
  139. package/dist/utils/path-locks.d.ts +30 -0
  140. package/dist/utils/path-locks.js +63 -0
  141. package/dist/utils/path-locks.js.map +1 -0
  142. package/dist/utils/path-safety.d.ts +41 -0
  143. package/dist/utils/path-safety.js +119 -0
  144. package/dist/utils/path-safety.js.map +1 -0
  145. package/dist/utils/safe-write.d.ts +24 -0
  146. package/dist/utils/safe-write.js +82 -0
  147. package/dist/utils/safe-write.js.map +1 -0
  148. package/package.json +16 -1
  149. package/public/assets/Dashboard-BdWPtroF.js +1 -0
  150. package/public/assets/{HermesChatPanel-_GHoklgo.js → HermesChatPanel-B_2HlVBQ.js} +1 -1
  151. package/public/assets/{HermesConfigForm-anDnwUp_.js → HermesConfigForm-DVlhg3WV.js} +2 -2
  152. package/public/assets/{InitPassword-ZU9_-hDr.js → InitPassword-D7glTExX.js} +1 -1
  153. package/public/assets/InstanceDetail-CxSy2cpe.js +92 -0
  154. package/public/assets/{Login-BItXqYAJ.js → Login-Cfr5c2sv.js} +1 -1
  155. package/public/assets/NewInstance-BIYDmJis.js +1 -0
  156. package/public/assets/{ProviderRecommendations-DFYj7Fb6.js → ProviderRecommendations-BuRnvRcI.js} +1 -1
  157. package/public/assets/{Settings-Bttc6QmM.js → Settings-Cc-tYBil.js} +1 -1
  158. package/public/assets/{Setup-Bsxx1zgj.js → Setup-lGZEk5jq.js} +1 -1
  159. package/public/assets/{WeixinLoginPanel-DPZpAKgO.js → WeixinLoginPanel-CoGqzxeV.js} +2 -2
  160. package/public/assets/index-87IJXG-w.css +1 -0
  161. package/public/assets/index-BZc5zH7u.js +19 -0
  162. package/public/assets/{registry-5s2UB6is.js → registry-BWnkJgZ1.js} +2 -2
  163. package/public/assets/{usePolling-Do5Erqm_.js → usePolling-CwwT9KrC.js} +1 -1
  164. package/public/assets/{vendor-i18n-ucpM0OR0.js → vendor-i18n-y9V7Sfuu.js} +1 -1
  165. package/public/assets/{vendor-react-Bk1hRGiY.js → vendor-react-BWrEVJVb.js} +6 -6
  166. package/public/index.html +4 -4
  167. package/scripts/check-app-spec.mjs +18 -4
  168. package/scripts/check-new-file-tests.mjs +230 -0
  169. package/scripts/check-quarantine-expiry.mjs +105 -0
  170. package/scripts/perf/README.md +49 -0
  171. package/scripts/perf/auth.js +99 -0
  172. package/scripts/perf/config.js +63 -0
  173. package/scripts/perf/instances.js +143 -0
  174. package/scripts/perf/proxy.js +96 -0
  175. package/scripts/smoke/files-w1.sh +142 -0
  176. package/scripts/smoke-backend.mjs +122 -0
  177. package/scripts/smoke-post-publish.mjs +346 -0
  178. package/public/assets/Dashboard-rkWp-CXd.js +0 -1
  179. package/public/assets/InstanceDetail-CN0FH1aw.js +0 -92
  180. package/public/assets/NewInstance-BousE6kY.js +0 -1
  181. package/public/assets/index-8xZy1z5k.css +0 -1
  182. package/public/assets/index-Dw3HhUYE.js +0 -19
@@ -0,0 +1,73 @@
1
+ import { validateMount, } from "../services/external-mounts.js";
2
+ import { getPanelConfig, savePanelConfig } from "../config.js";
3
+ export async function externalMountsRoutes(app, deps) {
4
+ // ── GET ────────────────────────────────────────
5
+ app.get("/api/files/external-mounts", async (_req, reply) => {
6
+ const cfg = getPanelConfig();
7
+ const mounts = Array.isArray(cfg.external_mounts)
8
+ ? cfg.external_mounts
9
+ : [];
10
+ reply.send({ mounts });
11
+ });
12
+ // ── POST /test (dry-run) ───────────────────────
13
+ app.post("/api/files/external-mounts/test", async (req, reply) => {
14
+ const candidate = req.body?.mount ?? {};
15
+ const cfg = getPanelConfig();
16
+ const existing = Array.isArray(cfg.external_mounts)
17
+ ? cfg.external_mounts
18
+ : [];
19
+ // Exclude the candidate's own alias from the conflict check so
20
+ // editing a row in place doesn't trigger "already in use".
21
+ const others = existing.filter((m) => m.alias !== candidate.alias);
22
+ const result = validateMount(candidate, others);
23
+ reply.send(result);
24
+ });
25
+ // ── PUT (full replacement) ─────────────────────
26
+ app.put("/api/files/external-mounts", async (req, reply) => {
27
+ const candidate = Array.isArray(req.body?.mounts)
28
+ ? req.body.mounts
29
+ : null;
30
+ if (!candidate) {
31
+ return reply.code(400).send({
32
+ error: "body.mounts must be an array",
33
+ code: "invalid",
34
+ });
35
+ }
36
+ // Validate each, accumulating errors with index so the UI can
37
+ // pinpoint bad rows.
38
+ const validated = [];
39
+ const allErrors = [];
40
+ const allWarnings = [];
41
+ for (let i = 0; i < candidate.length; i++) {
42
+ const r = validateMount(candidate[i] ?? {}, validated);
43
+ if (r.ok) {
44
+ // We know all required fields are present from validation.
45
+ validated.push(candidate[i]);
46
+ }
47
+ else {
48
+ for (const err of r.errors) {
49
+ allErrors.push({ index: i, field: err.field, message: err.message });
50
+ }
51
+ }
52
+ for (const warn of r.warnings) {
53
+ allWarnings.push({ index: i, message: warn });
54
+ }
55
+ }
56
+ if (allErrors.length > 0) {
57
+ return reply.code(400).send({
58
+ error: "invalid mount set",
59
+ code: "invalid",
60
+ errors: allErrors,
61
+ warnings: allWarnings,
62
+ });
63
+ }
64
+ // Persist into panel.json; live-update the FilesManager so changes
65
+ // take effect without restart.
66
+ const cfg = getPanelConfig();
67
+ cfg.external_mounts = validated;
68
+ savePanelConfig(cfg);
69
+ deps.filesManager.setExternalMounts(validated);
70
+ reply.send({ mounts: validated, warnings: allWarnings });
71
+ });
72
+ }
73
+ //# sourceMappingURL=external-mounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-mounts.js","sourceRoot":"","sources":["../../src/routes/external-mounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * /api/instances/:id/file-mounts routes (M1 W2 PR-5).
3
+ *
4
+ * GET → current mount list (echoes runtime.fileMounts).
5
+ * PUT → full replacement; runs validateMounts first, then writes the
6
+ * runtime field, calls rebuildWorkspace immediately so symlinks
7
+ * are fresh, and reports requires_restart so the UI can prompt
8
+ * the user to restart the container (volume binds in docker mode
9
+ * are part of the running task spec — they do not pick up
10
+ * changes without a restart).
11
+ */
12
+ import type { FastifyInstance } from "fastify";
13
+ export declare function fileMountsRoutes(app: FastifyInstance): Promise<void>;
@@ -0,0 +1,90 @@
1
+ import { getInstance, getInstanceRuntime, getOpenclawHome, } from "../services/instance-manager.js";
2
+ import { validateMounts, ensureMountTargets, } from "../services/files-mounts.js";
3
+ import { rebuildWorkspace } from "../services/workspace-builder.js";
4
+ import { FILES_ROOT, INSTANCES_DIR } from "../config.js";
5
+ import { safeWriteJson } from "../utils/safe-json.js";
6
+ import { join } from "node:path";
7
+ export async function fileMountsRoutes(app) {
8
+ // ── GET /api/instances/:id/file-mounts ──────────
9
+ app.get("/api/instances/:id/file-mounts", async (req, reply) => {
10
+ const meta = getInstance(req.params.id);
11
+ if (!meta) {
12
+ return reply.code(404).send({ error: "instance not found", code: "not-found" });
13
+ }
14
+ const runtime = getInstanceRuntime(req.params.id);
15
+ const mounts = Array.isArray(runtime.fileMounts)
16
+ ? runtime.fileMounts
17
+ : Array.isArray(runtime.file_mounts)
18
+ ? runtime.file_mounts
19
+ : [];
20
+ reply.send({ mounts });
21
+ });
22
+ // ── PUT /api/instances/:id/file-mounts ──────────
23
+ app.put("/api/instances/:id/file-mounts", async (req, reply) => {
24
+ const id = req.params.id;
25
+ const meta = getInstance(id);
26
+ if (!meta) {
27
+ return reply.code(404).send({ error: "instance not found", code: "not-found" });
28
+ }
29
+ const candidate = Array.isArray(req.body?.mounts) ? req.body.mounts : null;
30
+ if (!candidate) {
31
+ return reply.code(400).send({
32
+ error: "body.mounts must be an array",
33
+ code: "invalid",
34
+ });
35
+ }
36
+ const v = validateMounts(candidate, id);
37
+ if (!v.ok) {
38
+ return reply.code(400).send({
39
+ error: "invalid mount set",
40
+ code: "invalid",
41
+ errors: v.errors.map((e) => ({
42
+ mount_index: e.mountIndex,
43
+ message: e.message,
44
+ })),
45
+ });
46
+ }
47
+ // Persist into instance.json (full runtime block; safeWriteJson does
48
+ // an atomic write).
49
+ const newRuntime = { ...meta.runtime, fileMounts: candidate };
50
+ // Drop any stale snake_case from earlier writes
51
+ delete newRuntime.file_mounts;
52
+ const newMeta = { ...meta, runtime: newRuntime };
53
+ const metaPath = join(INSTANCES_DIR, id, "instance.json");
54
+ safeWriteJson(metaPath, newMeta);
55
+ // Mounts targets must exist on host before docker tries to bind
56
+ ensureMountTargets(FILES_ROOT, candidate);
57
+ // Lay down workspace symlinks immediately so raw_exec / process
58
+ // mode picks up changes without a restart. Docker still needs a
59
+ // restart for the volume binds, signalled via requires_restart.
60
+ try {
61
+ const home = getOpenclawHome(id);
62
+ if (home) {
63
+ rebuildWorkspace({
64
+ openclawHome: home,
65
+ filesRoot: FILES_ROOT,
66
+ mounts: candidate,
67
+ instanceId: id,
68
+ });
69
+ }
70
+ }
71
+ catch (e) {
72
+ if (e?.reason === "needs-migration") {
73
+ return reply.code(409).send({
74
+ error: "instance workspace contains pre-W2 user data; run legacy migration first",
75
+ code: "needs-migration",
76
+ detail: e.message,
77
+ });
78
+ }
79
+ return reply.code(500).send({
80
+ error: e?.message ?? "workspace rebuild failed",
81
+ code: "rebuild-failed",
82
+ });
83
+ }
84
+ reply.send({
85
+ mounts: candidate,
86
+ requires_restart: true,
87
+ });
88
+ });
89
+ }
90
+ //# sourceMappingURL=file-mounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-mounts.js","sourceRoot":"","sources":["../../src/routes/file-mounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * /api/files/organize/* routes (W1.5 PR-4).
3
+ *
4
+ * Mounted alongside /api/files via the same Fastify scope so they
5
+ * share path-safety, octet-stream parser etc. Auth piggybacks on the
6
+ * global onRequest hook in server.ts.
7
+ *
8
+ * Endpoints:
9
+ * POST /api/files/organize/scan run rules and return batch
10
+ * GET /api/files/organize/batches list recent batches
11
+ * GET /api/files/organize/batches/:id fetch one
12
+ * PUT /api/files/organize/batches/:id/apply apply (selectedIds in body)
13
+ * POST /api/files/organize/batches/:id/revert revert within undo window
14
+ * DELETE /api/files/organize/batches/:id mark expired (cancel)
15
+ * GET /api/files/organize/rules current rule file content
16
+ * PUT /api/files/organize/rules replace rule file
17
+ */
18
+ import type { FastifyInstance } from "fastify";
19
+ import { FilesManager } from "../services/files-manager.js";
20
+ import { BatchStore } from "../services/organize/store.js";
21
+ export interface OrganizeRoutesDeps {
22
+ filesManager: FilesManager;
23
+ /** Defaults to a store rooted at JISHUSHELL_HOME. */
24
+ store?: BatchStore;
25
+ /** Override files root in tests. Defaults to FILES_ROOT. */
26
+ filesRoot?: string;
27
+ }
28
+ export declare function organizeRoutes(app: FastifyInstance, deps: OrganizeRoutesDeps): Promise<void>;
@@ -0,0 +1,167 @@
1
+ import { FilesError } from "../services/files-manager.js";
2
+ import { readRules, writeRules, validateRules, } from "../services/organize/rules.js";
3
+ import { scan } from "../services/organize/scanner.js";
4
+ import { applyBatch, revertBatch } from "../services/organize/applier.js";
5
+ import { BatchStore } from "../services/organize/store.js";
6
+ import { FILES_ROOT, JISHUSHELL_HOME } from "../config.js";
7
+ export async function organizeRoutes(app, deps) {
8
+ const filesRoot = deps.filesRoot ?? FILES_ROOT;
9
+ const store = deps.store ?? new BatchStore(JISHUSHELL_HOME);
10
+ const audit = (op, p, meta) => {
11
+ deps.filesManager.audit(op, p, meta);
12
+ };
13
+ // W2 PR-3: /api/files/organize/* organize batches are also panel-internal
14
+ // substrate for the drive_* MCP shim only. Browser users now manage files
15
+ // via the Filebrowser app mounted at /apps/filebrowser/*. Reject any
16
+ // request that didn't pass the X-Jishushell-Internal-Token check in
17
+ // server.ts auth middleware. Return 404 rather than 401 so unauthenticated
18
+ // probes can't fingerprint the surface.
19
+ app.addHook("onRequest", async (request, reply) => {
20
+ if (!request.internalCallerInstance) {
21
+ return reply.status(404).send();
22
+ }
23
+ });
24
+ // ── POST /api/files/organize/scan ───────────────
25
+ app.post("/api/files/organize/scan", async (req, reply) => {
26
+ const path = typeof req.body?.path === "string" ? req.body.path : "";
27
+ try {
28
+ const { rules } = await readRules(filesRoot);
29
+ const batch = await scan(filesRoot, rules, path);
30
+ await store.put(batch);
31
+ reply.send(batch);
32
+ }
33
+ catch (e) {
34
+ sendOrganizeError(reply, e);
35
+ }
36
+ });
37
+ // ── GET /api/files/organize/batches ─────────────
38
+ app.get("/api/files/organize/batches", async (_req, reply) => {
39
+ reply.send({ batches: store.list() });
40
+ });
41
+ // ── GET /api/files/organize/batches/:id ─────────
42
+ app.get("/api/files/organize/batches/:id", async (req, reply) => {
43
+ const b = store.get(req.params.id);
44
+ if (!b)
45
+ return reply.code(404).send({ error: "batch not found", code: "not-found" });
46
+ reply.send(b);
47
+ });
48
+ // ── PUT /api/files/organize/batches/:id/apply ───
49
+ app.put("/api/files/organize/batches/:id/apply", async (req, reply) => {
50
+ const batch = store.get(req.params.id);
51
+ if (!batch) {
52
+ return reply.code(404).send({ error: "batch not found", code: "not-found" });
53
+ }
54
+ if (batch.status !== "pending") {
55
+ return reply.code(409).send({
56
+ error: `batch is ${batch.status}, not pending`,
57
+ code: "bad-state",
58
+ });
59
+ }
60
+ const selectedIds = new Set(req.body?.selected_ids ?? []);
61
+ // Re-read rules to get on_collision settings — and detect if rules
62
+ // changed since scan (rules_hash mismatch).
63
+ const { rules, hash } = await readRules(filesRoot);
64
+ if (hash !== batch.rules_hash) {
65
+ return reply.code(409).send({
66
+ error: "rules changed since scan, please re-scan",
67
+ code: "rules-changed",
68
+ });
69
+ }
70
+ const rulesById = new Map();
71
+ for (const r of rules)
72
+ rulesById.set(r.id, r);
73
+ try {
74
+ const { report } = await applyBatch(batch, {
75
+ filesRoot,
76
+ rulesById,
77
+ selectedIds,
78
+ audit,
79
+ });
80
+ await store.put(batch);
81
+ reply.send({ batch, report });
82
+ }
83
+ catch (e) {
84
+ sendOrganizeError(reply, e);
85
+ }
86
+ });
87
+ // ── POST /api/files/organize/batches/:id/revert ─
88
+ app.post("/api/files/organize/batches/:id/revert", async (req, reply) => {
89
+ const batch = store.get(req.params.id);
90
+ if (!batch) {
91
+ return reply.code(404).send({ error: "batch not found", code: "not-found" });
92
+ }
93
+ if (batch.status !== "applied") {
94
+ return reply.code(409).send({
95
+ error: `batch is ${batch.status}, not applied`,
96
+ code: "bad-state",
97
+ });
98
+ }
99
+ try {
100
+ const { report } = await revertBatch(batch, { filesRoot, audit });
101
+ await store.put(batch);
102
+ reply.send({ batch, report });
103
+ }
104
+ catch (e) {
105
+ if (e?.code === "expired") {
106
+ await store.put(batch);
107
+ return reply.code(410).send({
108
+ error: "undo window has expired",
109
+ code: "expired",
110
+ });
111
+ }
112
+ sendOrganizeError(reply, e);
113
+ }
114
+ });
115
+ // ── DELETE /api/files/organize/batches/:id ──────
116
+ app.delete("/api/files/organize/batches/:id", async (req, reply) => {
117
+ const batch = store.get(req.params.id);
118
+ if (!batch)
119
+ return reply.code(204).send();
120
+ await store.update(req.params.id, (b) => {
121
+ if (b.status === "pending")
122
+ b.status = "expired";
123
+ });
124
+ reply.code(204).send();
125
+ });
126
+ // ── GET /api/files/organize/rules ───────────────
127
+ app.get("/api/files/organize/rules", async (_req, reply) => {
128
+ try {
129
+ const { rules, source, hash } = await readRules(filesRoot);
130
+ reply.send({ rules, source, hash });
131
+ }
132
+ catch (e) {
133
+ sendOrganizeError(reply, e);
134
+ }
135
+ });
136
+ // ── PUT /api/files/organize/rules ───────────────
137
+ app.put("/api/files/organize/rules", async (req, reply) => {
138
+ const result = validateRules({
139
+ version: 1,
140
+ rules: req.body?.rules ?? [],
141
+ });
142
+ if (!result.ok) {
143
+ return reply.code(400).send({
144
+ error: "invalid rules",
145
+ code: "invalid",
146
+ errors: result.errors,
147
+ });
148
+ }
149
+ try {
150
+ await writeRules(filesRoot, result.valid_rules);
151
+ reply.send({ rules: result.valid_rules });
152
+ }
153
+ catch (e) {
154
+ sendOrganizeError(reply, e);
155
+ }
156
+ });
157
+ }
158
+ function sendOrganizeError(reply, e) {
159
+ if (e instanceof FilesError) {
160
+ reply.code(e.httpStatus).send({ error: e.message, code: e.code });
161
+ return;
162
+ }
163
+ const err = e;
164
+ console.error("[organize] unexpected:", err.message);
165
+ reply.code(500).send({ error: err.message ?? "internal error", code: err.code ?? "internal" });
166
+ }
167
+ //# sourceMappingURL=files-organize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files-organize.js","sourceRoot":"","sources":["../../src/routes/files-organize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * /api/files routes (M1 W1 PR-4).
3
+ *
4
+ * Mounted as a Fastify plugin so that the route-scoped octet-stream parser
5
+ * does not leak globally. The parser transparently passes the raw payload
6
+ * stream to handlers (no buffering), letting `FilesManager.writeStream`
7
+ * pipe straight to disk.
8
+ *
9
+ * Endpoints:
10
+ * GET /api/files list directory
11
+ * GET /api/files/raw stream file content
12
+ * GET /api/files/preview small text/image read (truncated)
13
+ * GET /api/files/quota quota info
14
+ * PUT /api/files upload (octet-stream only)
15
+ * POST /api/files/mkdir create directory
16
+ * POST /api/files/move rename / move
17
+ * DELETE /api/files soft-delete to .trash/
18
+ * GET /api/files/search full-text search index
19
+ * GET /api/files/meta read per-file sidecar metadata
20
+ * PUT /api/files/meta write/merge per-file sidecar metadata
21
+ * POST /api/files/reindex rebuild search index
22
+ * GET /api/files/resolve relative path → absolute host path
23
+ *
24
+ * Auth: covered by the global onRequest hook in server.ts.
25
+ */
26
+ import type { FastifyInstance } from "fastify";
27
+ import { FilesManager } from "../services/files-manager.js";
28
+ export interface FilesRoutesDeps {
29
+ filesManager: FilesManager;
30
+ }
31
+ export declare function filesRoutes(app: FastifyInstance, deps: FilesRoutesDeps): Promise<void>;