Skip to content
This repository was archived by the owner on Mar 28, 2026. It is now read-only.
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
217 changes: 217 additions & 0 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
name: Create Release

on:
push:
branches:
- development
- production

permissions:
contents: write

jobs:
create-release:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Determine release metadata
id: release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail

branch="${GITHUB_REF_NAME}"
before="${{ github.event.before }}"
current_version="$(node -p "require('./package.json').version")"

previous_version=""
if [[ "$before" != "0000000000000000000000000000000000000000" ]]; then
if git cat-file -e "${before}:package.json" 2>/dev/null; then
previous_version="$(
git show "${before}:package.json" \
| node -p "JSON.parse(require('node:fs').readFileSync(0, 'utf8')).version"
)"
fi
fi

version_changed=false
if [[ "$current_version" != "$previous_version" ]]; then
version_changed=true
fi

if [[ "$branch" == "development" ]]; then
tag="v${current_version}-dev"
previous_tag="$(
git tag --list 'v*-dev' --sort=-creatordate \
| grep -Fxv "$tag" \
| head -n 1 || true
)"
elif [[ "$branch" == "production" ]]; then
tag="v${current_version}"
previous_tag="$(
git tag --list 'v*' --sort=-creatordate \
| grep -Ev -- '-dev$' \
| grep -Fxv "$tag" \
| head -n 1 || true
)"
else
echo "release_action=skip" >> "$GITHUB_OUTPUT"
echo "Branch ${branch} is not configured for releases."
exit 0
fi

if gh release view "$tag" >/dev/null 2>&1; then
release_action="update"
else
release_action="create"
fi

if [[ "$release_action" == "create" && "$version_changed" == "true" ]]; then
echo "Package version changed; creating ${tag}."
elif [[ "$release_action" == "create" ]]; then
echo "No release exists for ${tag}; creating it."
else
echo "Release ${tag} exists; updating its notes."
fi

echo "release_action=${release_action}" >> "$GITHUB_OUTPUT"
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
echo "previous_tag=${previous_tag}" >> "$GITHUB_OUTPUT"
echo "version=${current_version}" >> "$GITHUB_OUTPUT"
echo "version_changed=${version_changed}" >> "$GITHUB_OUTPUT"

- name: Generate release notes
if: steps.release.outputs.release_action != 'skip'
shell: bash
run: |
set -euo pipefail

tag="${{ steps.release.outputs.tag }}"
previous_tag="${{ steps.release.outputs.previous_tag }}"

{
echo "## Changes"
echo

if [[ -n "$previous_tag" ]]; then
echo "Commits since ${previous_tag}:"
echo
git log "${previous_tag}..${GITHUB_SHA}" --pretty=format:'- %s (%h)'
else
echo "Commits included in this release:"
echo
git log "${GITHUB_SHA}" --pretty=format:'- %s (%h)'
fi
} > release-notes.md

if [[ ! -s release-notes.md ]]; then
printf '## Changes\n\n- No commits found.\n' > release-notes.md
fi

echo "Prepared release notes for ${tag}:"
cat release-notes.md

- name: Install dependencies
if: steps.release.outputs.release_action != 'skip'
run: npm ci

- name: Build release assets
if: steps.release.outputs.release_action != 'skip'
shell: bash
run: |
set -euo pipefail

tag="${{ steps.release.outputs.tag }}"
asset_base="buddy-${tag}"

rm -rf release-assets
mkdir -p release-assets

pack_json="$(npm pack --json --pack-destination release-assets)"
pack_file="$(
node -e 'const data = JSON.parse(process.argv[1]); process.stdout.write(data[0].filename);' \
"$pack_json"
)"

mv "release-assets/${pack_file}" "release-assets/${asset_base}.tgz"

temp_dir="$(mktemp -d)"
trap 'rm -rf "$temp_dir"' EXIT

tar -xzf "release-assets/${asset_base}.tgz" -C "$temp_dir"
(
cd "$temp_dir/package"
zip -rq "$GITHUB_WORKSPACE/release-assets/${asset_base}.zip" .
)

ls -lh release-assets

- name: Update release tag
if: steps.release.outputs.release_action != 'skip'
shell: bash
run: |
set -euo pipefail

tag="${{ steps.release.outputs.tag }}"

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

git tag -f "$tag" "${GITHUB_SHA}"
git push --force origin "refs/tags/${tag}"

- name: Create GitHub release
if: steps.release.outputs.release_action == 'create'
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail

tag="${{ steps.release.outputs.tag }}"
gh release create "$tag" \
--title "$tag" \
--verify-tag \
--notes-file release-notes.md

- name: Update GitHub release notes
if: steps.release.outputs.release_action == 'update'
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail

tag="${{ steps.release.outputs.tag }}"
gh release edit "$tag" \
--title "$tag" \
--notes-file release-notes.md

- name: Upload release assets
if: steps.release.outputs.release_action != 'skip'
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail

tag="${{ steps.release.outputs.tag }}"
asset_base="buddy-${tag}"

gh release upload "$tag" \
"release-assets/${asset_base}.tgz" \
"release-assets/${asset_base}.zip" \
--clobber
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@teichai/buddy",
"version": "0.0.2",
"version": "0.0.3",
"description": "Terminal-first AI assistant with onboarding, chat UI, and local or remote server support.",
"license": "MIT",
"type": "module",
Expand Down
17 changes: 7 additions & 10 deletions src/llm/system-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ export function buildSystemPrompt(config: BuddyConfig, channel: PromptChannel =
}

return [
`You are ${botName}, a local terminal-first AI assistant that helps the user inside a CLI application called buddy.`,
`You are ${botName}, a AI assistant that helps the user.`,
userName ? `The user's name is ${userName}.` : "The user's name has not been configured.",
"",
"Your role:",
"- Help the user think, plan, write, edit, and operate files from a local assistant interface.",
"- Help the user think, plan, write, edit, and operate the users computer in some ways.",
"- Be practical, accurate, and clear.",
"- Prefer useful action and direct answers over vague commentary.",
"",
"Your environment:",
"- You are operating in a local assistant environment, not a web chat.",
"- You are operating in a assistant environment, not a web chat.",
"- The user may expect help with files, code, configuration, and terminal-oriented tasks.",
"- You should act like a capable local assistant that can inspect and modify files through tools when those tools are available.",
"- You should act like a capable assistant that can inspect and modify files through tools when those tools are available.",
`- Your default workspace is ${workspacePath}. Unless the user asks otherwise, you should treat that as the main place to read, create, edit, and organize files.`,
"- When a file path is relative, treat it as relative to the workspace by default.",
"- If the user says 'desktop', assume they mean this assistant's own desktop/local environment by default, not the OS Desktop folder.",
Expand All @@ -51,11 +51,11 @@ export function buildSystemPrompt(config: BuddyConfig, channel: PromptChannel =
: undefined,
"- Do not claim you changed a file unless you actually used a file-writing tool successfully.",
"- If a tool is required to verify something, use the tool instead of guessing.",
"- Do not ask the user for tool permission yourself in normal conversation. Attempt the tool call directly when it is appropriate.",
"- Do not ask the user for tool permission yourself in normal conversation. Attempt the tool call directly. If it requires permission, the user will be prompted automatically.",
"- If approval is required, the runtime will handle that approval step for you.",
"- If the user asks for a path outside the workspace, still make the relevant tool call so the runtime can trigger approval instead of refusing preemptively.",
"- If the users task path is outside the workspace, still make the relevant tool call so the runtime can trigger approval instead of refusing preemptively.",
"- If a tool is blocked, denied, or fails, you will learn that from the tool response and should continue from there.",
"- If you cannot complete an action, explain exactly what is blocked.",
"- If you cannot complete an action, explain exactly what is blocked. Make sure to try everything before giving up.",
"",
"Guardrails and restrictions:",
`- Access level is currently set to ${config.restrictions.accessLevel}.`,
Expand All @@ -69,9 +69,6 @@ export function buildSystemPrompt(config: BuddyConfig, channel: PromptChannel =
"How to respond:",
"- Be concise by default, but include enough detail to be useful.",
"- Use clear, direct language and avoid filler.",
"- If the user asks for an explanation, give a structured explanation.",
"- If the user asks for help writing or editing something, provide concrete output rather than abstract advice.",
"- If there is uncertainty, say what is certain and what is uncertain.",
channel === "discord" ? "- You are replying inside Discord, so avoid tables and other non-Discord markdown." : undefined,
channel === "discord"
? "- Prefer short paragraphs, simple bullets, inline code, and fenced code blocks. Do not use markdown tables, footnotes, HTML, or other formatting that may render poorly in Discord."
Expand Down
Loading