Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/skills/coc-knowledge/references/dashboard-spa.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,44 @@ unmounts the embed, and renders the standard admin card content.
Each tool's internal sub-tab/hash scheme (e.g. `#skills/installed`,
`#logs?sessionId=…`) is unchanged.

### Remote-first shell (experimental)

An optional two-row navigation mode gated by `useRemoteShellEnabled()`
(`hooks/feature-flags/useRemoteShellEnabled.ts`), which reads the live
`features.remoteShell` admin flag (runtime flag `remoteShellEnabled`,
`isRemoteShellEnabled()` in `utils/config.ts`). It is a **global admin setting**
toggled in **Admin → Configure → Features → Remote-first shell**
(`toggle-remote-shell-enabled`), defined once in `ADMIN_SETTING_DEFINITIONS`.
Disabled by default; desktop-only; takes effect on reload.

When on, the desktop top nav switches from per-clone repo tabs to a remote-first
model built on `features/remote-shell/`:
- **Row 1 `RemoteTopBar`** replaces `RepoTabStrip` inside `TopBar`. It renders one
tab per remote (origin) via `groupReposByRemote`, with a color dot, clone-count
chip, aggregate running pulse, and summed unseen badge. Selecting a remote picks
its last-used clone (else the first). Aggregation comes from `summarizeRemote` /
`computeCloneStatusMap` in `shellModel.ts`. A trailing `+` button
(`remote-add-btn`) opens an add menu — Add workspace folder (`AddFolderDialog`),
Add specific repository (`AddRepoDialog`), Clone repository (`CloneRepoDialog`) —
the single top-level add action (not duplicated per-origin).
- **Row 2 `RemoteSubBar`** renders above a `chromeless` `RepoDetail` in `ReposView`
and replaces RepoDetail's own header. `partitionShellTabs` splits tabs into
remote-scoped (Work Items, Pull Requests — always shown left) and clone-scoped
(everything else). A clone-switcher popover (lists the remote's clones only) sits
between them, then the clone tabs, then compact Ask/Queue targeting the active
clone. Clone tabs use **responsive overflow**: a hidden measurement mirror plus a
`ResizeObserver` feed `computeVisibleTabKeys`, which shows every tab that fits and
collapses the tail into a `…` menu (always keeping the active tab visible).

The sub-tab taxonomy and feature-flag/git/layout gating live in
`features/repo-detail/repoSubTabs.ts` (`SUB_TABS`, `VISIBLE_SUB_TABS`,
`TAB_GROUP_INDEX`, `computeVisibleSubTabs`), shared by both `RepoDetail` and the
shell so the two stay behaviorally identical. Selection/routing reuse
`buildRepoSubTabSuffix` via `useShellNavigation`. `SHOW_WIKI_TAB` / `SHOW_MEMORY_TAB`
live in a dedicated lightweight `navFlags.ts` (read by `repoSubTabs.ts`; re-exported
from `TopBar` for `BottomNav`/`Router`) — kept out of the heavily-mocked
`featureFlags.ts` so partial test mocks of it don't break on the missing export.

## Onboarding

- `WelcomeTour`: 5-step full-screen modal (Welcome/Modes/Queue/Multi-repo/Servers)
Expand Down
16 changes: 1 addition & 15 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,6 @@ npm workspaces monorepo with one frozen VS Code extension and published Node pac

For anything touching CoC, forge, deep-wiki, coc-client, the dashboard SPA, REST API, workflow engine, memory system, LLM tools, process store, admin config, MCP settings, Ralph, loops, EnDev, the Windows service, monorepo layout, build/test/release flow, or repo conventions — **load `.github/skills/coc-knowledge/SKILL.md` and read the relevant `references/*.md` files** before responding or editing.

Quick-start pointers (full detail lives in the skill):

- **Monorepo, build, test, changesets release** → [monorepo.md](.github/skills/coc-knowledge/references/monorepo.md)
- **CoC server module layout / executors / startup** → [server-architecture.md](.github/skills/coc-knowledge/references/server-architecture.md)
- **Admin config field registry + admin UI styling** → [admin-config.md](.github/skills/coc-knowledge/references/admin-config.md)
- **Workspace MCP merge & allow-list** → [mcp-settings.md](.github/skills/coc-knowledge/references/mcp-settings.md)
- **EnDev xDPU eligibility & skill surfacing** → [endev.md](.github/skills/coc-knowledge/references/endev.md)
- **Windows service (`Manage-CoCService.ps1`)** → [coc-service.md](.github/skills/coc-knowledge/references/coc-service.md)
- **Ralph iterative sessions + promote endpoint** → [ralph.md](.github/skills/coc-knowledge/references/ralph.md)
- **Recurring loops + wakeups + circuit breakers** → [loops.md](.github/skills/coc-knowledge/references/loops.md)
- **Deep Wiki six-phase pipeline** → [deep-wiki.md](.github/skills/coc-knowledge/references/deep-wiki.md)
- **REST API catalog** → [rest-api.md](.github/skills/coc-knowledge/references/rest-api.md)
- **Notes Git sync engine** → [sync.md](.github/skills/coc-knowledge/references/sync.md)
- **SDK wrapper, Codex support, provider registry** → [sdk-wrapper.md](.github/skills/coc-knowledge/references/sdk-wrapper.md)

## Hard Invariants (apply even before reading the skill)

- **Multi-repo:** every feature must support multiple workspaces.
Expand All @@ -41,3 +26,4 @@ Quick-start pointers (full detail lives in the skill):
- **No SDK session caching:** `coc-agent-sdk` and above must never add `sendFollowUp` or keep-alive/session caches.
- **Model resolution order:** `task.config.model` > `PerRepoPreferences.defaultModels[mode]` > `defaultModel` > CLI default.
- **Node.js ≥ 24** for every package (`engines.node`).
- **Never switch branches:** AI must NEVER run `git checkout`, `git switch`, or any command that changes the current branch. Always work on the current branch as-is.
1 change: 1 addition & 0 deletions packages/coc-client/src/contracts/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ export interface RuntimeDashboardConfig {
commitChatLensDormantMode: 'ghost' | 'pill';
effortLevelsEnabled: boolean;
nativeCliSessionsEnabled: boolean;
remoteShellEnabled: boolean;
};
hostname?: string;
bindAddress?: string;
Expand Down
5 changes: 5 additions & 0 deletions packages/coc/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ export interface CLIConfig {
ralphMultiAgentGrill?: boolean;
/** Read-only native Copilot/Codex/Claude CLI sessions tab. Disabled by default. */
nativeCliSessions?: boolean;
/** Remote-first two-row dashboard shell (one tab per remote). Disabled by default. */
remoteShell?: boolean;
};
/** Memory promotion configuration */
memoryPromotion?: {
Expand Down Expand Up @@ -542,6 +544,8 @@ export interface ResolvedCLIConfig {
ralphMultiAgentGrill: boolean;
/** Read-only native Copilot/Codex/Claude CLI sessions tab. Disabled by default. */
nativeCliSessions: boolean;
/** Remote-first two-row dashboard shell (one tab per remote). Disabled by default. */
remoteShell: boolean;
};
/** Memory promotion configuration */
memoryPromotion: {
Expand Down Expand Up @@ -776,6 +780,7 @@ export const DEFAULT_CONFIG: ResolvedCLIConfig = {
autoAgentProviderRouting: false,
ralphMultiAgentGrill: false,
nativeCliSessions: false,
remoteShell: false,
},
memoryPromotion: {
batchSize: 50,
Expand Down
8 changes: 8 additions & 0 deletions packages/coc/src/config/admin-setting-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,14 @@ export const ADMIN_SETTING_DEFINITIONS: readonly AdminSettingDefinition[] = [
testId: 'toggle-native-cli-sessions-enabled',
},
}),
bool({
key: 'features.remoteShell', default: false, runtime: 'live', runtimeFlag: 'remoteShellEnabled',
ui: {
group: 'dashboard', order: 65, label: 'Remote-first shell', badge: 'experimental',
hint: 'Replace per-clone repo tabs with a remote-first two-row top bar: one tab per git remote, a clone switcher, and remote/clone-scoped sub-tabs. Desktop only. Disabled by default.',
testId: 'toggle-remote-shell-enabled',
},
}),
bool({
key: 'features.ralphMultiAgentGrill', default: false, runtime: 'live', runtimeFlag: 'ralphMultiAgentGrillEnabled',
ui: {
Expand Down
48 changes: 17 additions & 31 deletions packages/coc/src/server/executors/prompt-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Cross-platform compatible (Linux/Mac/Windows).
*/

import type { Tool } from '@plusplusoneplusplus/coc-agent-sdk';
import type {
AutoFolderContext,
ConversationTurn,
Expand All @@ -16,7 +17,6 @@ import type {
SendMessageOptions,
SystemMessageConfig,
} from '@plusplusoneplusplus/forge';
import type { Tool } from '@plusplusoneplusplus/coc-agent-sdk';
import {
READ_ONLY_SYSTEM_MESSAGE,
buildAutoFolderLocationBlock,
Expand All @@ -27,14 +27,21 @@ import {
} from '@plusplusoneplusplus/forge';
import * as fs from 'fs';
import * as path from 'path';
import { createSearchConversationsTool } from '../llm-tools/search-conversations-tool';
import { createGetConversationTool } from '../llm-tools/get-conversation-tool';
import { createSuggestFollowUpsTool } from '../llm-tools/suggest-follow-ups-tool';
import { createAskUserTool } from '../llm-tools/ask-user-tool';
import { CONFIG_FILE_NAME, resolveConfig } from '../../config';
import type { AskUserAnswerInput, AskUserAnswerValue, AskUserToolDeps } from '../llm-tools/ask-user-tool';
import { createAskUserTool } from '../llm-tools/ask-user-tool';
import { createCanvasTools } from '../llm-tools/canvas-tools';
import { createCreateUpdateWorkItemTool, type BroadcastWorkItemFn, type CreateUpdateWorkItemToolDeps } from '../llm-tools/create-update-work-item-tool';
import { createExcalidrawTools } from '../llm-tools/excalidraw-tools';
import { createGetConversationTool } from '../llm-tools/get-conversation-tool';
import { createGetWorkItemTool } from '../llm-tools/get-work-item-tool';
import type { ChatMode, ChatPayload, DreamRunPayload, PrClassificationPayload, RunScriptPayload } from '../tasks/task-types';
import { filterDisabledLlmTools } from '../llm-tools/llm-tool-registry';
import type { LoopToolDeps } from '../llm-tools/loop-tools';
import { createCancelLoopTool, createCreateLoopTool, createListLoopsTool, createScheduleWakeupTool } from '../llm-tools/loop-tools';
import { createSearchConversationsTool } from '../llm-tools/search-conversations-tool';
import { createSuggestFollowUpsTool } from '../llm-tools/suggest-follow-ups-tool';
import { createTavilyWebSearchTool } from '../llm-tools/tavily-web-search-tool';
import type { ChatMode, ChatPayload, DreamRunPayload, ForEachGenerationContext, MapReduceGenerationContext, PrClassificationPayload, RunScriptPayload } from '../tasks/task-types';
import {
hasCommitChatContext,
hasPullRequestChatContext,
Expand All @@ -48,14 +55,6 @@ import {
normalizeChatMode,
resolveInstructionMode,
} from '../tasks/task-types';
import type { ForEachGenerationContext, MapReduceGenerationContext } from '../tasks/task-types';
import { createTavilyWebSearchTool } from '../llm-tools/tavily-web-search-tool';
import { createExcalidrawTools } from '../llm-tools/excalidraw-tools';
import { createCanvasTools } from '../llm-tools/canvas-tools';
import { resolveConfig, CONFIG_FILE_NAME } from '../../config';
import { filterDisabledLlmTools } from '../llm-tools/llm-tool-registry';
import { createScheduleWakeupTool, createCreateLoopTool, createCancelLoopTool, createListLoopsTool } from '../llm-tools/loop-tools';
import type { LoopToolDeps } from '../llm-tools/loop-tools';


// ============================================================================
Expand Down Expand Up @@ -476,11 +475,8 @@ export function buildSearchConversationsAddon(
currentProcessId,
});
const { tool: getTool } = createGetConversationTool({ store, workspaceId });
const suffix =
'\n\nconversation-history tools: `search_conversations` (keyword search, or no query + since/until to list recent sessions) ' +
'and `get_conversation` (full transcript by processId). Use when the user references past discussions.';

return { tools: [searchTool, getTool], suffix };
return { tools: [searchTool, getTool], suffix: '' };
}

// ============================================================================
Expand Down Expand Up @@ -516,7 +512,7 @@ export function buildAskUserAddon(
answerQuestion: () => false,
skipQuestion: () => false,
answerQuestions: () => false,
cancelAll: () => {},
cancelAll: () => { },
hasPending: () => false,
};
}
Expand Down Expand Up @@ -632,12 +628,7 @@ export function buildScheduleWakeupAddon(
}

const { tool } = createScheduleWakeupTool(deps);
const suffix =
'\n\nYou have access to the `scheduleWakeup` tool. ' +
'Use it to schedule a one-shot delayed follow-up message into the current conversation. ' +
'Specify a delay like "30s", "5m", or "1h". Minimum delay is 1 second.';

return { tools: [tool], suffix };
return { tools: [tool], suffix: '' };
}

// ============================================================================
Expand All @@ -655,12 +646,7 @@ export function buildLoopToolsAddon(
const { tool: cancelTool } = createCancelLoopTool(deps);
const { tool: listTool } = createListLoopsTool(deps);

const suffix =
'\n\nLoop management tools (`createLoop`, `cancelLoop`, `listLoops`) are active via the /loop skill. ' +
'When a message starts with an interval + task (e.g. "1m check status"), treat it as a fixed-interval ' +
'loop: perform the task now, then call `createLoop`. Do not use `scheduleWakeup` for this pattern.';

return { tools: [createTool, cancelTool, listTool], suffix };
return { tools: [createTool, cancelTool, listTool], suffix: '' };
}

// ============================================================================
Expand Down
Loading
Loading