Skip to content

Commit 0476b70

Browse files
committed
Initial release snapshot from streamlit-coco-dev
0 parents  commit 0476b70

81 files changed

Lines changed: 10054 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## Summary
2+
3+
<!-- One paragraph: what changed and why -->
4+
5+
## Type of change
6+
7+
- [ ] Bug fix
8+
- [ ] New feature
9+
- [ ] Documentation
10+
- [ ] Security fix
11+
- [ ] Refactor / tech debt
12+
13+
## Checklist
14+
15+
### Code
16+
- [ ] Tests added or updated (`tests/`)
17+
- [ ] All existing tests pass (`make test`)
18+
- [ ] No new linting errors (`make lint`)
19+
20+
### Documentation
21+
- [ ] `CHANGELOG.md` updated (under `[Unreleased]`)
22+
- [ ] `docs/features/` updated if new or changed feature
23+
- [ ] `README.md` updated if install/usage changed
24+
25+
### Security
26+
- [ ] No secrets, credentials, or PII in code or tests
27+
- [ ] No `shell=True` or unsafe subprocess calls
28+
- [ ] No new pip-audit CVEs introduced
29+
- [ ] No hardcoded Snowflake account names or database names
30+
31+
### Governance (N1+)
32+
- [ ] `docs/roadmap.md` updated if this closes a roadmap item
33+
- [ ] Issue linked (closes #NNN)
34+
- [ ] Manual golden-path checklist run when UI/feature touched (`docs/features/*/test-checklist.md`)

.github/workflows/ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ci-${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version-file: .python-version
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v3
26+
27+
- name: Install dependencies
28+
run: uv sync --extra dev
29+
30+
- name: Lint
31+
run: uv run ruff check .
32+
33+
- name: Test
34+
run: uv run pytest tests/ -v
35+
36+
- name: Security audit
37+
run: uv run pip-audit
38+
continue-on-error: true # non-blocking until baseline is clean

.github/workflows/release.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
id-token: write
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Extract CHANGELOG for this version
18+
id: changelog
19+
run: |
20+
VERSION="${GITHUB_REF_NAME#v}"
21+
# Prefer ## [0.1.0] / ## [1.2.3]; fall back to Unreleased notes if missing.
22+
{
23+
awk "/^## \[$VERSION\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md
24+
} > release_notes.txt
25+
if [ ! -s release_notes.txt ]; then
26+
awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md > release_notes.txt
27+
fi
28+
if [ ! -s release_notes.txt ]; then
29+
echo "See CHANGELOG.md for details." > release_notes.txt
30+
fi
31+
{
32+
echo "notes<<EOF"
33+
cat release_notes.txt
34+
echo "EOF"
35+
} >> "$GITHUB_OUTPUT"
36+
37+
- name: Create GitHub Release
38+
uses: softprops/action-gh-release@v2
39+
with:
40+
body: ${{ steps.changelog.outputs.notes }}
41+
draft: false
42+
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }}
43+
44+
- name: Set up Python
45+
uses: actions/setup-python@v5
46+
with:
47+
python-version: "3.11"
48+
49+
- name: Install uv
50+
uses: astral-sh/setup-uv@v5
51+
52+
- name: Build sdist + wheel
53+
run: uv build
54+
55+
# PyPI only from the public release repo (not streamlit-coco-dev).
56+
- name: Publish to PyPI
57+
if: >-
58+
github.repository == 'DevoteamSP/streamlit-coco'
59+
&& !contains(github.ref_name, '-rc')
60+
&& !contains(github.ref_name, '-beta')
61+
&& !contains(github.ref_name, '-alpha')
62+
uses: pypa/gh-action-pypi-publish@release/v1
63+
with:
64+
packages-dir: dist/

.github/workflows/security.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Security
2+
3+
# Gitleaks: use the MIT CLI binary (not gitleaks-action@v2).
4+
# The action wrapper requires GITLEAKS_LICENSE for GitHub organization repos
5+
# (DevoteamSP), even public ones. The CLI itself does not.
6+
7+
on:
8+
schedule:
9+
- cron: "0 6 * * 1" # every Monday at 06:00 UTC
10+
pull_request:
11+
branches: [main]
12+
push:
13+
branches: [main]
14+
15+
permissions:
16+
contents: read
17+
18+
env:
19+
GITLEAKS_VERSION: "8.30.1"
20+
21+
jobs:
22+
gitleaks:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
with:
27+
fetch-depth: 0
28+
29+
- name: Install gitleaks
30+
run: |
31+
set -euo pipefail
32+
curl -sSL \
33+
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
34+
-o /tmp/gitleaks.tgz
35+
tar -xzf /tmp/gitleaks.tgz -C /tmp gitleaks
36+
sudo install /tmp/gitleaks /usr/local/bin/gitleaks
37+
gitleaks version
38+
39+
- name: Scan for secrets
40+
run: gitleaks git --verbose --redact --exit-code 1 .
41+
42+
codeql:
43+
runs-on: ubuntu-latest
44+
permissions:
45+
contents: read
46+
security-events: write
47+
steps:
48+
- uses: actions/checkout@v4
49+
- uses: github/codeql-action/init@v3
50+
with:
51+
languages: python
52+
- uses: github/codeql-action/autobuild@v3
53+
- uses: github/codeql-action/analyze@v3
54+
55+
pip-audit:
56+
runs-on: ubuntu-latest
57+
steps:
58+
- uses: actions/checkout@v4
59+
- name: Set up Python
60+
uses: actions/setup-python@v5
61+
with:
62+
python-version-file: .python-version
63+
- uses: astral-sh/setup-uv@v3
64+
- run: uv sync --extra dev
65+
- run: uv run pip-audit
66+
continue-on-error: true

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.venv/
2+
__pycache__/
3+
*.py[cod]
4+
.pytest_cache/
5+
.ruff_cache/
6+
dist/
7+
*.egg-info/
8+
.DS_Store
9+
*.tmp
10+
uv.lock
11+
tmp/
12+
.cursor/
13+
14+
# Streamlit agent skills (environment-specific symlinks)
15+
.agents/skills/developing-with-streamlit
16+
.claude/skills/developing-with-streamlit

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.11

AGENTS.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# AGENTS.md — streamlit-coco
2+
3+
Guidance for coding agents working in this repository.
4+
5+
## Product
6+
7+
Streamlit library + optional CCv2 component for Snowflake CoCo (Cortex Code Agent SDK). Preferred UX: `panel()` + app-owned `chat_input_bar` / `st.chat_input`.
8+
9+
Canonical SDK docs: https://docs.snowflake.com/en/user-guide/cortex-code-agent-sdk/cortex-code-agent-sdk
10+
Pinned rule: `.cursor/rules/coco-sdk-docs.mdc`
11+
12+
## Layout
13+
14+
- `streamlit_coco/` — library (`ui`, `session`, `permissions`, `tool_*`, `bootstrap`, …)
15+
- `examples/` — chat, approval, structured, headless demos
16+
- `docs/PRD.md`, `docs/api.md`, `docs/roadmap.md`, `docs/features/` — product + API + DSP N1 feature docs/checklists
17+
- `docs/deployment/publish.md` — dual-repo sync + tag → PyPI (`streamlit-coco`)
18+
- `CHANGELOG.md` — shipped history (not the roadmap)
19+
20+
**Repos:** develop in `DevoteamSP/streamlit-coco-dev`; publish from `DevoteamSP/streamlit-coco` (`make sync-release`, then tag `v*`).
21+
22+
## Commands
23+
24+
```bash
25+
make install # uv sync --extra dev
26+
make check # ruff + pytest
27+
make audit # pip-audit
28+
make chat # Streamlit demo
29+
```
30+
31+
## Conventions
32+
33+
- Do not default-show raw JSON tool expanders; use meaningful tool cards (`docs/features/tools-display/SPEC.md`).
34+
- Approval buttons left→right: Approve once · Always allow · Deny.
35+
- AskUserQuestion / ExitPlanMode always go through pending HITL; never “Always allow”.
36+
- Update `CHANGELOG.md` `[Unreleased]` for user-visible changes; update feature checklists when UX changes.
37+
- Prefer small, focused diffs; no drive-by refactors.
38+
39+
## Testing
40+
41+
- Unit/smoke: `tests/`
42+
- Manual UI: `docs/features/*/test-checklist.md` before release

CHANGELOG.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6+
Versioning: date-based (`YYYY-MM-DD`) until v1.0.0 is cut, then semantic versioning.
7+
Package version in `pyproject.toml` remains `0.1.0` (alpha) until the first PyPI release is cut.
8+
9+
Living plan (what’s next): [`docs/roadmap.md`](docs/roadmap.md).
10+
11+
---
12+
13+
## [Unreleased]
14+
15+
### Added
16+
17+
#### Dual-repo publish
18+
- Public release repo [`DevoteamSP/streamlit-coco`](https://github.com/DevoteamSP/streamlit-coco); `make sync-release` / `scripts/sync_release.sh`; guide [`docs/deployment/publish.md`](docs/deployment/publish.md)
19+
- Apache-2.0 `LICENSE`; PyPI Trusted Publisher gate in `release.yml` (`github.repository == DevoteamSP/streamlit-coco` only)
20+
21+
#### Phase 3 — HITL, headless, render flexibility
22+
- **Headless multi-turn**`CocoSession.stream()` and `await session.run(prompt)`; `execute_plan()` / `set_permission_mode()`; extended `examples/headless_pipeline.py`
23+
- **Streamlit-free core imports** — lazy `__getattr__` for UI exports so headless scripts never load Streamlit; smoke test + example assert
24+
- **Plan mode Execute CTA** — native `render_plan_banner()` in `panel()`; CCv2 banner **Execute plan** trigger
25+
- **Edit/Write unified diff** — approval + transcript previews via `difflib` (`tool_extract.unified_diff`); Before/After fallback when empty
26+
- **Pluggable text renderer**`text_renderer=` on `panel()`, `render_transcript()`, `render_output_field()` (`markdown` / `write` / `text` / … or callable); feature docs under `docs/features/text-renderer/`
27+
- **App-owned `request_input`** — form + optional multi-field `schema=` (AskUserQuestion remains the in-turn CoCo channel)
28+
- Headless checklist re-signed (2026-07-27): `query()` + `run()` + `stream()` live path; no Streamlit import
29+
30+
#### Earlier unreleased (pre–Phase 3 on this branch)
31+
- **Clear tool “running” captions when done** — parse SDK `UserMessage` / NDJSON `user` tool results; finalize leftover `running` tools on turn `result`
32+
- **CCv2 skill hygiene** — JS cleanup via AbortController; pause `run_every` on pending approval; drop `provide_input`; `isolate_styles=True`; CSS via `--st-yellow-*` / `--st-red-*` / radius tokens
33+
- **API reference**[`docs/api.md`](docs/api.md)
34+
- **Deployment docs (local)**[`docs/deployment/local.md`](docs/deployment/local.md)
35+
- **Typed error hierarchy**`streamlit_coco.errors`; `require_environment()`
36+
- **NDJSON fixture corpus**`tests/fixtures/ndjson/` + `tests/test_ndjson_fixtures.py`
37+
- Feature docs pack + checklist sign-offs (panel, approvals, tools-display, structured-output, chat-ccv2, headless)
38+
- GitHub CI/CD (ci / security / release + optional PyPI publish on `v*` tags); `make publish`; hatch sdist excludes for agent/IDE dirs
39+
- Smoke tests: CCv2 register-once; core import does not load Streamlit
40+
41+
### Changed
42+
- Package / README / identity URLs point at the public [`streamlit-coco`](https://github.com/DevoteamSP/streamlit-coco) repo; development continues on [`streamlit-coco-dev`](https://github.com/DevoteamSP/streamlit-coco-dev)
43+
- GitHub repository renamed to [`DevoteamSP/streamlit-coco-dev`](https://github.com/DevoteamSP/streamlit-coco-dev) (package name remains `streamlit-coco`)
44+
- Examples `structured_output.py` / `approval_gate.py`: `get_or_create_session` + eager `start()` for CCv2 transcript across reruns
45+
- Chat demo sidebar: compact status badges; Settings popover; test prompts behind a toggle
46+
- [`docs/roadmap.md`](docs/roadmap.md) — Phase 3 marked shipped; Next is tag/PyPI + Docker/SPCS docs only
47+
- CCv2 `chat()` registration cached (`@lru_cache`) so `st.components.v2.component` runs once per process
48+
- Headless example: separate event loops for `query()` vs `CocoSession` to avoid SDK cancel-scope teardown issues
49+
50+
### Fixed
51+
- Grep / Glob completed cards: compact summary instead of dumping full result bodies
52+
- AskUserQuestion: free-form / “Other…” options always last in radio / multiselect
53+
- Security workflow: free Gitleaks CLI instead of `gitleaks-action@v2` (org license)
54+
55+
---
56+
57+
## [2026-07-24]
58+
59+
### Added
60+
- **Tools display & user interactions** — full spec + implementation ([`docs/features/tools-display/SPEC.md`](docs/features/tools-display/SPEC.md))
61+
- Meaningful bordered tool cards (no default JSON expanders) for Glob, Grep, Read, Write, Edit, Bash, SQL / `sql_execute`, AskUserQuestion, ExitPlanMode, and generic / MCP tools
62+
- `streamlit_coco.tool_names`, `tool_extract`, `tool_cards` dispatch; CCv2 frontend parity
63+
- AskUserQuestion UI: radio / multiselect, **Other…** free-text, Submit / Cancel; always routed through `can_use_tool`
64+
- SQL card: query code block + dataframe / text results; SQL preview on approval
65+
- ExitPlanMode: Approve plan / Reject (with optional feedback); never “Always allow”
66+
- CoCo debug mode (`STREAMLIT_COCO_DEBUG` / `COCO_DEBUG` / `st.session_state["coco_debug"]`) for collapsed **Raw tool payload**
67+
- Feature checklist + `display_*` test prompt pack ([`docs/features/tools-display/test-checklist.md`](docs/features/tools-display/test-checklist.md), [`examples/testdata/prompts.json`](examples/testdata/prompts.json) v2 — 50+ prompts)
68+
- Chat demo: Plan mode toggle, debug checkbox, test-prompt runner by category
69+
70+
### Changed
71+
- Approval button order (left → right): **Approve once** · **Always allow** · **Deny** (Deny rightmost); AskUser Submit · Cancel; plan Approve · Reject
72+
- Tool approvals show family-specific previews (path, content, Before/After, command, SQL) instead of raw JSON by default
73+
74+
---
75+
76+
## [2026-07-23]
77+
78+
### Added
79+
- `streamlit_coco.bootstrap``check_environment` / start gate helpers, `get_or_create_session`, `chat_input_bar`, `reset_session`, `stop_session`
80+
- `streamlit_coco.diagnostics``CocoEnvironment` probe (CLI, SDK, Snowflake config) without starting an agent
81+
- Session readiness lifecycle — `CONNECTING``READY` / `ERROR`, `ensure_ready()`, init metadata capture
82+
- Soft status chrome in `panel()` — Starting / Thinking / tool activity / Needs approval without remount flicker
83+
- DSP N1 feature test checklists under `docs/features/*/test-checklist.md`
84+
- `docs/roadmap.md` — Now / Next / Soon / Later plan aligned with `docs/PRD.md`
85+
- `Makefile` targets for install, test, lint, format, check, build, and example apps
86+
- Cursor rule pinning Cortex Code Agent SDK docs as source of truth
87+
88+
### Changed
89+
- Preferred app pattern documented as `panel()` + `chat_input_bar` / `st.chat_input` (legacy `chat()` retained)
90+
- `docs/PRD.md` and `README.md` synced to the implemented `panel()`-first API and package layout
91+
- Example `examples/chat_app.py` simplified around bootstrap helpers
92+
93+
### Fixed
94+
- Avoid double-display of Snowflake connections TOML path in the environment / start gate UI
95+
- `chat_input_bar` — graceful fallback when Streamlit lacks `submit_mode` (< 1.59)
96+
- Session status skeleton — fallback placeholder when `st.skeleton` is unavailable (< 1.59)
97+
98+
---
99+
100+
## [2026-07-22] — Alpha baseline (shipped)
101+
102+
Core library and preferred Streamlit UX first landed:
103+
104+
- [x] Pip-installable package + `CocoOptions` / `CocoSession` / `query()`
105+
- [x] Native UI: `panel()` + app-owned input (`chat_input_bar` / `send_prompt`)
106+
- [x] Streaming transcript, tool cards, Stop, fragment polling
107+
- [x] Human-in-the-loop approvals (`require_approval_for`, Deny / Approve once / Always)
108+
- [x] Structured output (inline JSON or `on_structured_output`)
109+
- [x] Legacy CCv2 `chat()` (still supported)
110+
- [x] Examples: chat, approval gate, structured output, headless pipeline
111+
112+
### Added (detail)
113+
- Initial `streamlit-coco` package (`0.1.0` alpha): Python API + Streamlit embedding for Snowflake CoCo
114+
- Normalized `CocoEvent` model and unit tests (`tests/test_core.py`)
115+
- Legacy CCv2 `chat()` component with static frontend assets under `streamlit_coco/frontend/`
116+
- `docs/PRD.md` and `README.md`
117+
118+
---
119+
120+
<!-- Notes:
121+
- Link PRs/issues when available: (#42) or (DevoteamSP/streamlit-coco-dev#42)
122+
- One entry per user-visible change
123+
- Security fixes always under "Security", never under "Fixed"
124+
- Update [Unreleased] as you go; rename to a date (or semver after v1.0.0) on release
125+
-->

0 commit comments

Comments
 (0)