diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3ed1f94d77..7e7eb9697e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -201,15 +201,13 @@ jobs: if: steps.should-build.outputs.skip != 'true' && env.PUSH != 'true' && matrix.image == 'workspace' && matrix.platform == 'linux/amd64' run: | docker run --rm memoh-ci-workspace:debian sh -eux -c ' - grep -q "\"contract_version\": 2" /opt/memoh/workspace-contract.json + grep -q "\"contract_version\": 3" /opt/memoh/workspace-contract.json ldd --version >/dev/null node --version python3 --version uv --version test -x /opt/memoh/toolkit/bin/codex - test -x /opt/memoh/toolkit/bin/codex-acp - test -x /opt/memoh/toolkit/bin/claude-agent-acp - test -x /opt/memoh/toolkit/bin/hermes-acp + test -x /opt/memoh/toolkit/bin/claude test -x /opt/memoh/toolkit/display/bin/a11y-cli sh -n /opt/memoh/scripts/display-prepare.sh sh -n /opt/memoh/scripts/display-apply-style.sh diff --git a/AGENTS.md b/AGENTS.md index ac9596d828..61a48acd2e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,9 +81,14 @@ Memoh/ │ │ ├── decision/ # User input, tool approval, and stable user-facing feedback │ │ ├── event/ # Agent events and transport payload vocabulary │ │ ├── runtime/ # Runtime implementations -│ │ │ ├── acp/ # ACP pool, client process manager, and profiles +│ │ │ ├── acp/ # ACP pool, client process manager, and the generic custom-agent profile +│ │ │ ├── claudecode/ # Claude Code direct runtime (external.Driver) +│ │ │ ├── codex/ # Codex direct runtime (external.Driver) +│ │ │ ├── external/ # Neutral Driver port between the application layer and external runtimes │ │ │ ├── native/ # Twilight AI native runtime, prompts, streaming, hooks, and guards -│ │ │ └── session/ # Per-thread runtime state and control +│ │ │ ├── agentstate/ # External Agent session publication heads and state storage port +│ │ │ ├── session/ # Per-thread runtime state and control +│ │ │ └── toolmount/ # Memoh tool gateway mounts for direct runtimes │ │ ├── sessionmode/ # Session mode resolution │ │ ├── tool/ # Native tool providers (package name remains tools) │ │ ├── message.go # Send message tool @@ -387,7 +392,7 @@ PostgreSQL migrations live in `db/postgres/migrations/`: The codebase has grown beyond the original agent/channel/container core. When working near these areas, read the local `AGENTS.md` and treat the corresponding `internal/` package as the source of truth; do not guess tool or schema details. -- **ACP (`internal/agent/runtime/acp/`)** — runtime pool, client process manager, profiles, and OAuth integration for external ACP agents such as Claude Code and Codex. Stable user-facing ACP errors live in `internal/agent/decision/feedback/`. +- **External coding-agent runtimes (`internal/agent/runtime/external/`, `codex/`, `claudecode/`)** — the neutral `external.Driver` port plus the direct Codex and Claude Code runtimes (pinned protocol assets, device-code/OAuth login, native thread resume/fork, Memoh tool gateway mounts via `toolmount/`). **ACP (`internal/agent/runtime/acp/`)** is the generic channel for custom user-supplied ACP agents (single generic profile with a managed launch command), folded into the same driver port. Stable user-facing runtime errors live in `internal/agent/decision/feedback/`. - **Skill Packages (`internal/skillpackages/`, `internal/supermarket/`)** — Supermarket Package discovery and installation state. Installed Packages expand into immutable Registry Skills in the selected workspace target. - **User input / `ask_user` (`internal/agent/decision/input/`)** — lets the in-process agent ask the user a question mid-conversation and wait for an answer. - **Bot backup / import / export (`internal/botbackup/`)** — archive-based bot portability with preview and merge/replace/skip strategies. diff --git a/apps/web/src/components/session-select/options.ts b/apps/web/src/components/session-select/options.ts index b71c19b150..1d9441ec5d 100644 --- a/apps/web/src/components/session-select/options.ts +++ b/apps/web/src/components/session-select/options.ts @@ -2,8 +2,9 @@ import type { SessionSession } from '@memohai/sdk' import type { SearchableSelectOption } from '@/components/searchable-select-popover/index.vue' import type { BotWorkdir } from '@/composables/api/useWorkdirs' import type { SessionKind } from './session-kind-icon.vue' -import { acpAgentDisplayName, normalizeACPAgentID } from '@/utils/acp' -import { normalizedRuntimeType, normalizedSessionMode } from '@/store/chat-list.utils' +import { acpAgentDisplayName } from '@/utils/acp' +import { sessionAgentProvider } from '@/utils/bot-agent' +import { isAgentRuntimeType, normalizedRuntimeType, normalizedSessionMode } from '@/store/chat-list.utils' // The per-row mark the picker paints beside a session title. export interface SessionMark { @@ -29,8 +30,11 @@ export function sessionTitle(session: SessionSession, labels: SessionSelectLabel } export function sessionMark(session: SessionSession, labels: SessionSelectLabels): SessionMark { - const agentId = normalizeACPAgentID( - session.runtime_metadata?.acp_agent_id ?? session.metadata?.acp_agent_id, + const runtimeType = normalizedRuntimeType(session) + const agentId = sessionAgentProvider( + runtimeType, + session.runtime_metadata, + session.metadata, ) // Schedule wins over the ACP mark here, unlike the sidebar row: this picker // exists to tell schedule-owned sessions apart from ordinary chats, and a @@ -38,7 +42,7 @@ export function sessionMark(session: SessionSession, labels: SessionSelectLabels if (normalizedSessionMode(session) === 'schedule') { return { kind: 'schedule', agentId, label: labels.schedule } } - if (normalizedRuntimeType(session) === 'acp_agent') { + if (isAgentRuntimeType(runtimeType)) { return { kind: 'acp', agentId, label: acpAgentDisplayName(agentId, labels.agent) } } return NO_MARK diff --git a/apps/web/src/components/sidebar/session-item.vue b/apps/web/src/components/sidebar/session-item.vue index 7213a94fe7..1200b62ab9 100644 --- a/apps/web/src/components/sidebar/session-item.vue +++ b/apps/web/src/components/sidebar/session-item.vue @@ -15,17 +15,17 @@ @keydown.enter.prevent="$emit('select', session)" @keydown.space.prevent="$emit('select', session)" > -