From f3f4a30b3ccf75693067952909fe05d7dca5ea7c Mon Sep 17 00:00:00 2001 From: Junjun Zhang Date: Fri, 25 Sep 2026 19:10:28 +0800 Subject: [PATCH] feat(memory): /init generates standard AGENTS.md with exploration-first prompt - DefaultProjectMemoryFilename GGCODE.md -> AGENTS.md; /init and the startup prompt now target AGENTS.md (cross-CLI standard). Loader still reads GGCODE.md/CLAUDE.md/COPILOT.md as before. - /init prompt rewritten: the agent must explore the repository (README, manifests, entrypoints, CI/Makefile, representative sources) and write AGENTS.md from what it actually found; the heuristic snapshot is now a verify-first hint block instead of verbatim content. - Repo's own memory file converted: GGCODE.md -> AGENTS.md (renamed, content unchanged), with a thin GGCODE.md compat stub to avoid duplicate injection. - i18n (11 languages), completion, and related comments updated; enumeration strings listing all four memory filenames untouched. Co-Authored-By: ggcode --- AGENTS.md | 129 +++++++++++++++++++++++++++++++ GGCODE.md | 130 +------------------------------- internal/memory/init.go | 13 ++-- internal/memory/project.go | 2 +- internal/memory/project_test.go | 2 +- internal/tui/commands.go | 29 +++++-- internal/tui/completion.go | 2 +- internal/tui/i18n_command.go | 12 +-- internal/tui/i18n_de.go | 10 +-- internal/tui/i18n_en.go | 10 +-- internal/tui/i18n_es.go | 10 +-- internal/tui/i18n_fr.go | 10 +-- internal/tui/i18n_ja.go | 10 +-- internal/tui/i18n_ko.go | 10 +-- internal/tui/i18n_pt.go | 8 +- internal/tui/i18n_ru.go | 10 +-- internal/tui/i18n_vi.go | 10 +-- internal/tui/i18n_zh.go | 10 +-- internal/tui/model.go | 2 +- internal/tui/model_messages.go | 4 +- internal/tui/update_keys.go | 2 +- 21 files changed, 225 insertions(+), 200 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..1ac2e6a11 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,129 @@ +# ggcode + + +## Quick Reference + +| Item | Value | +|------|-------| +| Module | `github.com/topcheer/ggcode` | +| Go version | 1.26.2 (see `go.mod`) | +| Build tag | **`-tags goolm`** required for ALL `go build` / `go test` | +| Current release | v1.3.188 | +| Platform | Linux / macOS / Windows (amd64 + arm64) | + +## Validation Commands + +```bash +# CI-equivalent check (what pre-commit hook runs) +make verify-ci + +# Quick build +go build -tags goolm -o /tmp/ggcode ./cmd/ggcode + +# Run tests (use memory limits on shared/CI machines) +GOMEMLIMIT=2GiB GOGC=50 go test -tags goolm -p 1 -parallel 1 -timeout 600s ./... + +# Lint +go vet -tags goolm ./... + +# Cross-platform build check +CGO_ENABLED=0 go build -tags goolm ./... +``` + +**Key rule**: Always use `-tags goolm`. Without it, CGO-only packages (e.g. `go-olm`) will fail to compile. + +## Major Directories + +| Path | Purpose | +|------|---------| +| `cmd/ggcode/` | Main CLI entrypoint, root command, resume picker | +| `cmd/ggcode-installer/` | Go-based binary installer | +| `internal/agent/` | Agent loop, tool execution, autopilot strategist, compaction | +| `internal/tui/` | Bubble Tea terminal UI, panels, slash commands, i18n | +| `internal/provider/` | LLM provider adapters (OpenAI, Anthropic, Gemini), retry, error formatting | +| `internal/config/` | Config schema, vendor/endpoint resolution, built-in vendor defaults, i18n display names | +| `internal/session/` | JSONL session store, debounce, index, checkpoints | +| `internal/context/` | Context manager, token counting, compaction | +| `internal/tool/` | Built-in tools (file edit, search, run_command, browser, etc.) | +| `internal/im/` | IM adapters (QQ, Telegram, Discord, Slack, Feishu, WeChat, etc.) | +| `internal/permission/` | Permission modes, dangerous command detection | +| `internal/a2a/` | Agent-to-agent protocol, mDNS discovery | +| `internal/mcp/` | MCP server/client integration | +| `internal/debug/` | Debug logging system (category-based ring buffer) | +| `internal/safego/` | Panic recovery for goroutines | +| `internal/util/` | Shell detection, path helpers, common utilities | +| `mobile/flutter/` | Flutter mobile app (iOS + Android) | +| `desktop/ggcode-desktop-wails/` | Desktop app (Wails: Go backend + web frontend) | +| `desktop/ggcode-desktop/` | Legacy desktop builds (no active go.mod) | +| `docs/` | Documentation, architecture notes, release process | + +## Architecture + +### Provider System +- Config uses `vendor` / `endpoint` / `model` schema (not old `provider/providers`) +- Built-in vendors: ZAI, Anthropic, OpenAI, Google, Kimi, Aliyun, Ark, MiniMax, MiMo, GitHub Copilot, etc. +- `ResolveEndpointSelection()` resolves active config to `ResolvedEndpoint` with display names +- Built-in vendor/endpoint display names are i18n-aware (`vendor_display_i18n.go`) +- Coding plan providers return 429 for both transient limits AND quota exhaustion — `isQuotaExhaustedError()` distinguishes them + +### TUI Layout +- When any panel is open, conversation is hidden; panel fills full height +- `renderContextBox` forces full height; `renderContextBoxAuto` for compact elements (status bar) +- Composer/input position stays fixed regardless of panel content height + +### Error Handling +- `FriendlyError()` — detailed error classification for retry decisions +- `UserFacingErrorLang()` — user-facing messages with i18n (zh-CN/en) +- Both detect quota exhaustion patterns from all coding plan providers +- Non-streaming `Chat()` paths in all 3 providers have `debug.Log` on errors + +## Release Process + +**Full playbook**: `docs/release-process.md` + +Quick checklist: +1. Create `docs/releases/vX.Y.Z.md` +2. Run `cd mobile/flutter && bash scripts/version_sync.sh X.Y.Z` (bumps 4 files) +3. `make verify-ci` +4. `git commit -m "release: vX.Y.Z"` → push main +5. `git tag vX.Y.Z` → push tag +6. Monitor CI, Release, Mobile Release, CodeQL — all must pass + +**Do NOT** push tag before mobile version sync. TestFlight/Google Play reject duplicate build numbers. + +## Runtime Modes + +| Mode | Behavior | +|------|----------| +| `supervised` | Default; asks confirmation for tool calls | +| `plan` | Read-only exploration only | +| `auto` | Safe operations auto-allowed | +| `bypass` | Almost everything allowed | +| `autopilot` | Bypass + autonomous goal-directed execution | + +## Coding Conventions + +- **Build tag**: All `go build`/`go test` must use `-tags goolm` +- **Debug logging**: Use `debug.Log(category, format, args...)` — never `log.Printf` for diagnostics +- **Goroutine safety**: Use `safego.Recover("name")` or `safego.Go("name", fn)` for all goroutines +- **Circular imports**: `debug` imports `util`; `util` cannot import `debug` — use injectable callback (`SetDebugLogFn`) +- **Panel rendering**: All full-screen panels use `renderContextBox`; compact elements use `renderContextBoxAuto` +- **Error handling**: Don't swallow errors silently — add `debug.Log` on error paths +- **i18n**: TUI uses `tr(lang, key)` system; register catalogs via `registerCatalog(en, zh)` in `init()` +- **Windows shell**: PowerShell is primary (`-NoProfile -ExecutionPolicy Bypass`); Git Bash is fallback. Detection cached with `sync.Once`. Dangerous PowerShell patterns in `dangerous.go`. +- **Sub-agent model**: `spawn_agent` accepts optional `model` param; inherits parent runtime model if omitted. Sub-agents and swarm teammates always use current runtime provider, not startup-time snapshot. +- **Inline tool call detection**: `hasInlineToolCall` scans first 4KB of model response to detect non-native tool calls (nudge limited to 2 attempts). +- **Pre-commit hook**: Runs `gofmt`, `go vet`, `go build` on staged files + +## Testing + +```bash +# CI-safe (unit + Tier 1 integration) +go test -tags "goolm,integration" ./cmd/... ./internal/... + +# Full suite (needs API key + external services) +go test -tags 'goolm,integration,integration_local,integration_service' ./... +``` + +Test memory limits: `GOMEMLIMIT=2GiB GOGC=50` on shared/CI machines. +Use `-p 1 -parallel 1` to avoid OOM on large packages. diff --git a/GGCODE.md b/GGCODE.md index 1ac2e6a11..1f68404d2 100644 --- a/GGCODE.md +++ b/GGCODE.md @@ -1,129 +1,3 @@ -# ggcode +# ggcode project memory - -## Quick Reference - -| Item | Value | -|------|-------| -| Module | `github.com/topcheer/ggcode` | -| Go version | 1.26.2 (see `go.mod`) | -| Build tag | **`-tags goolm`** required for ALL `go build` / `go test` | -| Current release | v1.3.188 | -| Platform | Linux / macOS / Windows (amd64 + arm64) | - -## Validation Commands - -```bash -# CI-equivalent check (what pre-commit hook runs) -make verify-ci - -# Quick build -go build -tags goolm -o /tmp/ggcode ./cmd/ggcode - -# Run tests (use memory limits on shared/CI machines) -GOMEMLIMIT=2GiB GOGC=50 go test -tags goolm -p 1 -parallel 1 -timeout 600s ./... - -# Lint -go vet -tags goolm ./... - -# Cross-platform build check -CGO_ENABLED=0 go build -tags goolm ./... -``` - -**Key rule**: Always use `-tags goolm`. Without it, CGO-only packages (e.g. `go-olm`) will fail to compile. - -## Major Directories - -| Path | Purpose | -|------|---------| -| `cmd/ggcode/` | Main CLI entrypoint, root command, resume picker | -| `cmd/ggcode-installer/` | Go-based binary installer | -| `internal/agent/` | Agent loop, tool execution, autopilot strategist, compaction | -| `internal/tui/` | Bubble Tea terminal UI, panels, slash commands, i18n | -| `internal/provider/` | LLM provider adapters (OpenAI, Anthropic, Gemini), retry, error formatting | -| `internal/config/` | Config schema, vendor/endpoint resolution, built-in vendor defaults, i18n display names | -| `internal/session/` | JSONL session store, debounce, index, checkpoints | -| `internal/context/` | Context manager, token counting, compaction | -| `internal/tool/` | Built-in tools (file edit, search, run_command, browser, etc.) | -| `internal/im/` | IM adapters (QQ, Telegram, Discord, Slack, Feishu, WeChat, etc.) | -| `internal/permission/` | Permission modes, dangerous command detection | -| `internal/a2a/` | Agent-to-agent protocol, mDNS discovery | -| `internal/mcp/` | MCP server/client integration | -| `internal/debug/` | Debug logging system (category-based ring buffer) | -| `internal/safego/` | Panic recovery for goroutines | -| `internal/util/` | Shell detection, path helpers, common utilities | -| `mobile/flutter/` | Flutter mobile app (iOS + Android) | -| `desktop/ggcode-desktop-wails/` | Desktop app (Wails: Go backend + web frontend) | -| `desktop/ggcode-desktop/` | Legacy desktop builds (no active go.mod) | -| `docs/` | Documentation, architecture notes, release process | - -## Architecture - -### Provider System -- Config uses `vendor` / `endpoint` / `model` schema (not old `provider/providers`) -- Built-in vendors: ZAI, Anthropic, OpenAI, Google, Kimi, Aliyun, Ark, MiniMax, MiMo, GitHub Copilot, etc. -- `ResolveEndpointSelection()` resolves active config to `ResolvedEndpoint` with display names -- Built-in vendor/endpoint display names are i18n-aware (`vendor_display_i18n.go`) -- Coding plan providers return 429 for both transient limits AND quota exhaustion — `isQuotaExhaustedError()` distinguishes them - -### TUI Layout -- When any panel is open, conversation is hidden; panel fills full height -- `renderContextBox` forces full height; `renderContextBoxAuto` for compact elements (status bar) -- Composer/input position stays fixed regardless of panel content height - -### Error Handling -- `FriendlyError()` — detailed error classification for retry decisions -- `UserFacingErrorLang()` — user-facing messages with i18n (zh-CN/en) -- Both detect quota exhaustion patterns from all coding plan providers -- Non-streaming `Chat()` paths in all 3 providers have `debug.Log` on errors - -## Release Process - -**Full playbook**: `docs/release-process.md` - -Quick checklist: -1. Create `docs/releases/vX.Y.Z.md` -2. Run `cd mobile/flutter && bash scripts/version_sync.sh X.Y.Z` (bumps 4 files) -3. `make verify-ci` -4. `git commit -m "release: vX.Y.Z"` → push main -5. `git tag vX.Y.Z` → push tag -6. Monitor CI, Release, Mobile Release, CodeQL — all must pass - -**Do NOT** push tag before mobile version sync. TestFlight/Google Play reject duplicate build numbers. - -## Runtime Modes - -| Mode | Behavior | -|------|----------| -| `supervised` | Default; asks confirmation for tool calls | -| `plan` | Read-only exploration only | -| `auto` | Safe operations auto-allowed | -| `bypass` | Almost everything allowed | -| `autopilot` | Bypass + autonomous goal-directed execution | - -## Coding Conventions - -- **Build tag**: All `go build`/`go test` must use `-tags goolm` -- **Debug logging**: Use `debug.Log(category, format, args...)` — never `log.Printf` for diagnostics -- **Goroutine safety**: Use `safego.Recover("name")` or `safego.Go("name", fn)` for all goroutines -- **Circular imports**: `debug` imports `util`; `util` cannot import `debug` — use injectable callback (`SetDebugLogFn`) -- **Panel rendering**: All full-screen panels use `renderContextBox`; compact elements use `renderContextBoxAuto` -- **Error handling**: Don't swallow errors silently — add `debug.Log` on error paths -- **i18n**: TUI uses `tr(lang, key)` system; register catalogs via `registerCatalog(en, zh)` in `init()` -- **Windows shell**: PowerShell is primary (`-NoProfile -ExecutionPolicy Bypass`); Git Bash is fallback. Detection cached with `sync.Once`. Dangerous PowerShell patterns in `dangerous.go`. -- **Sub-agent model**: `spawn_agent` accepts optional `model` param; inherits parent runtime model if omitted. Sub-agents and swarm teammates always use current runtime provider, not startup-time snapshot. -- **Inline tool call detection**: `hasInlineToolCall` scans first 4KB of model response to detect non-native tool calls (nudge limited to 2 attempts). -- **Pre-commit hook**: Runs `gofmt`, `go vet`, `go build` on staged files - -## Testing - -```bash -# CI-safe (unit + Tier 1 integration) -go test -tags "goolm,integration" ./cmd/... ./internal/... - -# Full suite (needs API key + external services) -go test -tags 'goolm,integration,integration_local,integration_service' ./... -``` - -Test memory limits: `GOMEMLIMIT=2GiB GOGC=50` on shared/CI machines. -Use `-p 1 -parallel 1` to avoid OOM on large packages. +This repository's agent instructions live in [AGENTS.md](AGENTS.md) — the cross-CLI standard adopted by most coding agents. This stub keeps legacy `GGCODE.md` lookups working; do not duplicate content here. diff --git a/internal/memory/init.go b/internal/memory/init.go index 218a0b085..f5d8d2752 100644 --- a/internal/memory/init.go +++ b/internal/memory/init.go @@ -26,7 +26,10 @@ var projectPathHints = []projectPathHint{ {Path: "python", Description: "Python wrapper that installs the GitHub Release binary"}, } -// GenerateProjectMemory builds a GGCODE.md document using the current repo state. +// GenerateProjectMemory builds the AGENTS.md starter document from +// heuristically detected repo facts. /init presents it to the agent as a +// hint block - the agent explores the repository first and writes the final +// AGENTS.md from what it actually found (see handleInitCommand). func GenerateProjectMemory(root string) (string, error) { absRoot, err := filepath.Abs(root) if err != nil { @@ -46,7 +49,7 @@ func GenerateProjectMemory(root string) (string, error) { conventions := detectConventions(absRoot) var b strings.Builder - b.WriteString("# GGCODE.md\n\n") + b.WriteString("# AGENTS.md\n\n") b.WriteString("> Generated by `/init` from the current repository snapshot. Review and edit when project conventions change.\n\n") b.WriteString("## Project Snapshot\n") @@ -118,7 +121,7 @@ func detectReadmeSummary(root string) string { // #1615: centered HTML banners (

, ,

) // are the first "paragraph" in many READMEs (this repo's own) - // the tag soup became the project Summary injected into every - // session's GGCODE.md. Skip HTML-tag lines and empty-out + // session's AGENTS.md. Skip HTML-tag lines and empty-out // tag-only paragraphs so the first REAL text paragraph wins. if strings.HasPrefix(line, "<") { continue @@ -149,7 +152,7 @@ func detectTechStack(root string) []string { // #1636-A: same gate as detectImportantPaths (#1593-A) - the specific // stack claims below (npm release wrapper, plugin-system phrases) are // ggcode's OWN facts; a user repo with python/ or an MCP-mentioning - // README got them written into GGCODE.md as MUST-follow context. + // README got them written into AGENTS.md as MUST-follow context. // Correct silence beats wrong facts; foreign repos keep only the // generic Go-codebase line. module := detectGoModule(root) @@ -186,7 +189,7 @@ func detectImportantPaths(root string) []string { // #1593-A: the hints describe THIS repository's layout. Almost every // standard Go repo has internal/agent, internal/tool, docs/, python/ // namesakes - emitting these descriptions for a user's own repo wrote - // factually WRONG entries into GGCODE.md, which is injected into every + // factually WRONG entries into AGENTS.md, which is injected into every // subsequent session ("MUST follow"). Gate on the module name; foreign // repos get no path claims at all (correct silence beats wrong facts). module := detectGoModule(root) diff --git a/internal/memory/project.go b/internal/memory/project.go index 7cc3551a4..358f2a8e3 100644 --- a/internal/memory/project.go +++ b/internal/memory/project.go @@ -31,7 +31,7 @@ var CompatibilitySubdirRules = []string{ ".github/copilot-instructions.md", } -const DefaultProjectMemoryFilename = "GGCODE.md" +const DefaultProjectMemoryFilename = "AGENTS.md" // LoadProjectMemory reads supported project bootstrap documents from the // global config dir (~/.ggcode/) and the current working directory only. diff --git a/internal/memory/project_test.go b/internal/memory/project_test.go index ac7f0d832..b676dcfc5 100644 --- a/internal/memory/project_test.go +++ b/internal/memory/project_test.go @@ -156,7 +156,7 @@ func TestResolveProjectMemoryInitTarget_CurrentDirOnly(t *testing.T) { t.Fatalf("unexpected error: %v", err) } // Should target the current working dir, not walk up to git root - if target != filepath.Join(subDir, "GGCODE.md") { + if target != filepath.Join(subDir, "AGENTS.md") { t.Fatalf("expected current-dir target, got %q", target) } if len(existing) != 0 { diff --git a/internal/tui/commands.go b/internal/tui/commands.go index ec9ba9d45..96d88db8f 100644 --- a/internal/tui/commands.go +++ b/internal/tui/commands.go @@ -691,13 +691,32 @@ func (m *Model) handleInitCommand() tea.Cmd { m.chatWriteSystem(nextSystemID(), m.t("init.generate_failed", err)) return nil } - // Build init prompt directly - var prompt string + // Exploration-first init prompt (#AGENTS.md standard): the agent must + // understand the repository BEFORE writing the memory file, instead of + // dumping the heuristic snapshot verbatim. The detected facts below are + // hints to verify, not the final content. + verb := "Create" if existed { - prompt = fmt.Sprintf("Update project memory file at %s with the following content:\n\n%s", targetPath, content) - } else { - prompt = fmt.Sprintf("Create project memory file at %s with the following content:\n\n%s", targetPath, content) + verb = "Update" } + prompt := fmt.Sprintf(`%s the project memory file at %s (AGENTS.md - the cross-CLI agent instructions standard). + +FIRST understand this repository - do NOT write the file from a generic template: +1. Read the README and docs/ overview: what does this application do? +2. Read build manifests (go.mod / package.json / Cargo.toml / ...) and map entrypoints (cmd/, main.*, src/) to major directories and their responsibilities. +3. Read Makefile / CI workflows (.github/workflows, ...) to learn the REAL build, test, and lint commands. +4. Skim a few representative source and test files to infer conventions (logging, error handling, i18n, testing style). + +THEN %s AGENTS.md with durable guidance for coding agents: +- Project snapshot: what the app is, module path, stack +- Validation: exact build/test/lint commands as verified in CI/Makefile +- Architecture: major directories and what lives where +- Coding conventions: rules this repo actually follows +- Concise (~100-150 lines), durable guidance only - no one-off task plans + +Heuristically detected hints (VERIFY each against the repository; discard anything wrong or stale): + +%s`, verb, targetPath, verb, content) m.chatWriteUser(nextChatID(), "/init") m.appendUserMessage("/init") diff --git a/internal/tui/completion.go b/internal/tui/completion.go index b46ede819..e6d727dea 100644 --- a/internal/tui/completion.go +++ b/internal/tui/completion.go @@ -436,7 +436,7 @@ var SlashCommandDescriptions = map[string]string{ "/chat": "Open LAN chat panel", "/nick": "Set LAN chat nickname, role, and team", "/image": "Attach an image", - "/init": "Create GGCODE.md", + "/init": "Create AGENTS.md", "/exit": "Exit ggcode", "/quit": "Exit ggcode", "/compact": "Compress conversation history", diff --git a/internal/tui/i18n_command.go b/internal/tui/i18n_command.go index b25c0cfe6..74970aa32 100644 --- a/internal/tui/i18n_command.go +++ b/internal/tui/i18n_command.go @@ -21,7 +21,7 @@ func enCommandModule() map[string]string { "slash.plugins": "List loaded plugins", "slash.image": "Attach an image", "slash.mode": "Set permission mode", - "slash.init": "Generate project GGCODE.md", + "slash.init": "Generate project AGENTS.md", "slash.lang": "Switch interface language", "slash.skills": "Browse available skills", "slash.exit": "Exit ggcode", @@ -83,7 +83,7 @@ func enCommandModule() map[string]string { "command.mention_error": "Mention expansion error: %v", "command.skill_agent_only": "Skill %s can only be invoked by the agent.", "init.resolve_failed": "Failed to resolve init target: %v\n\n", - "init.generate_failed": "Failed to generate GGCODE.md content: %v\n\n", + "init.generate_failed": "Failed to generate AGENTS.md content: %v\n\n", "init.collecting": "Collecting project knowledge...", "help.text": `Available commands: /help, /? Show this help message @@ -117,7 +117,7 @@ func enCommandModule() map[string]string { /plugins List loaded plugins and their tools /image Attach an image file /mode Set agent mode (supervised|plan|auto|bypass|autopilot) - /init Generate GGCODE.md from the current project + /init Generate AGENTS.md from the current project /agents List sub-agents /agent Show sub-agent details /agent cancel Cancel a sub-agent @@ -166,7 +166,7 @@ func zhCommandModule() map[string]string { "slash.plugins": "列出已加载插件", "slash.image": "附加图片", "slash.mode": "设置权限模式", - "slash.init": "生成项目 GGCODE.md", + "slash.init": "生成项目 AGENTS.md", "slash.lang": "切换界面语言", "slash.skills": "浏览可用 skills", "slash.exit": "退出 ggcode", @@ -228,7 +228,7 @@ func zhCommandModule() map[string]string { "command.mention_error": "展开 @ 引用失败:%v", "command.skill_agent_only": "技能 %s 只能由 agent 调用。", "init.resolve_failed": "解析初始化目标失败:%v\n\n", - "init.generate_failed": "生成 GGCODE.md 内容失败:%v\n\n", + "init.generate_failed": "生成 AGENTS.md 内容失败:%v\n\n", "init.collecting": "正在收集项目知识...", "help.text": `可用命令: /help, /? 显示帮助 @@ -262,7 +262,7 @@ func zhCommandModule() map[string]string { /plugins 列出已加载插件及其工具 /image 附加图片文件 /mode 设置运行模式(supervised|plan|auto|bypass|autopilot) - /init 基于当前项目生成 GGCODE.md + /init 基于当前项目生成 AGENTS.md /agents 列出子 Agent /agent 查看子 Agent 详情 /agent cancel 取消子 Agent diff --git a/internal/tui/i18n_de.go b/internal/tui/i18n_de.go index 03fc07864..489a71cb8 100644 --- a/internal/tui/i18n_de.go +++ b/internal/tui/i18n_de.go @@ -559,19 +559,19 @@ func deCatalog(key string) string { case "init.resolve_failed": return "Init-Ziel konnte nicht aufgelöst werden: %v\n\n" case "init.generate_failed": - return "GGCODE.md-Inhalt konnte nicht generiert werden: %v\n\n" + return "AGENTS.md-Inhalt konnte nicht generiert werden: %v\n\n" case "init.collecting": return "Projektwissen wird gesammelt..." case "init.prompt.title": return "Projekt initialisieren" case "init.prompt.body": - return "Keine GGCODE.md in diesem Projekt gefunden. Eine erstellen, damit der Agent Ihre Codebase-Konventionen versteht?" + return "Keine AGENTS.md in diesem Projekt gefunden. Eine erstellen, damit der Agent Ihre Codebase-Konventionen versteht?" case "init.prompt.yes": return "Erstellen" case "init.prompt.no": return "Überspringen" case "init.prompt.hint": - return " y = GGCODE.md erstellen • n/Esc = überspringen" + return " y = AGENTS.md erstellen • n/Esc = überspringen" // --- Model commands --- case "command.model_switched": @@ -873,7 +873,7 @@ func deCatalog(key string) string { case "slash.image": return "Bild anhängen" case "slash.init": - return "Projekt-GGCODE.md generieren" + return "Projekt-AGENTS.md generieren" case "slash.lang": return "Oberflächensprache wechseln" case "slash.skills": @@ -1159,7 +1159,7 @@ Entwicklung: /cost Sitzungs-Token-Nutzung und geschätzte Kosten anzeigen /context Kontextfenster-Nutzung aufschlüsseln /hooks Konfigurierte Hooks anzeigen - /init GGCODE.md aus aktuellem Projekt generieren + /init AGENTS.md aus aktuellem Projekt generieren /todo Todo-Liste anzeigen /todo clear Todo-Liste löschen diff --git a/internal/tui/i18n_en.go b/internal/tui/i18n_en.go index 7ea483b32..de163028e 100644 --- a/internal/tui/i18n_en.go +++ b/internal/tui/i18n_en.go @@ -574,19 +574,19 @@ func enCatalog(key string) string { case "init.resolve_failed": return "Failed to resolve init target: %v\n\n" case "init.generate_failed": - return "Failed to generate GGCODE.md content: %v\n\n" + return "Failed to generate AGENTS.md content: %v\n\n" case "init.collecting": return "Collecting project knowledge..." case "init.prompt.title": return "Initialize project" case "init.prompt.body": - return "No GGCODE.md found in this project. Create one to help the agent understand your codebase conventions?" + return "No AGENTS.md found in this project. Create one to help the agent understand your codebase conventions?" case "init.prompt.yes": return "Create" case "init.prompt.no": return "Skip" case "init.prompt.hint": - return " y = create GGCODE.md • n/Esc = skip" + return " y = create AGENTS.md • n/Esc = skip" case "command.model_switched": return "Switched model to: %s (vendor: %s)\n\n" case "command.model_failed": @@ -888,7 +888,7 @@ func enCatalog(key string) string { case "slash.image": return "Attach an image" case "slash.init": - return "Generate project GGCODE.md" + return "Generate project AGENTS.md" case "slash.lang": return "Switch interface language" case "slash.skills": @@ -1241,7 +1241,7 @@ Development: /allow [tool] Permanently allow a tool in current mode /files Open fullscreen file browser with preview /inspector [filt] Open inspector panel (tool calls, context, metrics) - /init Generate GGCODE.md from the current project + /init Generate AGENTS.md from the current project /todo View todo list /todo clear Clear todo list /reflect Trigger agent self-reflection on recent runs diff --git a/internal/tui/i18n_es.go b/internal/tui/i18n_es.go index b0344b5ab..1bf6cdae1 100644 --- a/internal/tui/i18n_es.go +++ b/internal/tui/i18n_es.go @@ -507,19 +507,19 @@ func esCatalog(key string) string { case "init.resolve_failed": return "Error al resolver el objetivo de init: %v\n\n" case "init.generate_failed": - return "Error al generar contenido de GGCODE.md: %v\n\n" + return "Error al generar contenido de AGENTS.md: %v\n\n" case "init.collecting": return "Recopilando conocimiento del proyecto..." case "init.prompt.title": return "Inicializar proyecto" case "init.prompt.body": - return "No se encontro GGCODE.md en este proyecto. Crear uno para ayudar al agente a entender las convenciones de su código?" + return "No se encontro AGENTS.md en este proyecto. Crear uno para ayudar al agente a entender las convenciones de su código?" case "init.prompt.yes": return "Crear" case "init.prompt.no": return "Omitir" case "init.prompt.hint": - return " y = crear GGCODE.md • n/Esc = omitir" + return " y = crear AGENTS.md • n/Esc = omitir" case "command.model_switched": return "Modelo cambiado a: %s (proveedor: %s)\n\n" case "command.model_failed": @@ -791,7 +791,7 @@ func esCatalog(key string) string { case "slash.image": return "Adjuntar una imagen" case "slash.init": - return "Generar GGCODE.md del proyecto" + return "Generar AGENTS.md del proyecto" case "slash.lang": return "Cambiar idioma de interfaz" case "slash.skills": @@ -1057,7 +1057,7 @@ Desarrollo: /cost Mostrar uso de tokens y costo estimado de la sesión /context Mostrar desglose de uso de ventana de contexto /hooks Mostrar hooks configurados - /init Generar GGCODE.md del proyecto actual + /init Generar AGENTS.md del proyecto actual /todo Ver lista de táreas /todo clear Limpiar lista de táreas diff --git a/internal/tui/i18n_fr.go b/internal/tui/i18n_fr.go index 68a34f051..702be87c8 100644 --- a/internal/tui/i18n_fr.go +++ b/internal/tui/i18n_fr.go @@ -507,19 +507,19 @@ func frCatalog(key string) string { case "init.resolve_failed": return "Erreur de resolution de la cible d'init: %v\n\n" case "init.generate_failed": - return "Erreur de génération du contenu GGCODE.md: %v\n\n" + return "Erreur de génération du contenu AGENTS.md: %v\n\n" case "init.collecting": return "Collecte des connaissances du projet..." case "init.prompt.title": return "Initialisér le projet" case "init.prompt.body": - return "Aucun GGCODE.md trouvé dans ce projet. En créer un pour aider l'agent a comprendre les conventions de votre code?" + return "Aucun AGENTS.md trouvé dans ce projet. En créer un pour aider l'agent a comprendre les conventions de votre code?" case "init.prompt.yes": return "Créer" case "init.prompt.no": return "Passer" case "init.prompt.hint": - return " y = créer GGCODE.md • n/Esc = passer" + return " y = créer AGENTS.md • n/Esc = passer" case "command.model_switched": return "Modèle change en: %s (fournisseur: %s)\n\n" case "command.model_failed": @@ -791,7 +791,7 @@ func frCatalog(key string) string { case "slash.image": return "Joindre une imâge" case "slash.init": - return "Génèrer le GGCODE.md du projet" + return "Génèrer le AGENTS.md du projet" case "slash.lang": return "Changer là langue de l'interface" case "slash.skills": @@ -1057,7 +1057,7 @@ Developpement: /cost Afficher l'utilisation de tokens et le coût estime de la session /context Afficher le détail d'utilisation de la fenêtre de contexte /hooks Afficher les hooks configurés - /init Génèrer le GGCODE.md du projet actuel + /init Génèrer le AGENTS.md du projet actuel /todo Voir la liste de tâches /todo clear Effacér la liste de tâches diff --git a/internal/tui/i18n_ja.go b/internal/tui/i18n_ja.go index 3b59d3094..1b513aac2 100644 --- a/internal/tui/i18n_ja.go +++ b/internal/tui/i18n_ja.go @@ -548,19 +548,19 @@ func jaCatalog(key string) string { case "init.resolve_failed": return "初期化ターゲットの解決に失敗しました: %v\n\n" case "init.generate_failed": - return "GGCODE.md コンテンツの生成に失敗しました: %v\n\n" + return "AGENTS.md コンテンツの生成に失敗しました: %v\n\n" case "init.collecting": return "プロジェクト知識を収集中..." case "init.prompt.title": return "プロジェクトを初期化" case "init.prompt.body": - return "このプロジェクトに GGCODE.md が見つかりません。エージェントがコードベースの規約を理解できるように作成しますか?" + return "このプロジェクトに AGENTS.md が見つかりません。エージェントがコードベースの規約を理解できるように作成しますか?" case "init.prompt.yes": return "作成" case "init.prompt.no": return "スキップ" case "init.prompt.hint": - return " y = GGCODE.md作成 • n/Esc = スキップ" + return " y = AGENTS.md作成 • n/Esc = スキップ" case "command.model_switched": return "モデルを %s に切り替えました(ベンダー: %s)\n\n" case "command.model_failed": @@ -836,7 +836,7 @@ func jaCatalog(key string) string { case "slash.image": return "画像を添付" case "slash.init": - return "GGCODE.md を生成" + return "AGENTS.md を生成" case "slash.lang": return "言語を切り替え" case "slash.skills": @@ -1102,7 +1102,7 @@ func jaCatalog(key string) string { /cost セッショントークン使用量と推定コストを表示 /context コンテキストウィンドウ使用量の内訳を表示 /hooks 設定済みフックを表示 - /init 現在のプロジェクトから GGCODE.md を生成 + /init 現在のプロジェクトから AGENTS.md を生成 /todo TODOリストを表示 /todo clear TODOリストをクリア diff --git a/internal/tui/i18n_ko.go b/internal/tui/i18n_ko.go index 4f64b78cb..02e4014a6 100644 --- a/internal/tui/i18n_ko.go +++ b/internal/tui/i18n_ko.go @@ -511,19 +511,19 @@ func koCatalog(key string) string { case "init.resolve_failed": return "초기화 대상 확인 실패: %v\n\n" case "init.generate_failed": - return "GGCODE.md 콘텐츠 생성 실패: %v\n\n" + return "AGENTS.md 콘텐츠 생성 실패: %v\n\n" case "init.collecting": return "프로젝트 지식 수집 중..." case "init.prompt.title": return "프로젝트 초기화" case "init.prompt.body": - return "이 프로젝트에 GGCODE.md가 없습니다. 에이전트가 프로젝트를 이해하는 데 도움이 되도록 생성하세요." + return "이 프로젝트에 AGENTS.md가 없습니다. 에이전트가 프로젝트를 이해하는 데 도움이 되도록 생성하세요." case "init.prompt.yes": return "생성" case "init.prompt.no": return "건너뛰기" case "init.prompt.hint": - return " y = GGCODE.md 생성 • n/Esc = 건너뛰기" + return " y = AGENTS.md 생성 • n/Esc = 건너뛰기" case "command.model_switched": return "모델 전환: %s (제공자: %s)\n\n" case "command.model_failed": @@ -797,7 +797,7 @@ func koCatalog(key string) string { case "slash.image": return "이미지 첨부" case "slash.init": - return "프로젝트 GGCODE.md 생성" + return "프로젝트 AGENTS.md 생성" case "slash.lang": return "인터페이스 언어 전환" case "slash.skills": @@ -1113,7 +1113,7 @@ func koCatalog(key string) string { /cost 세션 토큰 사용량 및 예상 비용 표시 /context 컨텍스트 윈도우 사용량 내역 표시 /hooks 설정된 훅 표시 - /init 현재 프로젝트에서 GGCODE.md 생성 + /init 현재 프로젝트에서 AGENTS.md 생성 /todo 할 일 목록 보기 /todo clear 할 일 목록 지우기 diff --git a/internal/tui/i18n_pt.go b/internal/tui/i18n_pt.go index 4995ababa..2ca3dece8 100644 --- a/internal/tui/i18n_pt.go +++ b/internal/tui/i18n_pt.go @@ -166,7 +166,7 @@ func ptCatalog(key string) string { case "slash.context": return "Mostrar detalhamento de uso da janela de contexto" case "slash.init": - return "Gerar GGCODE.md a partir do projeto atual" + return "Gerar AGENTS.md a partir do projeto atual" case "slash.im": return "Abrir painel unificado de canais IM" case "slash.mcp": @@ -336,13 +336,13 @@ func ptCatalog(key string) string { case "init.prompt.title": return "Inicializar projeto" case "init.prompt.body": - return "Nenhum GGCODE.md encontrado neste projeto. Criar um para ajudar o agente a entender as convenções do seu código?" + return "Nenhum AGENTS.md encontrado neste projeto. Criar um para ajudar o agente a entender as convenções do seu código?" case "init.prompt.yes": return "Criar" case "init.prompt.no": return "Pular" case "init.prompt.hint": - return " y = criar GGCODE.md • n/Esc = pular" + return " y = criar AGENTS.md • n/Esc = pular" // ── Activity ────────────────────────────────────────────────── case "activity.idle": @@ -1016,7 +1016,7 @@ func ptCatalog(key string) string { // ── Init ────────────────────────────────────────────────────── case "init.generate_failed": - return "Falha ao gerar conteúdo GGCODE.md: %v\n\n" + return "Falha ao gerar conteúdo AGENTS.md: %v\n\n" case "init.resolve_failed": return "Falha ao resolver destino de inicialização: %v\n\n" diff --git a/internal/tui/i18n_ru.go b/internal/tui/i18n_ru.go index 8509b1f8a..91cd2ca6f 100644 --- a/internal/tui/i18n_ru.go +++ b/internal/tui/i18n_ru.go @@ -551,19 +551,19 @@ func ruCatalog(key string) string { case "init.resolve_failed": return "Не удалось разрешить цель init: %v\n\n" case "init.generate_failed": - return "Не удалось сгенерировать содержимое GGCODE.md: %v\n\n" + return "Не удалось сгенерировать содержимое AGENTS.md: %v\n\n" case "init.collecting": return "Сбор знаний о проекте..." case "init.prompt.title": return "Инициализация проекта" case "init.prompt.body": - return "GGCODE.md не найдена в этом проекте. Создать, чтобы агент понимал конвенции вашей кодовой базы?" + return "AGENTS.md не найдена в этом проекте. Создать, чтобы агент понимал конвенции вашей кодовой базы?" case "init.prompt.yes": return "Создать" case "init.prompt.no": return "Пропустить" case "init.prompt.hint": - return " y = создать GGCODE.md • n/Esc = пропустить" + return " y = создать AGENTS.md • n/Esc = пропустить" // --- Model commands --- case "command.model_switched": @@ -865,7 +865,7 @@ func ruCatalog(key string) string { case "slash.image": return "Прикрепить изображение" case "slash.init": - return "Сгенерировать GGCODE.md для проекта" + return "Сгенерировать AGENTS.md для проекта" case "slash.lang": return "Сменить язык интерфейса" case "slash.skills": @@ -1141,7 +1141,7 @@ func ruCatalog(key string) string { /cost Показать использование токенов и оценочную стоимость /context Показать разбивку контекстного окна /hooks Показать настроенные хуки - /init Сгенерировать GGCODE.md из текущего проекта + /init Сгенерировать AGENTS.md из текущего проекта /todo Показать список задач /todo clear Очистить список задач diff --git a/internal/tui/i18n_vi.go b/internal/tui/i18n_vi.go index ee708186c..0fab66a8c 100644 --- a/internal/tui/i18n_vi.go +++ b/internal/tui/i18n_vi.go @@ -507,19 +507,19 @@ func viCatalog(key string) string { case "init.resolve_failed": return "Không thể giải quyết mục tiêu init: %v\n\n" case "init.generate_failed": - return "Không thể tạo nội dung GGCODE.md: %v\n\n" + return "Không thể tạo nội dung AGENTS.md: %v\n\n" case "init.collecting": return "Đang thu thập kiến thức dự án..." case "init.prompt.title": return "Khởi tạo dự án" case "init.prompt.body": - return "Không tìm thấy GGCODE.md trong dự án này. Tạo một tệp để giúp agent hiểu quy ước codebase của bạn?" + return "Không tìm thấy AGENTS.md trong dự án này. Tạo một tệp để giúp agent hiểu quy ước codebase của bạn?" case "init.prompt.yes": return "Tạo" case "init.prompt.no": return "Bỏ qua" case "init.prompt.hint": - return " y = tạo GGCODE.md • n/Esc = bỏ qua" + return " y = tạo AGENTS.md • n/Esc = bỏ qua" case "command.model_switched": return "Đã chuyển mô hình sang: %s (nhà cung cấp: %s)\n\n" case "command.model_failed": @@ -791,7 +791,7 @@ func viCatalog(key string) string { case "slash.image": return "Đính kèm ảnh" case "slash.init": - return "Tạo GGCODE.md cho dự án" + return "Tạo AGENTS.md cho dự án" case "slash.lang": return "Chuyển ngôn ngữ giao diện" case "slash.skills": @@ -1057,7 +1057,7 @@ Phát triển: /cost Hiện sử dụng token và chi phí ước tính /context Hiện phân tích cửa sổ ngữ cảnh /hooks Hiện hook đã cấu hình - /init Tạo GGCODE.md từ dự án hiện tại + /init Tạo AGENTS.md từ dự án hiện tại /todo Xem danh sách todo /todo clear Xóa danh sách todo diff --git a/internal/tui/i18n_zh.go b/internal/tui/i18n_zh.go index 797e37628..d5a99e108 100644 --- a/internal/tui/i18n_zh.go +++ b/internal/tui/i18n_zh.go @@ -585,19 +585,19 @@ func zhCatalog(key string) string { case "init.resolve_failed": return "解析初始化目标失败:%v\n\n" case "init.generate_failed": - return "生成 GGCODE.md 内容失败:%v\n\n" + return "生成 AGENTS.md 内容失败:%v\n\n" case "init.collecting": return "正在收集项目知识..." case "init.prompt.title": return "初始化项目" case "init.prompt.body": - return "此项目中未找到 GGCODE.md。是否创建一个,帮助 agent 了解你的代码规范?" + return "此项目中未找到 AGENTS.md。是否创建一个,帮助 agent 了解你的代码规范?" case "init.prompt.yes": return "创建" case "init.prompt.no": return "跳过" case "init.prompt.hint": - return " y = 创建 GGCODE.md • n/Esc = 跳过" + return " y = 创建 AGENTS.md • n/Esc = 跳过" case "command.model_switched": return "已切换模型为:%s(供应商:%s)\n\n" case "command.model_failed": @@ -901,7 +901,7 @@ func zhCatalog(key string) string { case "slash.image": return "附加图片" case "slash.init": - return "生成项目 GGCODE.md" + return "生成项目 AGENTS.md" case "slash.lang": return "切换界面语言" case "slash.skills": @@ -1252,7 +1252,7 @@ func zhCatalog(key string) string { /allow [tool] 在当前模式中永久允许某个工具 /files 打开全屏文件浏览器(含预览) /inspector [filt] 打开检查器面板(工具调用、上下文、指标) - /init 基于当前项目生成 GGCODE.md + /init 基于当前项目生成 AGENTS.md /todo 查看 todo 列表 /todo clear 清空 todo 列表 /reflect 触发 Agent 对近期运行的自省 diff --git a/internal/tui/model.go b/internal/tui/model.go index 92064c9ef..a79da672e 100644 --- a/internal/tui/model.go +++ b/internal/tui/model.go @@ -729,7 +729,7 @@ func (m Model) Init() tea.Cmd { // place for the chain to start; explain-side checks gate it). func() tea.Msg { return usageSidebarRefreshMsg{} }, } - // Check whether the project has a GGCODE.md (or AGENTS.md, CLAUDE.md, + // Check whether the project has an AGENTS.md (or GGCODE.md, CLAUDE.md, // COPILOT.md). If none exist AND the directory has real project files // (non-hidden), prompt the user to initialize. The HOME directory is // skipped: users often run ggcode there for ad-hoc chores, not to diff --git a/internal/tui/model_messages.go b/internal/tui/model_messages.go index fe06be26b..fbe8eec94 100644 --- a/internal/tui/model_messages.go +++ b/internal/tui/model_messages.go @@ -75,10 +75,10 @@ type sessionMetricMsg struct { Metric metrics.MetricEvent } -// initPromptCheckMsg carries the result of the startup GGCODE.md existence check. +// initPromptCheckMsg carries the result of the startup AGENTS.md existence check. type initPromptCheckMsg struct { needsInit bool - target string // path to GGCODE.md that would be created + target string // path to AGENTS.md that would be created } type projectMemoryLoadedMsg struct { diff --git a/internal/tui/update_keys.go b/internal/tui/update_keys.go index 49cce1619..d04a4a2b3 100644 --- a/internal/tui/update_keys.go +++ b/internal/tui/update_keys.go @@ -817,7 +817,7 @@ func setValueAtCursor(ta *textarea.Model, value string, row, col int) { ta.SetCursorColumn(col) } -// handleInitPromptKey handles keyboard input for the startup "Create GGCODE.md?" prompt. +// handleInitPromptKey handles keyboard input for the startup "Create AGENTS.md?" prompt. func (m Model) handleInitPromptKey(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { switch msg.String() { case "y", "Y", "enter":