@emseepea/feedback 0.4.0 → 0.5.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 CHANGED
@@ -99,6 +99,44 @@ required.
99
99
 
100
100
  ## Choose a Backend
101
101
 
102
+ ### Markdown files (one-way submissions)
103
+
104
+ `createMarkdownFeedbackSubmissionBackend({ directory })` stores each one-way
105
+ submission as a separate Markdown file in a configurable local directory. Pass
106
+ it to `defineFeedbackSubmission`; it does not implement protected conversations
107
+ or a team reply path. No generated application enables this option by default.
108
+
109
+ ```ts
110
+ import { resolve } from "node:path";
111
+ import { createMarkdownFeedbackSubmissionBackend } from "@emseepea/feedback/markdown";
112
+
113
+ const backend = createMarkdownFeedbackSubmissionBackend({
114
+ directory: resolve("docs/feedback"),
115
+ });
116
+ ```
117
+
118
+ The directory must be absolute and on a trusted local filesystem that supports
119
+ directory syncing. Use a dedicated feedback folder, such as `docs/feedback`
120
+ when running locally from the repository root. Scope values become SHA-256
121
+ directory names; generated IDs become filenames. The adapter rejects symlinks
122
+ at the configured and scope directories and creates private scope directories
123
+ and files.
124
+
125
+ When the folder is inside a Git repository, the adapter creates and checks a
126
+ `.gitignore` there before storing feedback. It ignores generated feedback files
127
+ but leaves the `.gitignore` visible to Git. The adapter rejects a general docs
128
+ folder containing other files.
129
+
130
+ The ignore rule does not protect feedback that was already tracked or staged,
131
+ or files added with `git add -f`. Check those separately before sharing the
132
+ repository.
133
+
134
+ A successful call means the file and its directory entry were synced before the
135
+ receipt and event were returned. The adapter does not commit files to Git, send
136
+ notifications, or provide shared storage across instances. Include feedback
137
+ only in backups or exports approved for that content. Treat feedback prose and
138
+ application-declared context as untrusted, even when displayed as Markdown.
139
+
102
140
  ### PostgreSQL
103
141
 
104
142
  Run `migratePostgresFeedback(pool)` once during controlled setup, then use
@@ -0,0 +1,8 @@
1
+ import type { FeedbackSubmissionBackend } from "./index.js";
2
+ export interface MarkdownFeedbackOptions {
3
+ /** Local directory selected by the application. Keep it out of public source control. */
4
+ readonly directory: string;
5
+ }
6
+ /** One-way feedback storage. This adapter does not provide support conversations. */
7
+ export declare function createMarkdownFeedbackSubmissionBackend<Context = undefined>(options: MarkdownFeedbackOptions): FeedbackSubmissionBackend<Context>;
8
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qFAAqF;AACrF,wBAAgB,uCAAuC,CAAC,OAAO,GAAG,SAAS,EACzE,OAAO,EAAE,uBAAuB,GAC/B,yBAAyB,CAAC,OAAO,CAAC,CA6DpC"}
@@ -0,0 +1,159 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import fs from "node:fs/promises";
4
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
5
+ /** One-way feedback storage. This adapter does not provide support conversations. */
6
+ export function createMarkdownFeedbackSubmissionBackend(options) {
7
+ if (!isAbsolute(options.directory))
8
+ throw new Error("Markdown feedback directory must be absolute");
9
+ const root = resolve(options.directory);
10
+ return {
11
+ async submit(command, context) {
12
+ context.signal.throwIfAborted();
13
+ if (Date.now() >= context.deadlineMs)
14
+ throw new DOMException("The feedback deadline expired", "TimeoutError");
15
+ const id = randomUUID();
16
+ const recordedAt = new Date().toISOString();
17
+ const scopeKey = createHash("sha256").update(context.scope).digest("hex");
18
+ const scopeDirectory = join(root, scopeKey);
19
+ const finalPath = join(scopeDirectory, `${id}.md`);
20
+ const temporaryPath = join(scopeDirectory, `.${id}.tmp`);
21
+ const payload = `# Feedback ${id}\n\n- Observation: \`${command.observation}\`\n- Recorded at: \`${recordedAt}\`\n\n## Detail\n\n${fenced(command.detail, "text")}\n\n## Context\n\n${fenced(JSON.stringify(command.context ?? null, null, 2), "json")}\n`;
22
+ const events = [{
23
+ id: `feedback.message.added:${id}`,
24
+ type: "feedback.message.added",
25
+ occurredAt: recordedAt,
26
+ threadId: id,
27
+ messageId: id,
28
+ author: "user",
29
+ }];
30
+ const repository = await findGitRepository(root);
31
+ await fs.mkdir(root, { recursive: true, mode: 0o700 });
32
+ await ensureDirectory(root);
33
+ if (repository)
34
+ await ensureGitIgnore(root, repository);
35
+ await fs.mkdir(scopeDirectory, { mode: 0o700 }).catch((error) => {
36
+ if (error.code !== "EEXIST")
37
+ throw error;
38
+ });
39
+ await ensureDirectory(scopeDirectory);
40
+ context.signal.throwIfAborted();
41
+ if (Date.now() >= context.deadlineMs)
42
+ throw new DOMException("The feedback deadline expired", "TimeoutError");
43
+ let created = false;
44
+ try {
45
+ const file = await fs.open(temporaryPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
46
+ created = true;
47
+ try {
48
+ await file.writeFile(payload, { encoding: "utf8", signal: context.signal });
49
+ await file.sync();
50
+ }
51
+ finally {
52
+ await file.close();
53
+ }
54
+ context.signal.throwIfAborted();
55
+ if (Date.now() >= context.deadlineMs)
56
+ throw new DOMException("The feedback deadline expired", "TimeoutError");
57
+ await fs.rename(temporaryPath, finalPath);
58
+ created = false;
59
+ const directory = await fs.open(scopeDirectory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
60
+ try {
61
+ await directory.sync();
62
+ }
63
+ finally {
64
+ await directory.close();
65
+ }
66
+ }
67
+ finally {
68
+ if (created)
69
+ await fs.unlink(temporaryPath).catch(() => { });
70
+ }
71
+ // Once the directory entry is synced, no validation or cancellation may
72
+ // turn recorded feedback into a failed tool response.
73
+ return { id, recordedAt, events };
74
+ },
75
+ };
76
+ }
77
+ async function ensureDirectory(path) {
78
+ const stat = await fs.lstat(path);
79
+ if (stat.isSymbolicLink())
80
+ throw new Error("Markdown feedback directory cannot be a symlink");
81
+ if (!stat.isDirectory())
82
+ throw new Error("Markdown feedback destination is not a directory");
83
+ }
84
+ const gitIgnoreContent = "/*\n!/.gitignore\n";
85
+ async function findGitRepository(directory) {
86
+ let existing = directory;
87
+ for (;;) {
88
+ try {
89
+ await fs.lstat(existing);
90
+ break;
91
+ }
92
+ catch (error) {
93
+ if (error.code !== "ENOENT")
94
+ throw error;
95
+ const parent = dirname(existing);
96
+ if (parent === existing)
97
+ throw error;
98
+ existing = parent;
99
+ }
100
+ }
101
+ let current = join(await fs.realpath(existing), relative(existing, directory));
102
+ for (;;) {
103
+ try {
104
+ await fs.lstat(join(current, ".git"));
105
+ return current;
106
+ }
107
+ catch (error) {
108
+ if (error.code !== "ENOENT")
109
+ throw error;
110
+ }
111
+ const parent = dirname(current);
112
+ if (parent === current)
113
+ return undefined;
114
+ current = parent;
115
+ }
116
+ }
117
+ async function ensureGitIgnore(directory, repository) {
118
+ const canonical = await fs.realpath(directory);
119
+ if (canonical === repository || basename(canonical) === "docs") {
120
+ throw new Error("Markdown feedback needs a dedicated directory inside Git");
121
+ }
122
+ const entries = await fs.readdir(directory, { withFileTypes: true });
123
+ if (entries.some((entry) => entry.name !== ".gitignore" &&
124
+ (!/^[a-f0-9]{64}$/.test(entry.name) || !entry.isDirectory()))) {
125
+ throw new Error("Markdown feedback needs a dedicated directory inside Git");
126
+ }
127
+ const ignorePath = join(directory, ".gitignore");
128
+ try {
129
+ const file = await fs.open(ignorePath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
130
+ try {
131
+ await file.writeFile(gitIgnoreContent, "utf8");
132
+ await file.sync();
133
+ }
134
+ finally {
135
+ await file.close();
136
+ }
137
+ const parent = await fs.open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
138
+ try {
139
+ await parent.sync();
140
+ }
141
+ finally {
142
+ await parent.close();
143
+ }
144
+ }
145
+ catch (error) {
146
+ if (error.code !== "EEXIST")
147
+ throw error;
148
+ }
149
+ const stat = await fs.lstat(ignorePath);
150
+ if (!stat.isFile() || stat.isSymbolicLink() || await fs.readFile(ignorePath, "utf8") !== gitIgnoreContent) {
151
+ throw new Error("Markdown feedback requires its safe Git ignore rule");
152
+ }
153
+ }
154
+ function fenced(value, language) {
155
+ const longest = Math.max(0, ...[...value.matchAll(/`+/g)].map(([run]) => run.length));
156
+ const fence = "`".repeat(Math.max(3, longest + 1));
157
+ return `${fence}${language}\n${value}\n${fence}`;
158
+ }
159
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emseepea/feedback",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Optional detailed feedback and support conversations for Em See Pea servers",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,6 +20,10 @@
20
20
  "types": "./dist/index.d.ts",
21
21
  "import": "./dist/index.js"
22
22
  },
23
+ "./markdown": {
24
+ "types": "./dist/markdown.d.ts",
25
+ "import": "./dist/markdown.js"
26
+ },
23
27
  "./postgres": {
24
28
  "types": "./dist/postgres.d.ts",
25
29
  "import": "./dist/postgres.js"