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
51 changes: 51 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Dependabot — auto PRs for dependency updates.
# Spec: docs/DEVELOPMENT_PLAN.md §0 (engineering hygiene)
#
# We group most updates by ecosystem so we don't drown in tiny PRs. Major
# updates remain separate so they get explicit review.

version: 2
updates:
- package-ecosystem: npm
directory: '/'
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
groups:
typescript:
patterns:
- 'typescript'
- '@types/*'
- 'typescript-eslint'
update-types:
- 'minor'
- 'patch'
eslint:
patterns:
- 'eslint'
- '@eslint/*'
update-types:
- 'minor'
- 'patch'
testing:
patterns:
- 'vitest'
- '@vitest/*'
update-types:
- 'minor'
- 'patch'
react:
patterns:
- 'react'
- 'react-dom'
- '@types/react'
- '@types/react-dom'
update-types:
- 'minor'
- 'patch'

- package-ecosystem: github-actions
directory: '/'
schedule:
interval: weekly
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ concurrency:

jobs:
check:
name: Typecheck + Lint + Test
runs-on: ubuntu-latest
timeout-minutes: 15
name: Typecheck + Lint + Test (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 20

steps:
- name: Checkout
Expand All @@ -39,7 +43,10 @@ jobs:

- name: Lint
run: pnpm lint
continue-on-error: true # M0: lint 配置随 M1 完善,先不阻塞

- name: Worktree tests (gated)
run: DEEPCODE_WORKTREE_TESTS=1 pnpm -F @deepcode/core test src/worktree/
continue-on-error: true # flaky cross-platform; not yet a blocker

- name: Format check
run: pnpm format:check
Expand Down
31 changes: 29 additions & 2 deletions packages/core/skills/consolidate-memory/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,35 @@ description: Walk ~/.deepcode/memory/, merge duplicates, prune the index.

# consolidate-memory

(M4 baseline — body authored as quick guidance; can be expanded by the user via `/skill edit` or directly editing this file.)
DeepCode's `#` command appends snippets to the user's persistent memory.
Over time these accumulate duplicates and stale entries; this skill cleans
them up.

## When to invoke

The agent should invoke this skill when the user request matches the description.
- User says "consolidate my memory", "clean up notes", "dedupe memory".
- User notices the same hint surfacing twice in successive sessions.

## Process

1. **Read all files** under `~/.deepcode/memory/` (one MD per topic).
2. **Group by similarity** — entries on the same topic / same fact.
3. **Merge duplicates** — keep the most recent, clearest phrasing.
4. **Prune stale** — if an entry references a removed file/dir or an
outdated CLI flag, suggest deletion (don't auto-delete).
5. **Update the index** — `~/.deepcode/memory/MEMORY.md` should still
reference every remaining file. Drop dead links.

## Anti-patterns

- Don't auto-delete anything — always show the proposed delete list and
wait for user approval.
- Don't merge entries that LOOK similar but encode different decisions
(e.g. "use pnpm" + "use yarn" — they aren't duplicates, they're a
conflict to flag).

## Output

A single proposed-changes block with each action: KEEP / MERGE → / DELETE / EDIT,
and a final summary `N files; M consolidated; K to delete`. Then ask the
user to approve before writing.
70 changes: 68 additions & 2 deletions packages/core/skills/deepseek-api/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,74 @@ description: Help build/debug DeepSeek API usage (openai-compatible).

# deepseek-api

(M4 baseline — body authored as quick guidance; can be expanded by the user via `/skill edit` or directly editing this file.)
DeepSeek's HTTP API is OpenAI-Compatible. Use the same patterns; just
swap the base URL and key.

## When to invoke

The agent should invoke this skill when the user request matches the description.
- User asks "how do I call DeepSeek", "debug my chat completion call",
"stream tool calls from DeepSeek", etc.

## Basics

- **Base URL**: `https://api.deepseek.com/v1`
- **Auth**: `Authorization: Bearer <DEEPSEEK_API_KEY>` (or set via env)
- **SDK**: any OpenAI-compatible SDK works; e.g. `openai` npm with
`baseURL: 'https://api.deepseek.com/v1'`.

## Models

| Model | Alias | Strengths |
| ------------------- | ------------------ | -------------------------------------- |
| `deepseek-chat` | → `deepseek-v4-flash` | Fast general chat; tool use |
| `deepseek-reasoner` | → `deepseek-v4-pro` | Multi-step reasoning; emits `reasoning_content` |

Set via the standard `model` field.

## Streaming

Pass `stream: true`. SSE chunks come back as `data: {...}\n\n`. Each
chunk has `choices[0].delta.content` for text deltas, and
`choices[0].delta.tool_calls[]` for partial tool calls.

`deepseek-reasoner` ALSO emits `choices[0].delta.reasoning_content` —
the thinking trace. UI should render this in a collapsible panel.

## Tool calling

Standard OpenAI shape:

```js
const r = await client.chat.completions.create({
model: 'deepseek-chat',
messages: [...],
tools: [{
type: 'function',
function: {
name: 'Read',
description: '...',
parameters: { type: 'object', properties: {...}, required: [...] }
}
}],
tool_choice: 'auto',
});
```

Response includes `choices[0].message.tool_calls[]` when the model
chose to call a tool. Loop: send back `role: 'tool'` messages with the
`tool_call_id`, get next assistant message, repeat until no tool calls.

## Pricing (rough; verify on dashboard)

| Tier | Input | Output | Reasoning |
| ------------ | ------ | ------ | --------- |
| deepseek-chat | 1¥/M | 2¥/M | — |
| deepseek-reasoner | 1¥/M | 16¥/M | 4¥/M |

## Common pitfalls

- **`temperature: 1.0` makes tool calls flaky** — drop to 0.3 for tool use.
- **Streaming + tool_use** — must accumulate tool args across chunks; the
args field comes in pieces.
- **`reasoning_content` is not in messages** — it's separate; don't try
to echo it back as a content block to the model.
42 changes: 40 additions & 2 deletions packages/core/skills/fewer-permission-prompts/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,46 @@ description: Scan transcripts, propose .deepcode/settings.json allow rules.

# fewer-permission-prompts

(M4 baseline — body authored as quick guidance; can be expanded by the user via `/skill edit` or directly editing this file.)
The user keeps hitting the same approval prompt? Auto-generate a focused
`allow` rule from recent transcripts so they stop being asked.

## When to invoke

The agent should invoke this skill when the user request matches the description.
- User says "stop asking", "auto-approve npm test", "I keep clicking yes".
- User explicitly runs `/fewer-permission-prompts`.

## Process

1. **Scan recent sessions** — `~/.deepcode/sessions/*.jsonl`, last 7 days.
2. **Collect approved tool calls** — every PreToolUse where the user said
yes. Bin by tool + leading arg (e.g. `Bash(npm test:*)`).
3. **Find recurring bins** — anything approved 3+ times.
4. **Propose rules** matching the existing permission rule syntax:
- `Bash(npm test:*)` for a subcommand pattern
- `Bash(npm test *)` for a prefix pattern
- `Read(<cwd>/**)` for a path glob
5. **Show the user** the proposed additions to `.deepcode/settings.json`
(project-scoped). Wait for approval before writing.

## Safety

- Never propose `Bash(*)` or `Bash(rm:*)` — those are too broad.
- Never propose rules from `bypassPermissions` mode (the user wasn't
actually being asked).
- Default to PROJECT-scoped settings (`.deepcode/settings.json`) not user-
global (`~/.deepcode/settings.json`). Users can override.

## Output

A diff-like preview:

```
.deepcode/settings.json (proposed):

permissions.allow:
+ "Bash(npm test:*)" seen 14 times, last 2 days ago
+ "Bash(git diff:*)" seen 9 times
+ "Read(./src/**)" seen 47 times

Apply? [y]es / [n]o / [e]dit
```
49 changes: 47 additions & 2 deletions packages/core/skills/keybindings-help/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,53 @@ description: Help edit ~/.deepcode/keybindings.json.

# keybindings-help

(M4 baseline — body authored as quick guidance; can be expanded by the user via `/skill edit` or directly editing this file.)
Add or modify entries in `~/.deepcode/keybindings.json`. Explain the
syntax + show what will change.

## When to invoke

The agent should invoke this skill when the user request matches the description.
- User says "bind X to Y", "add a shortcut", "enable Vim mode".
- User runs `/keybindings` and asks for a tweak.

## File schema

```json
{
"enabled": true,
"vim": false,
"bindings": [
{ "key": "ctrl+shift+t", "action": "/clear" },
{ "key": "esc esc", "action": "/rewind" },
{ "key": "g g", "action": "cursor-buffer-start", "when": "NORMAL" }
]
}
```

## Key chord syntax

- Modifiers: `ctrl`, `shift`, `alt`, `meta`.
- Separator: `+` for chord (`ctrl+a`), space for sequence (`g g`).
- The order of modifiers is normalized, so `Shift+Ctrl+A` ≡ `ctrl+shift+a`.

## Action forms

1. **Slash command** — `"/clear"`, `"/mode plan"`, etc.
2. **Literal insertion** — `"insert:hello"` inserts "hello" at cursor.
3. **Built-in action** — `cursor-line-start`, `kill-to-end`, `vim-insert-mode`, etc.

See `DEFAULT_KEYBINDINGS` in `packages/core/src/keybindings/index.ts`
for the full list.

## Vim mode

When `vim: true`, the `when` field constrains a binding to `NORMAL` /
`INSERT` / `VISUAL`. Vim defaults (i, a, v, gg, dd, yy, p, u) ship by
default; user bindings layer on top.

## Process

1. Read current file (or note it doesn't exist).
2. Validate the user's chord (must match `chord-syntax`).
3. Check for collisions with existing bindings — warn the user.
4. Show the diff, ask y/n/e.
5. Write back.
46 changes: 44 additions & 2 deletions packages/core/skills/loop/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,50 @@ description: Run a command on a recurring interval (poll CI etc.).

# loop

(M4 baseline — body authored as quick guidance; can be expanded by the user via `/skill edit` or directly editing this file.)
Drive a polling loop where the agent re-checks state at an interval —
useful for "wait until CI is green", "poll deploy status", "tail a log".

## When to invoke

The agent should invoke this skill when the user request matches the description.
- User says "watch", "poll", "every N seconds check X", "wait until Y".
- Long-running observation with a clear termination condition.

## Pattern

Use `ScheduleWakeup` (or the loop primitive in the host) with a sensible
delay:

| Watching | Delay | Why |
| ------------------------- | ------------ | ------------------------------------ |
| CI run | 60-270 s | Status changes minute-scale |
| Deploy queue | 60-180 s | Same |
| Local file change | 5-30 s | Use fs.watch instead when possible |
| Cron / external timer | 20-30 min | Don't burn cache for nothing |
| "Idle tick, no signal" | 20-30 min | Default; cap notification noise |

## Cache-aware delays

Anthropic-style prompt caches expire after ~5 min. Pick either:
- **Under 5 min**: cache stays warm (60-270 s).
- **Long fallback**: 20+ min (one cache miss buys a long wait).

Avoid 5-15 min windows — they pay the miss without amortizing.

## Termination

ALWAYS have a clear stop condition. Loop should exit when:
- The watched condition is met.
- The user issues an interrupt / says stop.
- A timeout cap is exceeded (refuse to infinite-loop).

## Output per tick

Just enough to confirm progress: `[14:32] CI status: in_progress (8/12 jobs)`.
Don't dump full logs each tick.

## Anti-patterns

- Polling every second (burns API budget; rarely needed).
- Infinite loop without a max-iterations cap.
- Polling instead of using the harness's notification mechanism — if the
runtime can wake you on the event, use that instead.
Loading
Loading