Skip to content

Commit 47f84c1

Browse files
chore: update CHANGELOG for v1.3.39 release with new features and fixes
1 parent b7d5e22 commit 47f84c1

6 files changed

Lines changed: 191 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,29 @@ Versioning: [Semantic Versioning](https://semver.org/).
66

77
For releases before v1.3.35, see [GitHub Releases](https://github.com/VladoIvankovic/Codeep/releases).
88

9+
## [1.3.39] — 2026-05-06
10+
11+
### Added
12+
- **CLI sessions surfaced in Zed welcome message** — when you open a chat in
13+
Zed, Codeep now lists the most recent saved sessions for that workspace
14+
with one-line load instructions. Solves the discoverability gap where
15+
users couldn't find their CLI sessions in Zed's sidebar (Zed only lists
16+
sessions it created itself; CLI ones live in the hidden "Import Threads"
17+
modal).
18+
- **README "Loading CLI sessions in Zed" section** documenting both the
19+
in-chat (`/sessions`, `/session load <name>`) and the import-modal paths.
20+
21+
### Fixed
22+
- **`available_commands_update` not sent on `session/load` and `session/resume`**
23+
— the slash command popup (`/`) stayed empty after a panel reload because
24+
Zed registers commands only when the agent emits the notification. Codeep
25+
was emitting it only on `session/new`. Now also sent on load and resume.
26+
27+
### Internal
28+
- Added `npm run release` wrapper script — single command bumps version,
29+
verifies CHANGELOG section, runs tests, commits, tags, and pushes. See
30+
`scripts/release.js`.
31+
932
## [1.3.38] — 2026-05-05
1033

1134
### Added

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,12 +959,29 @@ Codeep advertises the following [ACP](https://agentclientprotocol.com) capabilit
959959

960960
- **`promptCapabilities.image`** — paste/drag images into chat for vision analysis.
961961
- **`promptCapabilities.embeddedContext`** — drag a file or pin a code selection into the chat and the actual file content is injected into the prompt (resource & resource_link blocks, 200 KB cap per file).
962-
- **`sessionCapabilities.list`**recent sessions appear in Zed's session picker.
962+
- **`sessionCapabilities.list`**exposes saved CLI sessions to ACP clients.
963963
- **`sessionCapabilities.resume`** — instant reconnect on panel reload without replaying history.
964964
- **`loadSession`** — restore a previous session by id.
965965

966966
Codeep also reads `clientCapabilities.terminal` from the client and routes shell commands through the editor's terminal when supported (so you see them in Zed's terminal panel), falling back to local execution otherwise.
967967

968+
### Loading CLI sessions in Zed
969+
970+
Zed's left sidebar shows only sessions Zed itself created (one per "New Thread") — it does **not** auto-list sessions you saved from the CLI or from a previous Zed window. Two ways to access those:
971+
972+
**Inside the chat (recommended):**
973+
974+
```
975+
/sessions # show all saved sessions for this workspace
976+
/session load <name> # restore one
977+
```
978+
979+
When you open a fresh chat in Zed, Codeep also shows you the most recent CLI sessions for that project right in the welcome message, so you can switch with one command.
980+
981+
**Via Zed's import modal:**
982+
983+
Open Zed's command palette (`Cmd+Shift+P`) and search for **"Import Threads"**. Codeep's saved sessions appear there as an importable list — once imported they show up in Zed's regular sidebar.
984+
968985
## VS Code Extension
969986

970987
Install **Codeep** from the VS Code marketplace. The extension is a thin UI around the CLI — all credentials and sessions live in the CLI's config (`~/.config/codeep/config.json`), so keys set anywhere are visible everywhere.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"build:binary": "npm run build && pkg dist/renderer/main.js --targets node18-macos-arm64,node18-macos-x64,node18-linux-x64 --output bin/codeep",
1818
"test": "vitest run",
1919
"test:watch": "vitest",
20-
"test:coverage": "vitest run --coverage"
20+
"test:coverage": "vitest run --coverage",
21+
"release": "node scripts/release.js"
2122
},
2223
"repository": {
2324
"type": "git",

scripts/release.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Release wrapper. Bumps version, commits, tags, pushes — and verifies a
4+
* CHANGELOG entry exists for the new version *before* doing any of that, so
5+
* the GitHub Actions workflow can use it as the release body.
6+
*
7+
* Usage:
8+
* npm run release patch # 1.3.38 → 1.3.39
9+
* npm run release minor # 1.3.38 → 1.4.0
10+
* npm run release major # 1.3.38 → 2.0.0
11+
* npm run release 1.4.2 # explicit version
12+
*/
13+
14+
import { execSync } from 'node:child_process';
15+
import { readFileSync } from 'node:fs';
16+
import { fileURLToPath } from 'node:url';
17+
import { dirname, join } from 'node:path';
18+
19+
const __dirname = dirname(fileURLToPath(import.meta.url));
20+
const repoRoot = join(__dirname, '..');
21+
22+
const arg = process.argv[2];
23+
if (!arg) {
24+
console.error('Usage: npm run release <patch|minor|major|x.y.z>');
25+
process.exit(1);
26+
}
27+
28+
// ── 1. Working tree must be clean ──────────────────────────────────────────
29+
const dirty = execSync('git status --porcelain', { cwd: repoRoot, encoding: 'utf8' }).trim();
30+
if (dirty) {
31+
console.error('❌ Working tree has uncommitted changes:\n');
32+
console.error(dirty);
33+
console.error('\nCommit or stash before releasing.');
34+
process.exit(1);
35+
}
36+
37+
// ── 2. Compute next version ────────────────────────────────────────────────
38+
const pkg = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf8'));
39+
const current = pkg.version;
40+
41+
function bump(version, kind) {
42+
const m = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
43+
if (!m) throw new Error(`Cannot parse current version: ${version}`);
44+
let [, major, minor, patch] = m.map(Number);
45+
if (kind === 'major') { major++; minor = 0; patch = 0; }
46+
else if (kind === 'minor') { minor++; patch = 0; }
47+
else if (kind === 'patch') { patch++; }
48+
else throw new Error(`Unknown bump kind: ${kind}`);
49+
return `${major}.${minor}.${patch}`;
50+
}
51+
52+
let next;
53+
if (/^\d+\.\d+\.\d+$/.test(arg)) {
54+
next = arg;
55+
} else if (['patch', 'minor', 'major'].includes(arg)) {
56+
next = bump(current, arg);
57+
} else {
58+
console.error(`❌ Invalid version arg: ${arg} (expected patch|minor|major|x.y.z)`);
59+
process.exit(1);
60+
}
61+
62+
console.log(`Releasing ${current}${next}\n`);
63+
64+
// ── 3. Verify CHANGELOG has section for the new version ────────────────────
65+
const changelog = readFileSync(join(repoRoot, 'CHANGELOG.md'), 'utf8');
66+
const sectionPattern = new RegExp(`^## \\[${next.replace(/\./g, '\\.')}\\]`, 'm');
67+
if (!sectionPattern.test(changelog)) {
68+
const today = new Date().toISOString().slice(0, 10);
69+
console.error(`❌ CHANGELOG.md is missing a section for v${next}.\n`);
70+
console.error(`Add this near the top of CHANGELOG.md (above the previous version):\n`);
71+
console.error(` ## [${next}] — ${today}\n`);
72+
console.error(` ### Added`);
73+
console.error(` - …\n`);
74+
console.error(` ### Fixed`);
75+
console.error(` - …\n`);
76+
console.error(`Then commit it and re-run the release.`);
77+
process.exit(1);
78+
}
79+
console.log(`✓ CHANGELOG.md has section for v${next}`);
80+
81+
// ── 4. Run tests ───────────────────────────────────────────────────────────
82+
console.log('\nRunning tests…');
83+
try {
84+
execSync('npm test', { cwd: repoRoot, stdio: 'inherit' });
85+
} catch {
86+
console.error('\n❌ Tests failed. Aborting release.');
87+
process.exit(1);
88+
}
89+
90+
// ── 5. Bump version (creates commit + tag) ─────────────────────────────────
91+
// `npm version <x.y.z>` mutates package.json, commits with message "x.y.z",
92+
// and tags as v<x.y.z>. We pass the explicit version so npm doesn't compute it.
93+
console.log(`\nBumping package.json and tagging…`);
94+
execSync(`npm version ${next} -m "%s"`, { cwd: repoRoot, stdio: 'inherit' });
95+
96+
// ── 6. Push commit and tag ─────────────────────────────────────────────────
97+
console.log('\nPushing commit…');
98+
execSync('git push', { cwd: repoRoot, stdio: 'inherit' });
99+
console.log('Pushing tag…');
100+
execSync(`git push origin v${next}`, { cwd: repoRoot, stdio: 'inherit' });
101+
102+
console.log(`\n✅ v${next} released.`);
103+
console.log(`\nWatch the workflow:`);
104+
console.log(` gh run watch -R VladoIvankovic/Codeep`);
105+
console.log(`Or: https://github.com/VladoIvankovic/Codeep/actions`);

src/acp/commands.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ export function initWorkspace(workspaceRoot: string, fresh = false): {
122122
'Type `/help` to see available commands.',
123123
];
124124

125+
// Surface CLI sessions so Zed users discover them without having to know
126+
// about the hidden "Import Threads" modal. Show up to 5 most recent.
127+
if (sessions.length > 1 || (sessions.length === 1 && sessions[0].name !== codeepSessionId)) {
128+
const others = sessions
129+
.filter(s => s.name !== codeepSessionId)
130+
.slice(0, 5);
131+
if (others.length > 0) {
132+
lines.push('', '**Other sessions in this project:**');
133+
for (const s of others) {
134+
const label = s.title && s.title !== s.name ? `${s.title} (\`${s.name}\`)` : `\`${s.name}\``;
135+
lines.push(`- ${label}${s.messageCount} messages`);
136+
}
137+
lines.push('', `Type \`/sessions\` for the full list, or \`/session load <name>\` to switch.`);
138+
}
139+
}
140+
125141
if (history.length > 0) {
126142
lines.push('', '---', '');
127143
lines.push(...formatSessionPreviewLines(history));

src/acp/server.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,17 @@ export function startAcpServer(): Promise<void> {
520520
};
521521
transport.respond(msg.id, result);
522522

523+
// Re-advertise slash commands so `/` autocomplete works after a reload.
524+
// Zed only registers commands when AvailableCommandsUpdated fires; without
525+
// this the slash menu stays empty after session/load.
526+
transport.notify('session/update', {
527+
sessionId: acpSessionId,
528+
update: {
529+
sessionUpdate: 'available_commands_update',
530+
availableCommands: AVAILABLE_COMMANDS,
531+
},
532+
});
533+
523534
// Send title immediately so Zed "Recent" panel shows something useful
524535
sendSessionTitle(params.sessionId, history, pathBasename(params.cwd));
525536

@@ -541,6 +552,20 @@ export function startAcpServer(): Promise<void> {
541552

542553
function handleSessionResume(msg: JsonRpcRequest): void {
543554
const params = msg.params as SessionResumeParams;
555+
556+
// Helper — re-advertise commands so `/` autocomplete works after a panel
557+
// reload. Without this the slash menu stays empty until a new session is
558+
// created. Same notification shape as session/new.
559+
const advertiseCommands = (sessionId: string) => {
560+
transport.notify('session/update', {
561+
sessionId,
562+
update: {
563+
sessionUpdate: 'available_commands_update',
564+
availableCommands: AVAILABLE_COMMANDS,
565+
},
566+
});
567+
};
568+
544569
const existing = sessions.get(params.sessionId);
545570
if (existing) {
546571
existing.workspaceRoot = params.cwd;
@@ -550,6 +575,7 @@ export function startAcpServer(): Promise<void> {
550575
configOptions: buildConfigOptions(),
551576
};
552577
transport.respond(msg.id, result);
578+
advertiseCommands(params.sessionId);
553579
return;
554580
}
555581

@@ -574,6 +600,7 @@ export function startAcpServer(): Promise<void> {
574600
configOptions: buildConfigOptions(),
575601
};
576602
transport.respond(msg.id, result);
603+
advertiseCommands(acpSessionId);
577604
}
578605

579606
// ── session/set_mode ────────────────────────────────────────────────────────

0 commit comments

Comments
 (0)