13 Commits
Author SHA1 Message Date
seed30 2aebbe5bbf test(live): skip Tencent News probe when upstream credits are exhausted
The live connector probe treated a Tencent News billing error (4007, insufficient credits) as a product failure. Skip that upstream usage limit the same way network failures are skipped, and still fail on bad credentials.
2026-10-12 21:00:11 +08:00
Suroyandjubaoliang 83b2ae2e73 feat(auth): add LDAP directory login (#1123)
Let users sign in with their directory (Active Directory / OpenLDAP)
credentials through the existing login form. Reuses sso_providers
(kind='ldap') and user_sso_identities, so no schema change is needed.

Authentication is search-then-bind: a service account resolves the user and
only the returned DN is bound with the submitted password, so user input is
never used as a bind identity. Roles come from a role template at first
provisioning only; changing a directory group later never re-templates an
existing account. Directory outages and wrong passwords stay distinguishable
(502 LDAP_UNAVAILABLE vs 401 AUTH_FAILED).

Hardening from review:

- An account holding its own password stops at the local check, so a local
  secret is never forwarded to the directory nor counted against that
  directory's own lockout policy.
- A lookup without a unique exact identifier match is refused instead of
  being bound against the first hit.
- A failure during the user bind surfaces as LDAP_UNAVAILABLE rather than a
  401 credential verdict.
- Binds are throttled before they reach the directory, keyed per identifier
  and client address, with the address resolved from a trusted peer so a
  spoofed X-Forwarded-For cannot reset the budget.
- Enabling a plain ldap:// URL without StartTLS is rejected; a disabled
  certificate check is surfaced as a warning.
- auto_provision defaults to off, with an optional allowed_groups allow-list
  and a group-search mode (member / uniqueMember / memberUid) for directories
  that do not expose memberOf. Nested groups are not resolved.
- The identity key is configurable (entryUUID / objectGUID) and blank by
  default; a connectivity probe reports which attribute the directory
  exposes.
- Config changes are audited against the acting admin, and referrals are no
  longer followed during binds.

Tests cover the above without a live directory (ldap3.Connection is the only
thing replaced); a live test exercises a real directory when configured.

Co-authored-by: jubaoliang <jubaoliang@gmail.com>
2026-10-02 22:39:13 +08:00
347dee56f4 refactor(infra): group agents modules and clarify package ownership (#1164)
* refactor(agents): group thin modules into domain subpackages

Move plugin helpers, memory, settings stores, persona/MBTI, and avatar
bootstrap code under plugins/, memory/, settings/, persona/, and experts/
while keeping top-level import shims so existing call sites stay stable.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(agents): drop compatibility shims after subpackage move

Call sites already import the new package paths; remove the top-level
re-export stubs so the agents tree only shows real modules.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(agents): move thread helpers into threads/

Group artifact shaping, fork, and context breakdown under
agents/threads so top-level only keeps lifecycle/config adapters.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(agents): fold profile/runtime/tool catalog into settings/

Move the remaining config-surface helpers under settings/ and drop the
skill_package id-list aliases in favor of dump/parse_id_list.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(agents): group workspace_dir and execute_env under workspace/

Keep path resolution and harness execute-env injection together as one
workspace package; leave only manager and conversation_mode at top level.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(infra): fix history/SkillHub ownership and drop thin providers/

Move history_projection under history/, share SkillHub host/limits and
route expert skill downloads through skills.skillhub_market, and fold
Codex OAuth helpers into agents.providers to remove the tiny providers/
package.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: sync AGENTS.md and guides with infra/agents layout

Reflect subpackages (settings/workspace/threads/persona, history/, skills/)
and drop stale runtime.py / mbti_profiles paths after the agents reorg.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-25 22:32:41 +08:00
2209cdc90f chore(deps): switch runtime packages to octop-* 1.0.0 (#1136)
Replace orcakit-harness-agent / harness-* with octop-harness, octop-gateway, octop-memory, and octop-browser, and align docs, UI copy, and generated paths.

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-25 06:44:24 +08:00
981a5aec99 fix(voice): localize Tencent probe failures for zh UI (#670)
* fix(voice): localize Tencent probe failures for zh UI

Map known AuthFailure codes (and related probe wrappers) through voice.* i18n, and send X-TC-Language so unmapped vendor messages follow Accept-Language.

Co-authored-by: Cursor <cursoragent@cursor.com>

* style(voice): apply ruff format to adapters.py

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(agents): stop memory GC before closing the harness SQLite store

Closing an agent while harness-memory list_candidates is still running segfaults (seen in make test-live). Quiesce the maintenance thread on delete/stop, and keep live fixtures memory-off.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 09:26:22 +08:00
jubaoliang 11457e33c1 feat(skills): localize skill presentation from metadata.octop (#480)
* feat(skills): localize skill presentation from metadata.octop

Read bilingual label/summary and icons from SKILL.md, keep slug identity
for disable/chat matching, and show market icons in the chat skill picker.

* chore: bump harness-agent to 1.0.1 and skip Weixin live timeouts

Pin orcakit-harness-agent>=1.0.1 now that 1.0.1 is on PyPI, and treat
iLink getUpdates timeouts as environment skips like other live probes.
2026-08-30 20:49:14 +08:00
jubaoliang fbe33e49c4 feat(tests): add live WeChat/Feishu channel credential probes (#479)
Wire ChannelManager.probe_channel live cases into CI so real iLink and
Feishu app credentials are verified when LIVE_* secrets are configured.
2026-08-30 12:24:36 +08:00
HUANG Chengandjubaoliang acf48d74b8 feat(connectors): catalog-driven MCP OAuth for Ardot and Dida365 (#414)
* feat(connectors): catalog-driven MCP OAuth for Ardot and Dida365

Unify Notion-style remote MCP OAuth behind catalog fields so new issuers
are mostly config, and add 腾讯设计 Ardot plus 滴答清单 with one-click
auth, manual token paste, and shared HTTPS callback handling.

Also align the Chrome runtime-dir unit test with non-Linux temp paths so
macOS pre-commit stays green.

* fix(tests): skip getuid monkeypatch when absent on Windows

setattr(os, "getuid") fails on Windows where the attribute does not
exist; only replace it on platforms that already have getuid.

---------

Co-authored-by: jubaoliang <jubaoliang@gmail.com>
2026-08-26 10:25:30 +08:00
jubaoliangandjubaoliang 18ab9f6ba9 feat: workspace backend sandboxing, execute-env injection, and ephemeral image refs (#376)
* feat: workspace backend sandboxing, execute-env injection, and ephemeral image refs

Workspace file-I/O hardening across backend and dashboard:
- Host directory sandboxing via root_dir allow-list and denied prefixes
- Execute-environment defaults injected into harness backend specs
- Ephemeral workspace image rematerialization for model calls
- Attachment hint expansion and inbound store improvements
- Portable memory backend and skill workspace catalog updates
- Dashboard UI for agent backend fields and root-dir selection
- Bump harness-agent 0.9.23 / harness-memory 0.9.7; docs + install notes

* feat: add user invitation codes with admin management and redeem flow

- Add user_invites table (migration 009) plus SQLite/Postgres reconcile paths
- Add InviteRepo and InviteService for create/revoke/list/redeem
- Expose public validate/redeem endpoints and admin create/revoke/list routers
- Extract default-agent bootstrap into octop.infra.agents.default_agent
- Add invite error codes and en/zh i18n strings
- Dashboard: invite drawer, login redeem UI, users list, and locales

* fix: add Windows cross-platform guards for pre-existing sandbox/rootfs tests

- Guard POSIX/container-only tests (rootfs-absolute /.octop/... workspace
  paths) with posix_only in test_thread_artifacts.py and test_agent_manager.py
- Normalize the rendered workspace path assertion in test_octop_builtin_skills.py
  (forward slashes on Windows, not str(tmp_path) backslashes)
- Canonicalize ws_dir before the prefix check in attachment hint/path tests
  (tempfile may yield an 8.3 short path on Windows while the resolved
  attachment path uses the long form)

These failures predate the user-invites commit and are unrelated to it; the
product path logic is correct.

---------

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
2026-08-21 22:32:48 +08:00
薄生 dca16ccc21 Feat/postgresql dual backend (#60)
* feat: PostgreSQL dual-backend for control plane

Add SqlitePool|PostgresPool behind DatabasePool, parallel PG migrations,
setup wizard defer/bind, pg_dump backups with cross-engine refusal, and
memory defaulting to the control-plane DSN when using PostgreSQL.

* fix(chat): delete checkpoint data when a conversation thread is deleted

Deleting a thread only removed Octop's own metadata row; the actual
message history stayed in the agent's LangGraph checkpointer forever,
making "delete conversation" cosmetic. Also confirm before deleting a
session in the UI, since the action is now genuinely destructive.

Checkpoint deletion runs before the metadata row is removed: if it
fails outright (not just "nothing to delete"), the thread stays
visible/retryable instead of orphaning data with no remaining handle.

* fix(memory): stop suggesting pg_dump for portable export of postgres memory

The 501 hint told users to "use pg_dump on the memory schema instead".
That advice predates the shared-table layout: memory for ALL agents now
lives in one harness_memory schema isolated by a namespace column, so a
schema-level pg_dump would export every agent's memory, not just the
requester's — a cross-agent data exposure if followed on a multi-user
install.

Document the two migration models where the refusal is implemented:
sqlite memory is per-agent files moved via pack/adopt; postgres memory
is shared, and the supported way to use it from another host (e.g.
OpenClaw's harness-memory bridge with --backend postgres) is pointing
that host at the same DSN and namespace — shared, not migrated.

* fix(test): update test_slash_compact to renamed SqlitePool

The /compact test module still imported the pre-rename DBPool, which
broke collection (ImportError) on this branch after develop's compact
feature was merged in — DBPool was renamed to SqlitePool (the concrete
class) with DatabasePool now the Protocol.

DBPool -> SqlitePool at all three sites: the import, the _agent_manager
type hint, and the fixture's DBPool(path) instantiation. SqlitePool is
the byte-for-byte successor of DBPool and matches how every other test
constructs a pool; DatabasePool cannot be used at the instantiation
site (a Protocol is not instantiable).

pytest -m live now collects cleanly (31 selected, 0 errors);
test_slash_compact 3 tests pass.

* fix(test): make memory_backend db_path assertion separator-agnostic

test_explicit_sqlite_overrides_postgresql_control_plane compared the
resolved db_path against the literal "/tmp/ws/memory.sqlite", which the
code never produces on Windows: it builds the path with pathlib, so the
Windows CI job got "\tmp\ws\memory.sqlite" and the string equality failed.

Compare as Path objects so the assertion holds on every OS separator,
matching the .as_posix() discipline already used in test_config.py.
2026-07-24 14:45:53 +08:00
jubaoliangandjubaoliang 6ee2f156f5 feat: remote desktop install and connector probe improvements (#16)
- Refactor RemoteDesktop control page
- Add desktop install hook and setup script tweaks
- Enhance connector probe with better detection
- Sync README and locale strings (zh/en)

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
2026-07-16 21:18:54 +08:00
085506e3f3 Feat/connectors gateway install (#14)
* feat(connectors): add gateway connectors and drop baidu-netdisk/figma

Expand the catalog with QQ Music, Fliggy, Baidu Map, Ctrip Wendao, Meituan Travel, and Yuandian; migrate Tencent News to API key; unify gateway credential probes; remove Baidu Netdisk/Figma OAuth paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(install): ship Playwright by default and harden install scripts

Make browser tooling a core dependency, drop obsolete optional extras, and improve glibc/Playwright system-deps handling across install.sh/ps1/bat.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(desktop): install build deps before Python packages on Linux

Add a build-deps-only path so remote desktop setup can compile extension wheels when system headers are missing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(dashboard): cache update-status checks in localStorage

Deduplicate concurrent PyPI probes across mounts and persist the last known update status with a short TTL.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(live): add OSS probes, secret helpers, and CI live job

Centralize require_env skipping, document live credentials in .env.example, and wire a secrets-gated live-tests workflow.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(tests): rename chat WS integration test and drop dead cases

Align the chat transport test name with WebSocket usage and remove a skipped bootstrap harness test.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): unblock typecheck, CodeQL, and drifted live tests

Align mypy with requires-python 3.12 so numpy stubs parse; clarify Fliggy
SHA-256 use for request signing; update live expert/backend assertions
to the lazy Expert catalog and DEFAULT_BACKEND_SPEC with root_dir.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): news Skill-Request-Id, workspace live reads, CodeQL FP

Add Tencent News CLI headers required by error 4010; assert expert
seeds via agent.workspace instead of host-rooted backend paths; ignore
Fliggy signing digests in CodeQL (protocol SHA-256, not password KDF).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(tests): allow newline-only __init__.py in expert live checks

Office-automation skill packages ship empty package markers; strip()-based
emptiness assertions should not treat those as copy failures.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(tests): compare expert seeds via adownload_bytes

Harness aread_text replaces empty/whitespace file bodies with a system
reminder, which broke live office-automation __init__.py checks.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 19:25:51 +08:00
jubaoliang 748d998cf2 first commit 2026-07-09 14:32:36 +00:00