mirror of
https://github.com/theniceboy/.config.git
synced 2026-07-16 22:01:21 +08:00
remove work summary integration
This commit is contained in:
parent
b4a7d0ae86
commit
e83f196acf
3 changed files with 2 additions and 250 deletions
|
|
@ -14,17 +14,6 @@
|
||||||
- Keep explanations compact unless the user asks for more detail.
|
- Keep explanations compact unless the user asks for more detail.
|
||||||
- For security warnings, destructive actions, or anything where brevity could cause confusion, switch to clear normal wording first.
|
- For security warnings, destructive actions, or anything where brevity could cause confusion, switch to clear normal wording first.
|
||||||
|
|
||||||
## Work Summary
|
|
||||||
|
|
||||||
- Keep `set_work_summary` up to date before you start work
|
|
||||||
- `theme`: what has the work been about overall?
|
|
||||||
- `now` answers: what the user asked you to do and/or what are you about to do?
|
|
||||||
- Keep both labels concrete and under 40 characters.
|
|
||||||
- Since the summary line has dedicated space, prefer richer phrases that help a forgetful human re-orient instantly.
|
|
||||||
- Keep phrasing simple
|
|
||||||
|
|
||||||
---------
|
|
||||||
|
|
||||||
## Adaptive Burst Workflow
|
## Adaptive Burst Workflow
|
||||||
|
|
||||||
### How to Burst
|
### How to Burst
|
||||||
|
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
||||||
import { tool } from "@opencode-ai/plugin"
|
|
||||||
|
|
||||||
const MAX_THEME_CHARS = 48
|
|
||||||
const MAX_NOW_CHARS = 48
|
|
||||||
const TMUX_THEME_OPTION = "@op_work_theme"
|
|
||||||
const TMUX_NOW_OPTION = "@op_work_now"
|
|
||||||
const TMUX_LEGACY_OPTION = "@op_work_summary"
|
|
||||||
const TRACKER_BIN = `${process.env.HOME || ""}/.config/agent-tracker/bin/agent`
|
|
||||||
const GENERIC_LABELS = new Set([
|
|
||||||
"working",
|
|
||||||
"coding",
|
|
||||||
"debugging",
|
|
||||||
"researching",
|
|
||||||
"thinking",
|
|
||||||
"fixing",
|
|
||||||
"checking",
|
|
||||||
"investigating",
|
|
||||||
"task",
|
|
||||||
"stuff",
|
|
||||||
"project",
|
|
||||||
"feature",
|
|
||||||
"issue",
|
|
||||||
"bug",
|
|
||||||
])
|
|
||||||
|
|
||||||
function capitalizeFirstLetter(value: string): string {
|
|
||||||
return value.replace(/[A-Za-z]/, (letter) => letter.toUpperCase())
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeLabel(value: string, maxChars: number): string {
|
|
||||||
const collapsed = value
|
|
||||||
.replace(/\s+/g, " ")
|
|
||||||
.replace(/[.!,;:]+$/g, "")
|
|
||||||
.trim()
|
|
||||||
if (collapsed.length <= maxChars) {
|
|
||||||
return capitalizeFirstLetter(collapsed)
|
|
||||||
}
|
|
||||||
|
|
||||||
const words = collapsed.split(" ")
|
|
||||||
let clipped = ""
|
|
||||||
for (const word of words) {
|
|
||||||
const next = clipped ? `${clipped} ${word}` : word
|
|
||||||
if (next.length > maxChars) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
clipped = next
|
|
||||||
}
|
|
||||||
if (clipped) {
|
|
||||||
return capitalizeFirstLetter(clipped)
|
|
||||||
}
|
|
||||||
|
|
||||||
return capitalizeFirstLetter(collapsed.slice(0, maxChars).trim())
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureSpecific(label: string, field: string): string {
|
|
||||||
if (!label) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GENERIC_LABELS.has(label.toLowerCase())) {
|
|
||||||
throw new Error(
|
|
||||||
`Use a more specific ${field}. Good examples: \"Tmux status summaries\", \"Patch work-context layout\", \"Wait for user reply\".`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return label
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runTmux(tmuxBin: string, args: string[]) {
|
|
||||||
const proc = Bun.spawn([tmuxBin, ...args], {
|
|
||||||
stdin: "ignore",
|
|
||||||
stdout: "pipe",
|
|
||||||
stderr: "pipe",
|
|
||||||
})
|
|
||||||
const [stdout, stderr, exitCode] = await Promise.all([
|
|
||||||
new Response(proc.stdout).text(),
|
|
||||||
new Response(proc.stderr).text(),
|
|
||||||
proc.exited,
|
|
||||||
])
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
const message = stderr.trim() || stdout.trim() || `tmux exited ${exitCode}`
|
|
||||||
throw new Error(message)
|
|
||||||
}
|
|
||||||
return stdout.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readTmuxOption(tmuxBin: string, tmuxPane: string, option: string) {
|
|
||||||
return runTmux(tmuxBin, ["display-message", "-p", "-t", tmuxPane, `#{${option}}`]).catch(() => "")
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeTmuxOption(tmuxBin: string, tmuxPane: string, option: string, value: string) {
|
|
||||||
if (!value) {
|
|
||||||
await runTmux(tmuxBin, ["set-option", "-p", "-u", "-t", tmuxPane, option])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await runTmux(tmuxBin, ["set-option", "-p", "-t", tmuxPane, option, value])
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runCommand(args: string[]) {
|
|
||||||
const proc = Bun.spawn(args, {
|
|
||||||
stdin: "ignore",
|
|
||||||
stdout: "ignore",
|
|
||||||
stderr: "pipe",
|
|
||||||
})
|
|
||||||
const [stderr, exitCode] = await Promise.all([
|
|
||||||
new Response(proc.stderr).text(),
|
|
||||||
proc.exited,
|
|
||||||
])
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
throw new Error(stderr.trim() || `${args[0]} exited ${exitCode}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function trackerSummary(theme: string, now: string) {
|
|
||||||
if (theme && now) {
|
|
||||||
return `${theme} -> ${now}`
|
|
||||||
}
|
|
||||||
return theme || now
|
|
||||||
}
|
|
||||||
|
|
||||||
export default tool({
|
|
||||||
description:
|
|
||||||
"Set the tmux pane's stable theme and immediate current-step labels for the current OpenCode session.",
|
|
||||||
args: {
|
|
||||||
theme: tool.schema
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.describe(
|
|
||||||
"Stable grand objective. Answer: what is this pane about overall? Keep it specific and under 48 characters. Prefer richer phrases like 'Tmux status summaries' or 'Agent tracker integration'.",
|
|
||||||
),
|
|
||||||
now: tool.schema
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.describe(
|
|
||||||
"Immediate next step. Answer: what are you about to do next? Keep it specific and under 48 characters. Use next-action phrasing like 'Read restore code', 'Patch status layout', or 'Wait for user reply'.",
|
|
||||||
),
|
|
||||||
summary: tool.schema
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.describe("Legacy alias for theme. Prefer using theme plus now."),
|
|
||||||
},
|
|
||||||
async execute(args) {
|
|
||||||
const tmuxPane = (process.env.TMUX_PANE || "").trim()
|
|
||||||
const tmuxBin = Bun.which("tmux") || "/opt/homebrew/bin/tmux"
|
|
||||||
const hasTheme = typeof args.theme === "string"
|
|
||||||
const hasNow = typeof args.now === "string"
|
|
||||||
const hasSummary = typeof args.summary === "string"
|
|
||||||
|
|
||||||
if (!hasTheme && !hasNow && !hasSummary) {
|
|
||||||
throw new Error("Provide at least one of: theme, now, or summary.")
|
|
||||||
}
|
|
||||||
|
|
||||||
let theme = hasTheme
|
|
||||||
? ensureSpecific(normalizeLabel(args.theme || "", MAX_THEME_CHARS), "theme")
|
|
||||||
: ""
|
|
||||||
const now = hasNow
|
|
||||||
? ensureSpecific(normalizeLabel(args.now || "", MAX_NOW_CHARS), "current-step label")
|
|
||||||
: ""
|
|
||||||
|
|
||||||
if (!hasTheme && hasSummary) {
|
|
||||||
theme = ensureSpecific(normalizeLabel(args.summary || "", MAX_THEME_CHARS), "theme")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tmuxPane) {
|
|
||||||
return JSON.stringify({ theme, now })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasTheme && !hasSummary) {
|
|
||||||
theme =
|
|
||||||
(await readTmuxOption(tmuxBin, tmuxPane, TMUX_THEME_OPTION)) ||
|
|
||||||
(await readTmuxOption(tmuxBin, tmuxPane, TMUX_LEGACY_OPTION))
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalNow = hasNow ? now : await readTmuxOption(tmuxBin, tmuxPane, TMUX_NOW_OPTION)
|
|
||||||
const finalTheme = theme
|
|
||||||
|
|
||||||
if (hasTheme || hasSummary) {
|
|
||||||
await writeTmuxOption(tmuxBin, tmuxPane, TMUX_THEME_OPTION, theme)
|
|
||||||
await writeTmuxOption(tmuxBin, tmuxPane, TMUX_LEGACY_OPTION, theme)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasNow) {
|
|
||||||
await writeTmuxOption(tmuxBin, tmuxPane, TMUX_NOW_OPTION, now)
|
|
||||||
}
|
|
||||||
|
|
||||||
const trackerText = trackerSummary(finalTheme, finalNow)
|
|
||||||
if (trackerText && (await Bun.file(TRACKER_BIN).exists())) {
|
|
||||||
await runCommand([TRACKER_BIN, "tracker", "command", "-pane", tmuxPane, "-summary", trackerText, "update_task"]).catch(() => {})
|
|
||||||
}
|
|
||||||
|
|
||||||
await runTmux(tmuxBin, ["refresh-client", "-S"])
|
|
||||||
return JSON.stringify({ theme: finalTheme, now: finalNow })
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
@ -63,9 +63,6 @@ load_option() {
|
||||||
|
|
||||||
clear_opencode_state() {
|
clear_opencode_state() {
|
||||||
[[ -n "$pane_id" ]] || return 0
|
[[ -n "$pane_id" ]] || return 0
|
||||||
tmux set-option -p -u -t "$pane_id" @op_work_theme 2>/dev/null || true
|
|
||||||
tmux set-option -p -u -t "$pane_id" @op_work_now 2>/dev/null || true
|
|
||||||
tmux set-option -p -u -t "$pane_id" @op_work_summary 2>/dev/null || true
|
|
||||||
tmux set-option -p -u -t "$pane_id" @op_question_pending 2>/dev/null || true
|
tmux set-option -p -u -t "$pane_id" @op_question_pending 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,11 +95,6 @@ else
|
||||||
title=$(fallback)
|
title=$(fallback)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
theme=$(load_option "@op_work_theme")
|
|
||||||
if [[ -z "$theme" ]]; then
|
|
||||||
theme=$(load_option "@op_work_summary")
|
|
||||||
fi
|
|
||||||
now=$(load_option "@op_work_now")
|
|
||||||
question_pending=$(load_option "@op_question_pending")
|
question_pending=$(load_option "@op_question_pending")
|
||||||
pane_watching=$(load_option "@pane_watching")
|
pane_watching=$(load_option "@pane_watching")
|
||||||
|
|
||||||
|
|
@ -111,45 +103,11 @@ if [[ "$pane_watching" == "1" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! opencode_active; then
|
if ! opencode_active; then
|
||||||
if [[ -n "$theme" || -n "$now" || -n "$question_pending" ]]; then
|
if [[ -n "$question_pending" ]]; then
|
||||||
clear_opencode_state
|
clear_opencode_state
|
||||||
fi
|
fi
|
||||||
printf '%s' "$title"
|
printf '%s' "$title"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
summary_display=""
|
printf '%s' "$title"
|
||||||
if [[ -n "$theme" ]]; then
|
|
||||||
summary_display="[$theme]"
|
|
||||||
fi
|
|
||||||
if [[ -n "$now" ]]; then
|
|
||||||
if [[ -n "$summary_display" ]]; then
|
|
||||||
summary_display="$summary_display ↳ $now"
|
|
||||||
else
|
|
||||||
summary_display="↳ $now"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$summary_display" ]]; then
|
|
||||||
printf '%s' "$title"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$pane_watching" == "1" ]]; then
|
|
||||||
summary_display="⏳ $summary_display"
|
|
||||||
title=${title#⏳ }
|
|
||||||
fi
|
|
||||||
|
|
||||||
reserved_width=$((${#summary_display} + 3))
|
|
||||||
prompt_width=$((width - reserved_width))
|
|
||||||
if (( prompt_width < 16 )); then
|
|
||||||
summary_display=$(trim_to_width "$summary_display" "$width")
|
|
||||||
printf '%s' "$summary_display"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v starship >/dev/null 2>&1; then
|
|
||||||
title=$(cd "$pane_path" && run_starship "$prompt_width") || title=$(fallback)
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf '%s · %s' "$summary_display" "$title"
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue