fix: POST for file creation (Gitea 1.25+), add edit_issue tool, persist poll state

- files.ts: Use POST for new files, PUT for updates (Gitea 1.25 requires this)
- issues.ts: Add editIssue() for state/title/body changes
- write-tools.ts: Add gitea_edit_issue tool (open/close/edit issues)
- webhook/server.ts: Persist lastPollAt to disk to prevent duplicate
  events on reload; use followUp delivery to queue events during LLM turns
- index.ts: Use deliverAs:'followUp' for sendUserMessage
This commit is contained in:
2026-03-13 17:14:06 -07:00
parent 578e2f91cb
commit b868ad4df5
5 changed files with 105 additions and 9 deletions

View File

@@ -44,12 +44,36 @@ export async function updateFile(
filepath: string,
opts: { content: string; message: string; branch?: string; sha?: string },
): Promise<FileCommitResponse> {
return client.put<FileCommitResponse>(`/repos/${owner}/${repo}/contents/${filepath}`, {
const body = {
content: Buffer.from(opts.content).toString("base64"),
message: opts.message,
branch: opts.branch,
sha: opts.sha,
});
};
if (opts.sha) {
// Explicit SHA → update existing file (PUT)
return client.put<FileCommitResponse>(`/repos/${owner}/${repo}/contents/${filepath}`, {
...body,
sha: opts.sha,
});
}
// No SHA → try POST (create). If 422 "SHA Required", the file already
// exists — fetch its SHA and retry with PUT.
try {
return await client.post<FileCommitResponse>(`/repos/${owner}/${repo}/contents/${filepath}`, body);
} catch (err: any) {
if (err?.status === 422 && /sha/i.test(err?.body ?? "")) {
const existing = await getFileContent(client, owner, repo, filepath, {
ref: opts.branch,
});
return client.put<FileCommitResponse>(`/repos/${owner}/${repo}/contents/${filepath}`, {
...body,
sha: existing.sha,
});
}
throw err;
}
}
/** Delete a file in a repo */

View File

@@ -76,3 +76,14 @@ export async function createIssue(
labels: opts.labels ?? [],
});
}
/** Edit an existing issue (title, body, state) */
export async function editIssue(
client: GiteaClient,
owner: string,
repo: string,
index: number,
opts: { title?: string; body?: string; state?: "open" | "closed" },
): Promise<Issue> {
return client.patch<Issue>(`/repos/${owner}/${repo}/issues/${index}`, opts);
}