ework-web 0.10.107 → 0.10.109
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/package.json +1 -1
- package/src/index.ts +10 -2
- package/src/render/layout.ts +4 -1
- package/src/views/issueList.ts +3 -1
- package/src/views/issueThread.ts +2 -1
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -402,7 +402,7 @@ const REPO_AI_RE = /^\/([^/]+)\/([^/]+)\/settings\/ai$/;
|
|
|
402
402
|
const REPO_LABELS_RE = /^\/([^/]+)\/([^/]+)\/settings\/labels$/;
|
|
403
403
|
const REPO_LABEL_ADD_RE = /^\/([^/]+)\/([^/]+)\/settings\/labels\/add$/;
|
|
404
404
|
const REPO_LABEL_ACTION_RE = /^\/([^/]+)\/([^/]+)\/settings\/labels\/(\d+)\/(update|archive|unarchive|delete)$/;
|
|
405
|
-
const REPO_ISSUE_HALT_RE = /^\/([^/]+)\/([^/]+)\/issues\/(\d+)\/(halt|resume|dispatch-off|dispatch-on)$/;
|
|
405
|
+
const REPO_ISSUE_HALT_RE = /^\/([^/]+)\/([^/]+)\/issues\/(\d+)\/(halt|resume|dispatch-off|dispatch-on|reset-session)$/;
|
|
406
406
|
const REPO_ISSUE_MODEL_RE = /^\/([^/]+)\/([^/]+)\/issues\/(\d+)\/model$/;
|
|
407
407
|
const REPO_ISSUE_RUNTIME_RE = /^\/([^/]+)\/([^/]+)\/issues\/(\d+)\/runtime$/;
|
|
408
408
|
const REPO_ISSUE_STATUS_RE = /^\/([^/]+)\/([^/]+)\/issues\/(\d+)\/ai-status$/;
|
|
@@ -611,7 +611,8 @@ async function handle(req: Request, url: URL, ip: string, ctx: { authed: boolean
|
|
|
611
611
|
const projectOff = cfgKv[`dispatchOff:${owner}/${repo}`] === "1";
|
|
612
612
|
const aiStatus = issue?.ai_status ?? "";
|
|
613
613
|
const issueOff = aiStatus === "dispatch_off" || aiStatus === "halted";
|
|
614
|
-
|
|
614
|
+
const sessionResetMs = Number(cfgKv[`sessionReset:${owner}/${repo}#${number}`]) || null;
|
|
615
|
+
return json({ dispatchOff: globalOff || projectOff || issueOff, aiStatus, sessionResetMs });
|
|
615
616
|
}
|
|
616
617
|
if (url.pathname === "/api/v1/wake-logins" && req.method === "GET") {
|
|
617
618
|
const owner = url.searchParams.get("owner") ?? "";
|
|
@@ -1911,6 +1912,13 @@ async function handle(req: Request, url: URL, ip: string, ctx: { authed: boolean
|
|
|
1911
1912
|
const issue = await getIssueWithMeta(project.id, number);
|
|
1912
1913
|
if (!issue) return json({ error: "issue not found" }, 404);
|
|
1913
1914
|
const statusMap: Record<string, string> = { halt: "halted", resume: "", "dispatch-off": "dispatch_off", "dispatch-on": "" };
|
|
1915
|
+
if (action === "reset-session") {
|
|
1916
|
+
if (!(await canAdminProject(project.id, ctx.user))) {
|
|
1917
|
+
return json({ error: "admin role required" }, 403);
|
|
1918
|
+
}
|
|
1919
|
+
await setConfig(`sessionReset:${owner}/${repo}#${number}`, String(Date.now()));
|
|
1920
|
+
return json({ ok: true, reset: true });
|
|
1921
|
+
}
|
|
1914
1922
|
const newStatus = statusMap[action] ?? "";
|
|
1915
1923
|
const oldStatus = issue.ai_status ?? "";
|
|
1916
1924
|
await updateIssueAiStatus(issue.id, newStatus);
|
package/src/render/layout.ts
CHANGED
|
@@ -214,6 +214,9 @@ export function renderLayout(props: LayoutProps, inner: string, initialItems: st
|
|
|
214
214
|
? `<button type="button" class="action-btn dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/dispatch-on" title="允许自动接单">🔔 恢复接单</button>`
|
|
215
215
|
: `<button type="button" class="action-btn dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/dispatch-off" data-action-confirm="设为不自动接单?" title="关闭此 issue 的自动接单">🔕 暂停接单</button>`
|
|
216
216
|
: "";
|
|
217
|
+
const resetBtnHtml = showActions
|
|
218
|
+
? `<button type="button" class="action-btn dispatch-btn" data-action-href="${escapeAttr(repoIssuesHref)}/${props.issueNumber}/reset-session" data-action-confirm="重置 AI 会话?下次触发将从全新会话开始(历史评论保留)" title="重置 AI 会话(下次触发开新会话)">🔄 重置会话</button>`
|
|
219
|
+
: "";
|
|
217
220
|
const runtimeSelectHtml = props.runtimeSelect && showActions
|
|
218
221
|
? `<span class="model-select-wrap"><select class="model-select" id="issueRuntimeSelect" title="此 issue 的运行时(新会话生效)">
|
|
219
222
|
<option value="" ${props.runtimeSelect.current === "" ? "selected" : ""}>默认运行时</option>
|
|
@@ -251,7 +254,7 @@ export function renderLayout(props: LayoutProps, inner: string, initialItems: st
|
|
|
251
254
|
<div class="meta-status">
|
|
252
255
|
<span class="state-badge ${stateClass}">${stateLabel}</span>
|
|
253
256
|
${aiBadgeHtml}
|
|
254
|
-
${(haltBtnHtml || dispatchBtnHtml || (props.customActions ?? []).length) ? `<span class="action-group">${haltBtnHtml}${dispatchBtnHtml}${runtimeSelectHtml}${modelSelectHtml}${(props.customActions ?? []).map((a) => {
|
|
257
|
+
${(haltBtnHtml || dispatchBtnHtml || (props.customActions ?? []).length) ? `<span class="action-group">${haltBtnHtml}${dispatchBtnHtml}${resetBtnHtml}${runtimeSelectHtml}${modelSelectHtml}${(props.customActions ?? []).map((a) => {
|
|
255
258
|
const attrs = [`data-action-href="${escapeAttr(a.href)}"`];
|
|
256
259
|
if (a.method && a.method !== "POST") attrs.push(`data-action-method="${escapeAttr(a.method)}"`);
|
|
257
260
|
if (a.confirm) attrs.push(`data-action-confirm="${escapeAttr(a.confirm)}"`);
|
package/src/views/issueList.ts
CHANGED
|
@@ -25,9 +25,11 @@ function issueRow(
|
|
|
25
25
|
: "";
|
|
26
26
|
const aiBadge = aiStatusBadge(it.ai_status);
|
|
27
27
|
const modelChip = it.model ? ` · <span class="row-model" title="模型">${escapeHtml(it.model)}</span>` : "";
|
|
28
|
+
// Synced issues carry their upstream (GitHub) author; local ones the poster.
|
|
29
|
+
const authorChip = it.author ? ` · <span class="row-author" title="创建者">👤 ${escapeHtml(it.author)}</span>` : "";
|
|
28
30
|
return `<a class="row" href="${escapeAttr(href)}">
|
|
29
31
|
<div class="row-title">${title}${chips}</div>
|
|
30
|
-
<div class="row-meta">#${it.number} · 💬 ${it.comment_count} · ${relTime(it.updated_at)}${aiBadge ? ` · ${aiBadge}` : ""}${modelChip}</div>
|
|
32
|
+
<div class="row-meta">#${it.number}${authorChip} · 💬 ${it.comment_count} · ${relTime(it.updated_at)}${aiBadge ? ` · ${aiBadge}` : ""}${modelChip}</div>
|
|
31
33
|
</a>`;
|
|
32
34
|
}
|
|
33
35
|
|
package/src/views/issueThread.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Config } from "../config";
|
|
2
|
-
import { classifyActor, renderCommentCard, type CommentView } from "../render/components";
|
|
2
|
+
import { classifyActor, renderCommentCard, relTime, type CommentView } from "../render/components";
|
|
3
3
|
import { renderMarkdown } from "../render/markdown";
|
|
4
4
|
import { renderLayout, escapeHtml, escapeAttr } from "../render/layout";
|
|
5
5
|
import { runIssueActionsHook, type IssueActionContext, type IssueAction } from "../issue-actions-hook";
|
|
@@ -164,6 +164,7 @@ export async function buildIssueThread(
|
|
|
164
164
|
!wakeList.some((l) => l.toLowerCase() === lowerAuthor);
|
|
165
165
|
const authorLineHtml =
|
|
166
166
|
`<div class="author-line">由 <strong>${escapeHtml(issue.author)}</strong> 提交` +
|
|
167
|
+
` <span class="when" data-ts="${escapeAttr(issue.created_at)}" title="${escapeAttr(issue.created_at)}">${relTime(issue.created_at)}</span>` +
|
|
167
168
|
(authorKind === "bot" ? ` <span class="kind-tag">bot</span>` : "") +
|
|
168
169
|
(showAuthorWhitelist
|
|
169
170
|
? `<form method="post" action="/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/settings/ai/wake-logins" class="wl-form">` +
|