5 Commits
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
fae76b7cca |
merge: resolve conflict with origin/main (PR #24/#25)
Test / backend-test (pull_request) Waiting to run
Details
Test / frontend-unit (pull_request) Waiting to run
Details
Test / api-e2e (pull_request) Waiting to run
Details
Test / frontend-e2e (pull_request) Waiting to run
Details
Conflict in src/agentkit/bitable/service.py delete_view(): - Adopted main's MAINT-2 fix (delete_view_if_not_last atomic op + race check) - Worktree's simpler version replaced by main's race-safe implementation No conflict markers remain. 277 tests pass, ruff clean. |
|
|
|
6d5a34ada2 |
feat(bitable): formula relations v2 — U1-U8 + review fixes
Test / backend-test (pull_request) Waiting to run
Details
Test / frontend-unit (pull_request) Waiting to run
Details
Test / api-e2e (pull_request) Waiting to run
Details
Test / frontend-e2e (pull_request) Waiting to run
Details
Implements bitable v2: formula engine expansion (10->64 functions),
cross-table formula references, relation CRUD (1:1/1:N/N:N + bidirectional),
lookup/rollup fields, cross-table dependency graph, automation engine
(3 triggers + 5 actions + retry + webhook), and REST API + BitableTool actions.
Implementation units:
- U1: Schema V3 migration (junction table, automations, cross_table_deps)
- U2: Formula functions 10->64 (datetime/text/logical/aggregate/lookup)
- U3: Cross-table formula {rel.target} syntax (parser 3-tuple, engine resolve)
- U4: Relation CRUD + bidirectional + self-reference
- U5: Lookup & Rollup field types with recalc worker routing
- U6: Cross-table dependency graph + recalc trigger
- U7: Automation engine (asyncio queue, 3x retry, execution logs)
- U8: REST API (11 endpoints) + BitableTool (17 actions)
Review fixes applied (ce-code-review mode:agent):
- P1: SSRF guard on outbound webhook (reuse _assert_safe_host from ingestion)
- P1: Bidirectional relation removal now cleans reverse field (symmetric with add)
- P2: Ownership check on target_table_id in relation field creation (IDOR fix)
- P2: Typed AutomationUpdate Pydantic model (prevents table_id injection)
- P3: Tracked automation fire-and-forget tasks (error visibility)
- P3: Public FormulaEngine.get_cross_table_mapping (remove private attr access)
Tests: 267 passed, 153 skipped (PG). Ruff clean.
Deferred: generate_formula/generate_automation LLM actions, frontend components.
|
|
|
|
c60e96ac32 |
fix(bitable/team): U3 — Residual P2 findings (DR-1/3/4/5 + #2/#3)
U3 修复 8 项 P2 design review 与 streaming 残留问题: DR-1 SQL 注入防御 — repository.py 添加 _validate_field_id UUID 校验, 拒绝非 UUID 字符串进入 jsonb_set path 与 WHERE 子句的字符串插值。 ceiling 注释标明仅覆盖 field_id,其余 SQL 结构由 service 层枚举白名单守护。 DR-3 design token 契约 — 新增 bitable-tokens.test.ts (31 tests), 解析 CSS :root 块并断言所有 --bitable-* token 在 :root 定义, 防止 token 被硬编码到组件外或遗漏定义。 DR-4 TOCTOU 修复 — repository.delete_view_if_not_last 用 SELECT ... FOR UPDATE 单事务原子化 check + delete, 消除 list_views → count → delete 三步分离的竞态。 service.delete_view 委托原子方法,失败抛 LastViewDeletionError。 DR-5 _update_field 静默失败 — type 参数被 Pydantic extra=ignore 静默丢弃,用户以为改了类型实际无效。显式返回 UNSUPPORTED_FIELD_TYPE_CHANGE 错误,避免静默失败的 UX 陷阱。 #2 team_synthesis 孤儿 milestone — 补 error + cancelled 路径测试, 验证内层 except 广播终结事件后 re-raise,外层 except 捕获后 fallback。 #3 synthesis_id 去重附身 — chatStream.ts 移除 || m.synthesis_id === undefined 兜底匹配,避免新 milestone 附身到上一次孤儿 streaming 占位。 测试:DR-1 (7) + DR-4 repo (3) + DR-4 service (3) + DR-5 (2) + #2 (2) + #8 frontend (31) = 48 项通过;U2 无回归 (29 项)。 |
|
|
|
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
|
|
|
|
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) |