5 Commits
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
229dc0b2f3 |
feat(bitable): U6 R15a BitableTool 4 new actions + DELETE /views endpoint
Extend BitableTool from 6 to 10 actions (create_view, update_view,
update_field, delete_view) and add the DELETE /views/{view_id} backend
endpoint with 404-before-403 ownership, 409 last-view protection, and
X-Internal-Token passthrough (KTD11).
Backend:
- repository.py: add delete_view() — DELETE row by view_id, returns rowcount > 0
- service.py: add LastViewDeletionError domain exception + delete_view()
with last-view guard (siblings <= 1 → raise → route maps to 409)
- routes/bitable.py: add DELETE /views/{view_id} (204 No Content),
404-before-403 ownership pattern, 409 on LastViewDeletionError,
X-Internal-Token passthrough via require_bitable_auth
- tools/bitable_tool.py: add 4 new actions (_create_view, _update_view,
_update_field, _delete_view), register in BOTH handlers dict AND
input_schema.action.enum (KTD10 — 10 actions each)
Frontend:
- api/bitable.ts: add deleteView(viewId): Promise<void>
- stores/bitable.ts: add deleteView action — removes from local state,
switches to first remaining view if active was deleted, 409 warning
- ViewSwitcher.vue: add delete button (a-popconfirm "确认删除此视图?"),
hidden when views.length <= 1 (preempt last-view 409)
- BitableFileDetailView.vue: handle @delete event from ViewSwitcher
Tests:
- test_routes.py: 6 new DELETE /views tests (204, 404 missing, 404
non-owner, 409 last-view, internal-token passthrough, internal-token 404)
- test_bitable_tool.py: 13 new tests (action count = 10, handlers = 10,
4 action happy paths, missing-field errors, 409 last-view, R3/R4
config parity, X-Internal-Token passthrough on all 4 new actions)
- e2e/bitable-agent-parity.spec.ts: 10 scenarios (P1-P10) covering
delete button visibility, popconfirm, 204/409/404 flows, tab removal,
view switch after delete, create view adds tab
Verification:
- ruff check: all files pass
- pytest: 62 passed, 12 pre-existing failures (unchanged from
|
|
|
|
e931fbef2d |
feat(bitable): U5 R4 grouping (max 3 fields) + conditional formatting (7 operators)
- GroupingEditor: multi-select field picker (max 3), per-level direction toggle, reorder buttons, "已知限制:不支持跨分组多选" note, empty state - ConditionalFormatEditor: per-rule enable/field/operator/value/color/bold, 8 color keys, WCAG 1.4.1 bold default true, first-match-wins footer legend - BitableGrid: unified section rendering (grouped/ungrouped via single vxe-grid declaration), group headers as separate divs (CF only on data cells), CF via row-config.className, multi-grid instance map for refresh - groupingRulesUtils: pure functions for CF matching (7 operators), group tree builder, SUM/AVG aggregation, CSS var mappers, self-check on load - view_config.py: Pydantic v2 validation (MAX_GROUP_BY_FIELDS=3, 7 operators, 8 color keys, extra="forbid" on sub-models) - routes/bitable.py: validate_view_config on PATCH (HTTP 422 on error) - stores/bitable.ts: updateViewConfig action (merges U5 sub-keys, preserves filters/sort/hidden_fields) - ViewConfigPanel: grouping + conditional-format tabs - E2E: 8 scenarios (G1-G8: single/multi grouping, collapse/expand, CF equals/between, combined, aggregation) - Tests: 54 unit tests (19 grouping + 35 CF), 2 PG-marked skipped |
|
|
|
78a7faa17b |
refactor: remove all emoji from agentkit
Deploy to Production / deploy (push) Waiting to run
Details
Test / backend-test (push) Waiting to run
Details
Test / frontend-unit (push) Waiting to run
Details
Test / api-e2e (push) Waiting to run
Details
Test / frontend-e2e (push) Waiting to run
Details
Test / backend-test (pull_request) Has been cancelled
Details
Test / frontend-unit (pull_request) Has been cancelled
Details
Test / api-e2e (pull_request) Has been cancelled
Details
Test / frontend-e2e (pull_request) Has been cancelled
Details
Replace emoji across codebase: YAML avatars -> first char, frontend banners -> Ant Design Vue components, CLI status -> OK/FAIL/WARN labels, terminal -> [WARN]/[OK]/[PENDING], Bitable DB default -> table, App.vue font cleanup, test fixtures -> first char letters. shell.avatar type upgraded to string | Component. |
|
|
|
a6e1bf5884 |
feat(bitable): 多维表格文件层 + 默认字段 + 表内字段操作 + ce-code-review 修复 (Stage 1)
Test / backend-test (pull_request) Has been cancelled
Details
Test / frontend-unit (pull_request) Has been cancelled
Details
Test / api-e2e (pull_request) Has been cancelled
Details
Test / frontend-e2e (pull_request) Has been cancelled
Details
实现多维表格 UI 完整性 Stage 1(U1-U6),补齐飞书/twenty 对齐缺失的文件层、
默认字段与表内字段操作能力,并修复 ce-code-review 走查发现的 P0/P1 级问题。
后端(U1-U2):
- 新增 BitableFile 实体(models/db/repository/service/routes),三级层级:文件→数据表→字段/记录
- Schema V2 迁移:bitable_files 表 + tables.file_id 列,幂等(IF NOT EXISTS),保留 V1 孤儿表
- 新建数据表自动创建 5 个默认字段(标题/状态/日期/创建人/创建时间)
- agent-owned 字段在 create_record 时自动填充(按 type+owner 匹配,传 actor_user_id)
- 7 个文件 REST 端点 + IDOR ownership 检查(404-before-403,internal token 旁路)
前端(U3-U5):
- 文件列表页(FileCard 网格 + 新建/重命名/删除)+ 文件详情页(侧栏表格列表 + vxe-table 网格)
- Vue Router 嵌套路由 /bitable → /bitable/:fileId → /bitable/:fileId/:tableId
- 列头菜单(编辑/隐藏/删除字段)+ 末尾 + 列新增字段
- select/multiselect 字段自定义单元格编辑器 + Tag 展示
- Pinia store 扩展 file 状态与动作,深链直访回退 getFile,fileId 切换 watch
测试(U6):
- 文件 CRUD(12 例)+ 默认字段(10 例)单元测试
- 3 个 E2E spec(视图加载、文件流、字段操作),后端不可用时优雅跳过
ce-code-review 修复(P0/P1):
- P0 路由冲突:GET /files/{file_id} 遮蔽下载端点 → 下载改 /uploads/{filename}
- P0 IDOR:update/delete field/record/view 五端点补 ownership 检查
- P1 is_initialized property 缺失致二次初始化崩溃
- P1 直接 URL 导航失效(files 数组为空)→ selectFile 回退 getFile
- P1 fileId 切换不重载 → 增加 watch
- P1 轮询丢弃最终公式值(wasCalculating 守卫)+ 复用视图 filters
- P1 测试断言 200→201;test_db 无 URL 用例解除 postgres 标记得以执行
- P2 _check_table_ownership 403→404;输入长度校验;upload field-table 一致性校验
- P2 multiselect 浅比较 → 深比较;E2E bitable-view 补 waitForServer 守卫
验证:ruff check 通过;pytest 91 passed/116 skipped;vue-tsc --noEmit 通过。
|
|
|
|
bbbf9cd40a |
feat(bitable): add bitable companion service with full P0-P2 fixes
Bitable is a multi-dimensional table companion service that runs alongside the main AgentKit server. It provides structured data storage with formula fields, views, and ingestion pipelines. Major components: - Domain models (Pydantic v2): Table, Field, Record, View, RecalcTask - SQLAlchemy 2 async ORM with independent bitable PostgreSQL schema - Formula engine: AST parser, DAG, Kahn topological sort, safe eval - RecalcWorker: atomic task claiming (FOR UPDATE SKIP LOCKED), topo-order processing, stale-threshold reaper for crash recovery - REST API (/api/v1/bitable): tables, fields, records, views, files - BitableTool: agent-facing tool with batch chunking (500/batch) - CLI: agentkit bitable subcommands (create, list, import-excel, etc.) - Frontend: Vue 3 + vxe-table grid with field management, views, filters - Ingestion: Excel (openpyxl), database reflection, API collector Security fixes (ce-code-review P0 + ce-debug P1): - SQL injection prevention (field_id validation, parameterized queries) - IDOR protection (_check_table_ownership on all table-level endpoints) - SSRF prevention (URL scheme + private IP validation in parse_excel_url) - OOM prevention (streaming file upload, batch delete, batch insert) - Atomic recalc task claiming (FOR UPDATE SKIP LOCKED) - Formula engine cache invalidation on field changes - Composite cursor pagination for non-id sort orders - Batch upsert (eliminates N+1 queries) - Sync I/O offloaded to thread pool in async contexts - Internal token auth (X-Internal-Token, hmac.compare_digest) - PK unique index enforcement Test coverage: 88 unit tests (95 skipped without Docker) |