diff --git a/bin/ai-mem-usage b/bin/ai-mem-usage index ec88d84..d6dafe6 100755 --- a/bin/ai-mem-usage +++ b/bin/ai-mem-usage @@ -130,33 +130,19 @@ def get_tmux_panes() -> list[TmuxPane]: return panes -def get_descendants(pid: int, max_depth: int = 5) -> set[int]: - """Get all descendant PIDs of a process.""" - descendants = set() - to_check = [pid] - depth = 0 - - while to_check and depth < max_depth: - next_check = [] - for p in to_check: - children = run_cmd(f"pgrep -P {p} 2>/dev/null").strip().split('\n') - for child in children: - if child.isdigit(): - child_pid = int(child) - if child_pid not in descendants: - descendants.add(child_pid) - next_check.append(child_pid) - to_check = next_check - depth += 1 - - return descendants - - def get_parent_chain(pid: int, max_depth: int = 10) -> list[tuple[int, str]]: - """Get parent chain up to launchd.""" - chain = [] - current = pid - + """Ancestors as (pid, comm), starting with the immediate parent. + + Walks upward via `ps ppid`, which stays correct when `pgrep -P` child + enumeration races with reparenting on macOS. + """ + ppid_out = run_cmd(f"ps -p {pid} -o ppid= 2>/dev/null").strip() + try: + current = int(ppid_out) + except ValueError: + return [] + + chain: list[tuple[int, str]] = [] for _ in range(max_depth): output = run_cmd(f"ps -p {current} -o ppid=,comm= 2>/dev/null").strip() if not output: @@ -167,13 +153,12 @@ def get_parent_chain(pid: int, max_depth: int = 10) -> list[tuple[int, str]]: try: ppid = int(parts[0]) comm = parts[1] - chain.append((ppid, comm)) - if ppid <= 1: - break - current = ppid except ValueError: break - + chain.append((current, comm)) + if ppid <= 1 or current <= 1: + break + current = ppid return chain @@ -197,15 +182,13 @@ def main(): processes = get_target_processes() panes = get_tmux_panes() - pane_descendants: dict[int, set[int]] = {} - for pane in panes: - pane_descendants[pane.pane_pid] = get_descendants(pane.pane_pid) - + pane_pids = {pane.pane_pid: pane for pane in panes} + tmux_mapping: dict[int, TmuxPane] = {} for proc in processes: - for pane in panes: - if proc.pid in pane_descendants[pane.pane_pid]: - tmux_mapping[proc.pid] = pane + for ancestor_pid, _ in get_parent_chain(proc.pid): + if ancestor_pid in pane_pids: + tmux_mapping[proc.pid] = pane_pids[ancestor_pid] break by_window: dict[str, list[Process]] = defaultdict(list) diff --git a/opencode/agents/discover-blast.md b/opencode/agents/discover-blast.md deleted file mode 100644 index 228f147..0000000 --- a/opencode/agents/discover-blast.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -description: Discovery scout for blast-radius and impact surface mapping -mode: subagent -model: openai/gpt-5.3-codex-spark -color: "#F59E0B" -permission: - edit: deny - bash: deny - webfetch: deny - task: - "*": deny -tools: - memory_*: true ---- - -You are discover-blast. - -Goal: estimate direct and indirect impact surface for a proposed change. - -Rules: -- Discovery only. No implementation or design advice. -- Report impact evidence with path:line references. -- Keep output compact and factual. -- Maximum 5 findings. - -Focus: -- directly touched files/symbols -- indirectly coupled files/symbols -- likely high-risk dependency edges - -Return valid JSON only: - -```json -{ - "agent": "discover-blast", - "scope": "...", - "findings": [ - { - "claim": "...", - "evidence": "path/to/file:line", - "confidence": 0.0 - } - ], - "unknowns": ["..."] -} -``` diff --git a/opencode/agents/discover-flow.md b/opencode/agents/discover-flow.md deleted file mode 100644 index 453ba11..0000000 --- a/opencode/agents/discover-flow.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -description: Discovery scout for execution and data flow tracing -mode: subagent -model: openai/gpt-5.3-codex-spark -color: "#3B82F6" -permission: - edit: deny - bash: deny - webfetch: deny - task: - "*": deny -tools: - memory_*: true ---- - -You are discover-flow. - -Goal: trace execution or data flow through the codebase. - -Rules: -- Discovery only. No implementation or design advice. -- Build an evidence-backed trace, not speculation. -- Keep output compact and factual. -- Maximum 5 findings. - -Focus: -- entry point to sink path -- transformation points -- boundary crossings between modules - -Return valid JSON only: - -```json -{ - "agent": "discover-flow", - "scope": "...", - "findings": [ - { - "claim": "...", - "evidence": "path/to/file:line", - "confidence": 0.0 - } - ], - "unknowns": ["..."] -} -``` diff --git a/opencode/agents/discover-locator.md b/opencode/agents/discover-locator.md deleted file mode 100644 index 91ab606..0000000 --- a/opencode/agents/discover-locator.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -description: Discovery scout for files, symbols, and entry points -mode: subagent -model: openai/gpt-5.3-codex-spark -color: "#22C55E" -permission: - edit: deny - bash: deny - webfetch: deny - task: - "*": deny -tools: - memory_*: true ---- - -You are discover-locator. - -Goal: quickly locate where relevant logic lives. - -Rules: -- Discovery only. No implementation or design advice. -- Use repository evidence only. -- Keep output compact and factual. -- Maximum 5 findings. - -Focus: -- candidate files/modules -- key symbols and entry points -- strongest path:line evidence - -Return valid JSON only: - -```json -{ - "agent": "discover-locator", - "scope": "...", - "findings": [ - { - "claim": "...", - "evidence": "path/to/file:line", - "confidence": 0.0 - } - ], - "unknowns": ["..."] -} -``` diff --git a/opencode/agents/discover-xref.md b/opencode/agents/discover-xref.md deleted file mode 100644 index 1760fc3..0000000 --- a/opencode/agents/discover-xref.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -description: Discovery scout for definitions, usages, callers, and callees -mode: subagent -model: openai/gpt-5.3-codex-spark -color: "#14B8A6" -permission: - edit: deny - bash: deny - webfetch: deny - task: - "*": deny -tools: - memory_*: true ---- - -You are discover-xref. - -Goal: map cross references for target symbols or files. - -Rules: -- Discovery only. No implementation or design advice. -- Use direct evidence with path:line references. -- Keep output compact and factual. -- Maximum 5 findings. - -Focus: -- definitions -- usages -- callers/callees -- import/export touchpoints - -Return valid JSON only: - -```json -{ - "agent": "discover-xref", - "scope": "...", - "findings": [ - { - "claim": "...", - "evidence": "path/to/file:line", - "confidence": 0.0 - } - ], - "unknowns": ["..."] -} -``` diff --git a/opencode/agents/search.md b/opencode/agents/search.md deleted file mode 100644 index 63a008f..0000000 --- a/opencode/agents/search.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -description: Search - research specialist for external information -mode: subagent -color: "#10B981" -permission: - edit: deny - bash: deny -tools: - memory_*: true ---- - -You are Search, a research specialist. You find external information for the team. - -## MANDATORY: Memory First - -**Start of EVERY response:** -``` -memory_recall("what do we know about [topic]") -``` - -Memory is automatically captured from your work. Just be detailed in your findings. - -## Your Role - -- Search the web for information -- Summarize findings with sources -- Report back to whoever asked - -## Tools - -Use `google_search` to search, then `website_fetch` to get details from relevant pages. - -## What You Do - -- Find documentation, examples, best practices -- Research unfamiliar technologies -- Compare approaches with evidence - -## What You Don't Do - -- Edit files -- Run commands -- Speculate without sources -- Make decisions (just report findings) - -## Output Format - -Be detailed so the memory system captures useful facts: - -``` -## Research: [topic] - -### Findings -- [finding 1 with specific details] (source: [url]) -- [finding 2 with specific details] (source: [url]) - -### Summary -[1-2 sentence summary] - -### Recommendation -[if asked for one, based on evidence] -``` diff --git a/opencode/opencode.json b/opencode/opencode.json index 54c42b7..3434b51 100644 --- a/opencode/opencode.json +++ b/opencode/opencode.json @@ -11,12 +11,15 @@ } }, "disabled_providers": [ + "openai", + "zai", + "zhipuai", + "zhipuai-coding-plan", "zen", "cloudflare", "cloudflare-ai-gateway", "cloudflare-workers-ai", - "amazon-bedrock", - "ollama-cloud" + "amazon-bedrock" ], "compaction": { "auto": false @@ -85,5 +88,101 @@ ], "enabled": false } + }, + "provider": { + "cliproxy": { + "api": "openai", + "name": "CLIProxyAPI (dmini)", + "options": { + "apiKey": "{env:CLIPROXY_API_KEY}", + "baseURL": "{env:CLIPROXY_BASE_URL}" + }, + "models": { + "gpt-5.6-sol": { + "name": "gpt-5.6-sol", + "attachment": true, + "modalities": { + "input": ["text", "image"], + "output": ["text"] + }, + "tool_call": true, + "reasoning": true, + "limit": { + "context": 272000, + "output": 128000 + } + }, + "gpt-5.6-terra": { + "name": "gpt-5.6-terra", + "attachment": true, + "modalities": { + "input": ["text", "image"], + "output": ["text"] + }, + "tool_call": true, + "reasoning": true, + "limit": { + "context": 272000, + "output": 128000 + } + }, + "gpt-5.6-luna": { + "name": "gpt-5.6-luna", + "attachment": true, + "modalities": { + "input": ["text", "image"], + "output": ["text"] + }, + "tool_call": true, + "reasoning": true, + "limit": { + "context": 272000, + "output": 128000 + } + }, + "gpt-5.5": { + "name": "gpt-5.5", + "attachment": true, + "modalities": { + "input": ["text", "image"], + "output": ["text"] + }, + "tool_call": true, + "reasoning": true, + "limit": { + "context": 272000, + "output": 128000 + } + }, + "gpt-5.4": { + "name": "gpt-5.4", + "attachment": true, + "modalities": { + "input": ["text", "image"], + "output": ["text"] + }, + "tool_call": true, + "reasoning": true, + "limit": { + "context": 272000, + "output": 128000 + } + }, + "gpt-5.4-mini": { + "name": "gpt-5.4-mini", + "attachment": true, + "modalities": { + "input": ["text", "image"], + "output": ["text"] + }, + "tool_call": true, + "reasoning": true, + "limit": { + "context": 272000, + "output": 128000 + } + } + } + } } }