646 Commits
Author SHA1 Message Date
Dongle 25a563a308 Merge pull request #158 from RheagalFire/feat/add-litellm-provider
feat: add LiteLLM as AI gateway provider
2026-08-26 07:14:46 +08:00
Dongle d51e74be9f Merge pull request #157 from yuruotong1/claude/update-ai-client-docs-BCdGk
v4.5.8: drop Android APK, cleaner Connect AI tab
2026-08-07 07:47:55 +08:00
RheagalFire 61bf4757cc feat: add LiteLLM as AI gateway provider 2026-05-05 23:35:34 +05:30
Claude 8b77d1bfb6 feat(v4.6.0): one-click OAuth — PKCE + cloud broker, drop secret-paste UX
Replaces the painful "register your own OAuth app, paste client_id +
client_secret" flow with click-Authorize-and-done. Two completion
paths:

PKCE (no broker, no secrets)
- Used for providers that support OAuth 2.1 PKCE: Linear today;
  Atlassian / Microsoft / Google / Twitter / Discord drop in once each
  is registered.
- Local hub generates code_verifier, sends sha256 challenge to the
  provider, exchanges code + verifier on the callback. No secret in
  the binary.

Broker-mediated (autoMate Cloud or self-hosted)
- For providers that still require a confidential client at the token
  endpoint: GitHub, Notion, Slack, 飞书, 钉钉.
- Hosted broker (cloud/oauth_broker/) holds client_secret per
  provider; local hub never sees it. Flow:
    local → broker /start → provider → broker /callback (exchanges
    code for token, stashes by flow_id) → user-browser bounce back to
    local with flow_id → local fetches token via broker /result
    (single-use, deleted on read).
- Default broker URL is https://broker.automate.cloud; override with
  AUTOMATE_OAUTH_BROKER_URL for self-hosted.
- Tokens live in the broker's memory only during the ~30s in-flight
  window; flow_id is the only secret in transit (HTTPS).

Tools tab UI
- Each card has ONE "Connect" button.
- OAuth modal: a single big "Authorize with X" button. Click opens a
  popup at the provider's consent page; on success the callback page
  posts a message to the opener and self-closes; the modal updates to
  ✓ Connected without a refresh.
- API-key path: a single big deep-link button to the EXACT token
  page (with scopes pre-selected for GitHub etc.) + one paste field.
- Removed: client_id + client_secret inputs, "Use OAuth instead
  (advanced)" toggle, the /api/integrations/<id>/oauth-app endpoint.

Standalone broker (cloud/oauth_broker/)
- Tiny FastAPI app, deployable as a Docker image (Dockerfile +
  requirements.txt included) or `pip install -r requirements.txt &
  uvicorn main:app`.
- Reads OAUTH_<PROVIDER>_CLIENT_ID/SECRET from env, plus
  PUBLIC_BASE_URL.
- Exposes /oauth/<p>/start, /oauth/<p>/callback, /oauth/result, /health.
- Per-provider OAuth scopes are hardcoded in main.py:SPECS.

Docs
- docs/oauth-broker.md walks maintainers/self-hosters through the
  deployment + per-provider OAuth app registration.

When the broker is unreachable the OAuth modal degrades gracefully:
clear error message + "Or paste an API key instead" expandable that
deep-links to the provider's PAT page. OAuth and API-key flows produce
identical end-state in the connections table.

https://claude.ai/code/session_019uRjfdjRsVwG9iNbc5gJmN
v4.6.0
2026-04-28 07:55:55 +00:00
Claude f4d23e2e32 feat(v4.5.10): drop Connect AI tab, rebuild Bots around OpenClaw-WeChat
The Connect AI tab was a dead-end for non-MCP clients (the user tried
several platforms and none of them worked end-to-end without a manual
relay). Removing it entirely:

- Delete the Connect AI section, the per-client picker, and the
  /api/connect snippet endpoint
- Drop aiClient / aiClients / pickAiClient / aiClientMode / aiClientWhere
  state, plus copySnippet / copiedKey / loadConnectInfo / connectInfo
- Strip the `connect` tab from desktop tabs and mobile More menu
- Reroute every "Get the snippet" / "Use from a different AI" entry
  point to the Bots tab

Bots tab is now a step-by-step OpenClaw-WeChat setup guide:

1. Install OpenClaw + the @canghe/openclaw-wechat plugin
2. Drop autoMate's bundle-mcp config block (URL + bearer token
   pre-filled) into ~/.openclaw/openclaw.json5
3. Configure channels.wechat.* (apiKey / proxyUrl / webhookHost)
4. `openclaw gateway start`, scan the QR with WeChat

The same path covers Telegram / Slack / Discord etc. — only step 3
changes per channel. Existing direct-webhook bots (telegram /
wechat_oa / wecom) are kept under "Direct platform webhooks
(advanced / legacy)" for users who can't run OpenClaw.

Renames installInfo state's connectCopied → installCopied and
copyConnectInstructions → copyInstallText to match the new naming.

References https://github.com/freestylefly/openclaw-wechat for the
upstream WeChat plugin setup.

https://claude.ai/code/session_019uRjfdjRsVwG9iNbc5gJmN
v4.5.10
2026-04-28 07:06:37 +00:00
Claude 41edf50ffa release: v4.5.9
Same shipping commit as v4.5.8 (drop Android APK + Connect AI tab
cleanup), bumped to 4.5.9 so the release artifacts have a fresh tag.

https://claude.ai/code/session_019uRjfdjRsVwG9iNbc5gJmN
v4.5.9
2026-04-28 06:08:05 +00:00
Claude 417a2d4a07 feat(v4.5.8): drop Android APK + cleaner Connect AI tab
Home tab: remove the four-channel grid (Telegram / 微信公众号 / WeCom /
个人微信) — Bots tab is still in the bottom nav. The home page now only
shows three primary entry points: chat, Connect AI, quick actions.

Connect AI tab: surface the "Copy install text (all clients)" button as
the primary CTA at the top of the tab — this is the per-client markdown
guide users can hand to any AI to set itself up. The per-client picker
moves below as a secondary path.

Per-client picker: split "Kimi K2 / Kimi Code" into two distinct cards
since Kimi Code (the CLI) doesn't load MCP servers. Add Cline as its
own card. Each card now declares its actual transport and a "where to
paste" hint pointing at the specific config file or UI surface.

Drop the Android APK build entirely: PWA covers Android the same way it
covers iOS. Removes the android/ directory, the android job in
.github/workflows/build.yml, isAndroid/downloadApk frontend code, and
the platform pattern in system.py update detection. Updates README,
README_CN, docs/mobile.md, docs/sync.md.

Bug fix: loadBridge() and loadConnectInfo() were both writing to a
single connectInfo Alpine property — they have different shapes
(markdown/url/token vs base_url/modes) and clobbered each other under
Promise.all. Renames the bridge-loaded one to installInfo.

https://claude.ai/code/session_019uRjfdjRsVwG9iNbc5gJmN
2026-04-28 05:58:29 +00:00
Claude 4d7bd0c712 docs: refresh README + README_CN for v4.5.7 (autoMate as MCP tool source)
Both READMEs were stuck at v4.2 status — pre-Coze-retrieval, pre-audio,
pre-channels, pre-MCP-HTTP. Reframes the pitch around the v4.5.7
positioning:
- autoMate is a tool source other AI clients (OpenClaw / Claude Desktop /
  Cursor / Cline) call into via MCP-over-HTTP
- standalone web chat is the secondary mode, not the primary
- Settings has a one-click "Copy install text" that's both human-
  readable and AI-pasteable
- IM channels are OpenClaw's job (it has the official Tencent WeChat
  plugin); autoMate plugs in as its tool source
- new feature surface: search.find (FTS5), audio.transcribe (Pro),
  configurable storage path, in-app auto-update

Diagram updated to show OpenClaw at the top of the client list and
search.find in the data column. Status section now reads v4.5.7.

Removed the four-modes table (MCP / HTTP / Bridge / OpenAPI) since
MCP-over-HTTP supersedes the bridge/HTTP modes for any modern client.
The legacy /api/channels/inbox is mentioned in docs/channels.md for
n8n / custom scripts but no longer highlighted as a top-level path.

automate/bots/ deprecation noted in both languages.
2026-04-26 14:53:18 +00:00
Claude 36d96d9e5e feat(v4.5.7): autoMate as a tool source — MCP-over-HTTP + connect text
Architectural pivot, prompted by user feedback. Previous design (v4.5.6)
treated autoMate as an interceptor: external gateways forwarded all IM
messages to autoMate's inbox, autoMate ran the agent, autoMate replied.
That conflated channel handling with reasoning, and pitted autoMate
against agents that were already doing reasoning (OpenClaw, Claude
Desktop, Cursor, ...).

The right model is: those clients are agents; autoMate is a tool
*they* call when they need the user's notes / files / memory /
schedule. Each agent stays the brain on its own platform; autoMate
is the personal-data spine they all share.

Backend:
- automate/server/mcp_bridge.py: split into _build_mcp() core +
  serve_stdio() (legacy, for Claude Desktop's stdio path) and
  build_http_app() returning the streamable_http_app + session
  manager. streamable_http_path="/" so mounting at /mcp gives the
  user-facing path /mcp/ instead of /mcp/mcp.
- automate/server/app.py: mount the MCP app at /mcp with a Bearer
  auth wrapper (_BearerProtect) that reuses the channels bridge
  token. Bare /mcp (no slash) returns a 307 to /mcp/. Lifespan
  context manager runs the MCP session_manager. mcp[cli] promoted
  from optional to required dep so this works out of the box.
- automate/server/api/channels.py: new GET /api/channels/connect-
  instructions endpoint. Generates a 4-5KB markdown blob with the
  hub's URL and token already substituted in, with sections for
  OpenClaw / Claude Desktop / Cursor / Cline / generic MCP /
  non-MCP gateways / security. Designed so the user can ALSO paste
  the entire blob into another AI ("Cursor, set up autoMate for
  me") — leading paragraph addresses an AI reader directly.

Frontend:
- Settings → "Connect to AI clients": single big "Copy install text"
  button. <details> below shows MCP URL + token + regenerate.
- The legacy /api/channels/inbox URL section moved into a
  collapsible <details> further down (kept for non-MCP gateways).
- copyConnectInstructions() prefetches the markdown at refresh
  time so the click is instant. Falls back to a notice modal if
  clipboard access is blocked.

Verified end-to-end in a smoke test:
- Mount auth: 401 without Bearer / 401 with bad token.
- Initialize: returns serverInfo {name: "autoMate"}.
- tools/list returns 42 tools (automate + search.find +
  notes.* + files.* + reminders.* + memory.* + audio.transcribe +
  shell + browser + ...).

Docs:
- docs/channels.md rewritten. Documents the two modes (autoMate as
  tool inside other clients vs. autoMate's own web chat). Marks
  v4.5.6 inbox endpoint as kept-for-non-MCP-gateways but no longer
  the highlighted path. /api/channels/inbox itself unchanged.

Bumps to 4.5.7; Android versionCode 17.
v4.5.7
2026-04-26 14:07:15 +00:00
Claude 073fa38502 feat(v4.5.6): channels bridge — let WeChat/Telegram/etc. talk to autoMate
Pivot from "build our own IM bots" to "expose a tiny inbox HTTP
endpoint and let an external gateway (OpenClaw) handle the platform
protocols". Architectural decision recorded in docs/channels.md.

Why: reimplementing WeChat/WhatsApp/Telegram is a full-time team's
job. OpenClaw already does it well, and its WeChat plugin is
maintained by Tencent against 微信个人助手 (the official WeChat AI
assistant channel) — no account-takeover, no ban risk. autoMate's
job is files/notes/agent reasoning; let OpenClaw handle the wire.

Backend:
- automate/channels.py:
  - get_or_create_token / regenerate_token / verify_token — Bearer
    auth, stored in the existing settings KV table, secrets.token_urlsafe.
  - InboundMessage / Reply dataclasses.
  - process_inbound() — frames the message with a "[from <user> on
    <channel>]" context line so the LLM knows it's on chat (terse,
    non-Markdown-heavy) and which user it's talking to (memory key).
    Calls AgentLoop.run() with source="channel:<chan>:<user>" so
    runs are searchable by who said what on which platform.
- automate/server/api/channels.py:
  - POST /api/channels/inbox — Bearer-auth'd, runs agent, returns
    {text, run_id, ms}. 401 missing/invalid token, 400 empty text,
    503 with friendly message on agent failure (instead of 500 — so
    the gateway can render something useful).
  - GET  /api/channels/bridge — returns the inbox URL path + token
    so the SPA can show them for copy-paste.
  - POST /api/channels/bridge/regenerate — rotate token (with
    explicit confirm dialog in UI; existing gateways will break).

Frontend:
- Settings → new "Channels" section above Storage. Shows the full
  inbox URL (anchored to hubBase || location.origin), masked token
  with Show/Hide, Copy buttons for both, regenerate button with
  red warning.
- Loaded as part of refreshAll(); silently noops in local-only mode
  (no hub = no token to display).

Docs:
- docs/channels.md — architecture diagram, full bridge protocol
  spec (POST shape + status codes), step-by-step OpenClaw setup
  including the official Tencent CLI command, examples for n8n /
  custom scripts / iOS Shortcuts. Marks automate/bots/ as frozen
  (no removal in v4.5.x — old installs keep working).

Smoke test passed: 401 without token / 401 with bad token / 400
on empty text / 503 (not 500) when no LLM provider.

NOT in this release (v4.5.7 candidates):
- Outbound attachments (text-only for now)
- Async 202-then-callback mode for long agent runs
- "Channels wizard" that runs npx OpenClaw install commands for
  the user

Bumps to 4.5.6; Android versionCode 16.
v4.5.6
2026-04-26 13:42:22 +00:00
Claude 6079715852 fix(v4.5.5): show current version in local mode + in-app APK install
User feedback on v4.5.4:
- "App version" line in Settings stayed blank (...) on local-mode
  installs because it read status?.version, which only loads when a
  hub is reachable. They couldn't tell which version they had.
- Clicking "Download & install APK" bounced them to the system browser
  instead of installing in-app — the user said it "feels weird" to
  download in browser then have to manually run the installer.

Two fixes:

1. Bundle version with the SPA
   - New automate/frontend/version.js sets window.AUTOMATE_VERSION =
     "4.5.5". Loaded before app.js so it's always available.
   - app.js currentVersion() prefers status?.version (definitive),
     falls back to window.AUTOMATE_VERSION, then "?".
   - Settings App-version block now shows "Current: v4.5.5" always.
   - Update result UI clearer:
     - Same version  -> green box "✓ You're already on the latest
       version (v4.5.5)."
     - Newer available -> amber box "v4.5.6 is available (you have
       v4.5.5)." with the install button.

2. Don't bounce .apk to the system browser
   - v4.5.1's shouldOverrideUrlLoading caught all http/https links
     and routed them to ACTION_VIEW (system browser). The "Download
     & install APK" button hit this too, so the in-app
     DownloadListener that was supposed to grab the APK never fired.
   - MainActivity.kt: shouldOverrideUrlLoading now returns false
     early when target path ends with .apk (case-insensitive). That
     lets WebView begin the navigation, which lets DownloadListener
     fire, which calls downloadAndInstall() -> DownloadManager ->
     FileProvider -> system installer.
   - Net effect: tap button -> "Downloading update…" toast ->
     download notification in shade -> system installer pops
     automatically. No browser detour.
   - Button copy updated to "Download & install in app" to match.

Bumps to 4.5.5; Android versionCode 15.
v4.5.5
2026-04-26 13:25:55 +00:00
Claude 61ba7218cf fix(v4.5.4): make local mode actually useful (no hub required)
User feedback: "auto-update doesn't work, asks for hub. file upload
doesn't work, asks for hub. just delete this hub thing, why doesn't
anything work, just store everything locally."

The frustration is justified. Several features were accidentally
gated behind a hub even though they don't structurally need one. This
fixes the worst offenders so the phone-only experience is honest:
some things work, some need a hub, and the difference is clear.

Update check (no hub):
- checkForUpdates() now hits api.github.com/repos/.../releases/latest
  directly from the SPA. The hub fallback is kept for users with a
  custom AUTOMATE_UPDATE_URL mirror that requires server-side proxy.
- Same response shape — UI didn't have to change.
- Mirror parameter still works client-side (rewrites GitHub URLs).

Files (no hub):
- local-store.js gains files_meta + files_blob object stores
  (IndexedDB schema bumped to v2; migration is "create the new stores").
- createFile/listFiles/getFileBlob/deleteFile/filesUsage methods.
- app.js loadFiles/uploadFiles/deleteFile fork on storageMode and
  call localStore in local mode, hub in connected mode.
- Files tab UI: drops the "Files need a hub" empty state. Shows
  "Stored on this device (IndexedDB)" when local, with a hint about
  connecting a hub for unlimited storage.
- Download button: hub mode → /api/files/{id}/raw URL; local mode →
  one-shot blob URL via downloadLocalFile().
- Record button hidden in local mode (transcription is Pro-only and
  requires the hub anyway).

Home banner copy:
- Old: "Notes & memory live on this device. Files, reminders and tools
  work once you connect to a hub."
- New: "Notes, files, memory, and update checks all work locally — no
  hub needed. For AI chat, automation tools, integrations, and bots,
  run a copy of autoMate on a computer/server (the 'hub') and paste
  its URL in Settings."
  Links to openSettingsToHub() so the user lands on the right field.

Also bundles v4.5.3 (in-app notice modal replacing native alert) which
was committed but not yet released. The two ship together.

Bumps to 4.5.4; Android versionCode 14.
v4.5.4
2026-04-26 13:11:38 +00:00
Claude cef810afb7 fix(v4.5.3): replace native alert() with in-app notice modal
User screenshots showed the v4.5.1 "Provider configuration lives on
the hub" alert rendered as Android WebView's native dialog, with the
ugly "网址为'file://'的网页显示" header that looks like a browser
warning. Worse, dismissing it dropped them into Settings at whatever
scroll position the sheet was last at — so they never saw the Hub URL
field they were supposed to fill in.

Two fixes:

1. Replace ALL 8 native alert() calls with a proper in-app modal
   (rendered as a centered card with icon, title, body, and CTAs).
   Same UX everywhere; nothing branded "file://" anymore.
   - Provider wizard pre-flight (the one in the screenshot)
   - Audio recording Pro gate
   - Microphone denied
   - Sync hub-empty / success / failure
   - Push permission / setup / test

2. New openSettingsToHub() helper: opens the Settings sheet, scrolls
   the Hub URL section into view via scrollIntoView, and flashes an
   amber ring around it for 2.4s so the user knows where to look.
   The provider wizard's "Open Settings" CTA uses this.

Better copy too — instead of "Provider configuration lives on the
hub", we now explain what a hub IS in plain language: "AI providers
(Kimi, Claude, etc.) run on a 'hub' — a copy of autoMate running on
your computer or server. Your phone talks to it over Wi-Fi."

Bumps to 4.5.3; Android versionCode 13.
2026-04-26 13:07:41 +00:00
Claude 678c169aee feat(v4.5.2): user-configurable storage location for files / videos
Default stays at ~/.automate/files (no migration needed for existing
installs). Users can repoint to an external SSD or shared drive via
Settings → Storage location.

Schema:
- files_meta gains a nullable storage_root column. ALTER runs once on
  start for existing dbs (pre-v4.5.2 rows keep storage_root=NULL and
  resolve to PATHS.files; new rows record their root explicitly).

Backend:
- automate/files.py: storage_dir(db) reads files.storage_dir from the
  KV settings, mkdirs + falls back to PATHS.files on error so a broken
  config never bricks uploads. set_storage_dir validates: non-empty,
  creatable, is-a-directory, write-probe. store_blob writes to the
  current dir + persists storage_root per row. open_blob resolves via
  per-row storage_root with PATHS.files fallback for legacy rows.
  delete_file's GC uses open_blob() so it cleans up wherever the blob
  actually lives.
- automate/server/api/system.py:
  - GET /api/system/storage → {current, default, is_default, used_bytes}
  - PUT /api/system/storage {path} → validates and persists; 400 with a
    real message on a bad path (not 500).

Frontend:
- Settings ⚙ gets a "Storage location" section above "Check for updates".
  Shows current path + (default) badge if unconfigured + total used
  bytes. Path input pre-fills with the current value so it's edit-not-
  retype. Save button POSTs and shows ok/error inline.
- loadStorage() runs in refreshAll() and silently no-ops in local-only
  mode.

Bumps to 4.5.2; Android versionCode 12.
v4.5.2
2026-04-26 12:46:56 +00:00
Claude 16baf24120 fix(v4.5.1): mobile provider wizard — clear errors + external links
User reported: on Android, configuring Kimi (and presumably any other
provider) ends in a cryptic "Failed to fetch", and the "Open the
API-keys page" link doesn't actually go anywhere — it looks like the
app jumps back to the home screen.

Root cause #1 (Failed to fetch): the SPA loaded from
file:///android_asset/index.html. With no hub URL in localStorage,
hubBase() returned "" and fetch("" + "/api/...") resolved to
file:///api/... which throws TypeError "Failed to fetch". All provider
paths go through api() so every LLM config hit the same wall.

Fix:
- frontend/app.js api(): pre-flight when location.protocol === "file:"
  and no hub configured, throw a real error pointing at Settings.
  Also wrap fetch() in try/catch and turn raw TypeError into a
  network-diagnostic message.
- frontend/app.js openWizard(): hard-gate when storageMode === "local"
  — pop Settings instead of letting the user paste an API key into
  a dialog that physically cannot save it.

Root cause #2 (link doesn't navigate): target="_blank" links inside a
file:// page have two failure modes in WebView. (a) Without
setSupportMultipleWindows, the browser silently drops the click. (b)
With it but no onCreateWindow handler, the click also drops. (c)
Without shouldOverrideUrlLoading, regular links (without _blank) try
to load https://platform.moonshot.cn inside the WebView, which most
sites' CSP rejects, leaving a blank page that looks like "the app
went back to the home screen".

Fix in MainActivity.kt:
- WebSettings.setSupportMultipleWindows(true) +
  javaScriptCanOpenWindowsAutomatically = true so target="_blank"
  fires onCreateWindow.
- WebChromeClient.onCreateWindow: extract the href from
  hitTestResult.extra and launch Intent.ACTION_VIEW (system browser).
- WebViewClient.shouldOverrideUrlLoading: catch http/https/mailto/tel
  schemes and route them to the system browser. Stay in-WebView only
  for URLs whose host matches the saved hub URL.

Bumps to 4.5.1; Android versionCode 11.
v4.5.1
2026-04-26 12:41:59 +00:00
Claude 436f89b8ff feat(v4.5.0): audio recording + transcription, gated as first Pro tool
Bundles audio into the same release stream — no separate sprint.

- automate/audio.py: provider abstraction with two adapters
  - tencent_asr: best Chinese accuracy, hot-words go in HotwordList
    with weight 5; auto-selected when the tencent_asr connection has
    secret_id/key set.
  - openai_whisper: universal fluency; hot-words injected via the
    `prompt` arg which biases Whisper's decoder.
  - Custom vocabulary is mined locally via TF-IDF over the user's
    notes + recent run results — proper-noun coverage without
    sending the corpus to the cloud server. We send only the top-N
    terms per call.

- automate/tools/audio.py: `audio.transcribe` tool, `tier="pro"`.
  First tool to actually exercise the v4.4 tier gate. Unauthenticated
  agents see {"error": "needs_pro_subscription", "message": "..."}
  and tell the user to sign in.

- automate/server/api/audio.py:
  - POST /api/audio/record: multipart upload, stores blob via the
    existing files store, transcribes synchronously, optionally
    saves a note. Returns 402 (with a clean detail) if no Pro
    session — short-circuits before doing the work.
  - GET /api/audio/providers: tells the SPA whether a provider is
    actually configured on this device.

- frontend Files tab: red Record / ⏹ Stop button next to + Upload,
  with an mm:ss timer. While transcribing we show "Transcribing via
  <provider>…"; when done we show the text, latency, hot-words, and
  a link to the saved note. Pre-flight check: if not signed in,
  pop the Settings sheet immediately rather than letting the user
  record 10 minutes and then telling them.

- Android:
  - AndroidManifest: RECORD_AUDIO + MODIFY_AUDIO_SETTINGS
  - MainActivity: WebChromeClient.onPermissionRequest forwards
    RESOURCE_AUDIO_CAPTURE to ActivityCompat.requestPermissions.
    onRequestPermissionsResult resolves the deferred PermissionRequest.

Bumps to 4.5.0; Android versionCode 10.
v4.5.0
2026-04-26 11:15:03 +00:00
Claude ec48c89157 feat(v4.4.0): Coze-style retrieval + auto-update + login stub
Three additions, each independently testable, all wired through the
existing agent / settings / Android shell.

1. Coze-style hybrid retrieval (SQLite FTS5)

The user's complaint: pure-vector RAG products ("Plot Ode") miss obvious
results; Coze nails the right note. Coze runs BM25 + vector + RRF; the
BM25 half is what catches proper nouns and IDs. SQLite FTS5 ships BM25
for free, no extra deps.

- automate/store/db.py: add notes_fts and files_fts virtual tables with
  content-link triggers (INSERT/UPDATE/DELETE keep them in sync).
  One-shot _backfill_fts() populates them from existing rows on first
  upgrade. FTS5 module is optional in the SQLite build, so failures fall
  back to LIKE quietly.
- automate/notes.py + automate/files.py: list_* uses FTS5 when query is
  set, prefix-matching each whitespace-separated token. UI search inputs
  benefit immediately.
- automate/tools/search.py: new search.find unified tool with structured
  filters (kinds, tags, date_after, date_before). BM25-ranked results
  across notes and files in one call.
- automate/agent/prompts.py: explicit guidance — when the user asks
  "find / search / where is / show me X", call search.find with parsed
  criteria; don't list everything and grep manually.

2. Auto-update (Android auto-install, desktop opens browser)

GET /api/system/update_check returns the latest GitHub Release plus
indexed download URLs per platform. Soft-fails (HTTP 200 with
{current, error}) on network errors so the UI never shows a 500.
6-hour cache. AUTOMATE_UPDATE_URL env override; ?mirror= query param
rewrites GitHub URLs through a CN-friendly proxy.

Frontend Settings ⚙ sheet gets a "Check for updates" section. UA-based:
- Android (TWA APK / Chrome): big "Download & install APK" button.
  Tapping it navigates to the APK URL → MainActivity's DownloadListener
  catches it → DownloadManager fetches to cacheDir/updates/ → on
  completion, BroadcastReceiver fires Intent.ACTION_VIEW with
  application/vnd.android.package-archive via FileProvider → system
  installer pops.
- Desktop / iOS / web: "Open release page" link.

A collapsed "CN-friendly mirror" sub-control lets the user paste a
ghproxy.com-style host that rewrites the asset URLs without changing
the metadata source.

Android changes:
- AndroidManifest.xml: add REQUEST_INSTALL_PACKAGES + a FileProvider
  with authority "${applicationId}.fileprovider"
- res/xml/provider_paths.xml: cache-path "updates"
- MainActivity.kt: setDownloadListener, downloadAndInstall(),
  registered BroadcastReceiver, FileProvider.getUriForFile

3. Login hook + paid-tier decoration (no server enforcement yet)

Modeled on SiYuan: open client, closed cloud server. The server itself
is a separate (closed-source) project that doesn't exist yet. This PR
ships the client side so v4.5+ paid features can plug in without
re-architecting later.

- automate/auth.py: get_session/login/logout/me. Session token stored
  in the existing connections table under id="automate_cloud", Fernet-
  encrypted via Vault. Cloud base URL comes from AUTOMATE_CLOUD_URL.
  When unset, all paths return cleanly: "Cloud sync coming soon", no
  network call attempted.
- automate/server/api/auth.py: /api/auth/{me,login,logout} proxying
  to the configured cloud server.
- automate/tools/registry.py: Tool.tier field ("free" | "pro").
  Default "free"; no current tools are flagged "pro" — the field is
  reserved for v4.5 (audio transcription).
- automate/agent/loop.py: before dispatch, if a tool's tier is "pro"
  and there's no session, return a clean
  {"error": "needs_pro_subscription", "message": "..."} for the LLM
  to relay. No exception, no scary 500.
- frontend Settings: an "autoMate Cloud" section. Configurable state:
  cloud_configured + logged_in. Coming-soon copy when unset; email/
  password form when configured but not logged in; sign-out when logged
  in. Tier badge shown next to email.

4. docs/cloud.md

Spells out the SiYuan-style moat strategy: brand + ops + free quota +
genuinely-cloud-only paid features (transcription, public-content
extraction). Documents the cloud server contract so anyone can fork
the client + run their own backend if they want.

Bumps version to 4.4.0; Android versionCode 9.

Audio recording + transcription deferred to v4.5 — see plan.
v4.4.0
2026-04-26 10:24:08 +00:00
Claude 3b6b6b48a9 feat(v4.3.0): built-in agent + bots (Telegram / 微信公众号 / 企业微信 / 个人微信 stub)
Strategic pivot: autoMate's built-in agent IS the primary chat experience.
Messaging bots become entry points into that same agent. Power-user
"plug autoMate into your other AI" flow stays available via the existing
Connect AI tab — just demoted, not deleted.

Backend: bot framework

- automate/bots/{base,manager,telegram,wechat_oa,wecom,wechat_personal}.py
- Telegram: long-poll worker (no public URL needed, works behind NAT)
- 微信公众号: webhook handler with SHA-1 signature verification, 5-second
  passive-reply XML, soft truncation for long agent responses
- 企业微信: webhook + active push via 主动消息 API (no 5s limit), with
  cached access_token
- 个人微信: stub + risk warning (Tencent doesn't sanction this; pluggable
  for wechaty/itchat backends later)
- Bot configs persist to a new 'bots' SQLite table, encrypted via Vault
- Manager auto-restarts enabled bots on server startup

Backend: API

- GET    /api/bots/catalog          static metadata
- GET    /api/bots                  per-instance state + last_error
- PUT    /api/bots/{id}/config      save (encrypted) — empty fields don't
                                    overwrite, so password fields can be
                                    re-saved without re-typing
- POST   /api/bots/{id}/start       starts background worker / readies webhook
- POST   /api/bots/{id}/stop        idempotent stop
- GET    /api/bots/wechat_oa/webhook    handshake (echostr)
- POST   /api/bots/wechat_oa/webhook    inbound XML, returns reply XML
- GET    /api/bots/wecom/webhook        handshake
- POST   /api/bots/wecom/webhook        inbound, replies via active push

Frontend

- Top nav adds Chat + Bots; mobile bottom nav now Home/Chat/Bots/Notes/More
- Home tab hero is now a big "💬 Chat with autoMate" CTA. Below, "Or chat
  from these channels" surfaces the 4 bot kinds with live status.
  External-AI snippets demoted to a small "Power user" disclosure.
- New Bots tab: card per kind with status badge (running / ready / error /
  stopped), risk note for 个人微信, "Set up" → modal with the kind's
  config fields, Start/Stop buttons, last_error inline.
- Webhook URL for 公众号 / 企业微信 shown in the modal, prefilled with
  the connect.base_url so the user can copy it into the platform's
  backend.

Bumps version to 4.3.0.
v4.3.0
2026-04-26 08:14:18 +00:00
Claude be07d9f5aa feat(ui): mobile redesign — Home tab makes the 'AI NAS' identity obvious
Three concrete fixes for "looks like a notes app, not what I expected":

1. NEW Home tab — the default landing on every fresh install.
   - Big black hero card: "📦 autoMate · A NAS for any AI"
   - "Plug your AI in" — 4 quick-pick cards (Claude Code, Kimi, ChatGPT,
     Ollama) that jump to the Connect tab pre-filtered
   - Quick actions: New note · Upload file · Set reminder · Get AI snippet
   - "Your warehouse" stats: live counts of notes / files / pending
     reminders, plus the last-edited note's title and time
   - Local-mode hint is small and contextual, with a link into Settings.

2. Top bar simplified — drops the confusing hub-URL input that used to
   live in a yellow banner, replaces it with a clear identity line:
   "autoMate · A NAS for any AI". A ⚙ icon (top right) opens a Settings
   bottom-sheet where the hub URL config now lives. Most users on the
   APK never need to touch it; advanced users find it in one obvious
   place.

3. Bottom nav reordered — Home / Notes / Files / Reminders + More.
   Connect AI moves into the More sheet (the Home tab's hero already
   surfaces it on the landing page, so the dedicated tab is for the
   detailed snippet view).

Plus: Kimi Code provider added.
   - New ProviderSpec id="kimi_code" with adapter=anthropic and base
     "https://api.moonshot.cn/anthropic" — Moonshot's Anthropic-
     compatible endpoint that Kimi for Coding / Kimi Code CLI uses.
     Same Moonshot API key works; the only difference is the endpoint
     and Anthropic message format.
   - Wizard pick list now shows "Moonshot Kimi (web API)" alongside
     "Kimi Code (Anthropic API)" so users know which one to choose.

Plus: mobile typography polish.
   - styles.css: -webkit-text-size-adjust: 100% (no iOS auto-zoom)
   - inputs/textareas at min 16px (no iOS focus-zoom)
   - tap-highlight-color: transparent (cleaner taps on Android)

Bumps version to 4.2.6.
v4.2.6
2026-04-26 05:45:09 +00:00
Claude 9db59451ac fix(ui): mobile-first layout — bottom nav, full-bleed modals, single-column
The v4.2.4 APK loaded the SPA correctly but rendered the desktop layout
on a 360px phone, with the 6-tab top nav cropped off-screen and content
crammed into a corner. This commit makes the SPA actually behave like
a phone app on small screens.

Top bar
- Logo + active-tab title (instead of static "autoMate") + truncated
  status badges on the right
- Tab nav hidden on mobile (`hidden md:flex`) — replaced by the bottom
  nav described below
- Smaller padding (`px-3 sm:px-6`)

Bottom nav (mobile only, `md:hidden`)
- Sticky bottom strip with 4 icon+label tabs (Notes / Reminders / Files /
  Connect) plus a "More" entry that opens a bottom-sheet listing the
  secondary tabs (Tools / Models / Help)
- Honours iOS safe-area-inset-bottom

Banner
- Local-mode banner stacks vertically on small screens, the URL input
  goes flex-1 to fill, the "Sync" button shrinks to one word

Modals
- Welcome modal becomes full-screen on mobile (no extra padding wasted)
- Wizard step badges shorten ("1·Pick", "2·Key", "3·Done")
- Provider + integration modals full-bleed on mobile, max-h-screen with
  scroll, larger tap targets

Notes tab
- Mobile: list view when no note is open, editor when one is. A "← Back
  to list" link returns. Desktop unchanged (3-col split).
- "+ New note" stays accessible from the header on both layouts

Bumps version to 4.2.5.
v4.2.5
2026-04-26 05:31:37 +00:00
Claude 9aafaba613 fix(apk): blank screen — absolute resource paths broke file:// loading
The APK loads the SPA from file:///android_asset/index.html. The HTML
referenced resources via absolute paths (/styles.css, /local-store.js,
/app.js, /icon-*.png) which the WebView resolves to file:///styles.css
etc. — outside the assets folder, so all 404. Without app.js the Alpine
data binding was never registered, so:

  - tabs (Notes/Files/etc) didn't render — `tabs` was undefined
  - the active section stayed hidden — `active === 'notes'` couldn't
    evaluate
  - only the hardcoded header text + Tailwind/Alpine CDN scripts
    survived, hence the blank screenshot below the header

Fix: switch every internal resource link to a relative path. They still
work fine when the SPA is served over HTTP (relative to /), and they
now also resolve correctly inside the APK (relative to
file:///android_asset/).

Also gate service-worker registration on `location.protocol` starting
with "http" so the registration call doesn't throw a NotSupportedError
on file:// origins.

Bumps version to 4.2.4.
v4.2.4
2026-04-26 05:21:22 +00:00
Claude b1e87ecf58 ci: release notes mention the APK + iOS PWA paths 2026-04-26 05:15:10 +00:00
Claude 4c27b85666 fix(ci): make release job wait for android so the APK actually lands
In v4.2.2 the APK build succeeded but the release was published before
the android job finished — release.needs only listed [resolve, build,
extension, wheel] so it ran in parallel with android instead of waiting
for it.

Adding android to release.needs makes the release wait. The existing
\`if: always() && needs.resolve.result == 'success' && needs.build.result
== 'success'\` keeps the release tolerant of an APK build failure (we
publish the rest), so this only adds latency when android succeeds —
which is what we want.

Bumps version to 4.2.3.
v4.2.3
2026-04-26 05:14:01 +00:00
Claude f2af2000fa ci: actually drop the Pages job (previous commit only bumped versions) v4.2.2 2026-04-26 05:12:46 +00:00
Claude cd956d9937 ci: drop the Pages job — APK is self-contained, Pages was a leftover
The pages job was originally needed to host the PWA so the Bubblewrap
TWA APK could wrap a public HTTPS URL. v4.1.1 replaced that with a
native Android project that bundles the SPA into the APK assets
directly, so Pages stopped doing any useful work — but it kept failing
on every run because the default GITHUB_TOKEN lacks permission to
enable Pages on repos that haven't been configured for it.

Just remove the job. The APK ships fine without it; users access the
SPA via their hub URL (laptop LAN IP, ngrok tunnel, or future relay).

Bumps version to 4.2.2.
2026-04-26 05:12:08 +00:00
Claude b8367d65e8 fix(android): missing gradle.properties broke the APK build
AGP 7+ refuses to build without `android.useAndroidX=true` in
gradle.properties — that file didn't exist in v4.2.0, which is why the
gradle build exited with code 1.

Adds android/gradle.properties with the AndroidX flag plus standard
performance/caching settings. Also pins gradle-version: "8.7" on the
setup-gradle action so the runner doesn't try to use a missing wrapper,
and adds --stacktrace + a "show versions" step so the next failure (if
there is one) is diagnosable from the log alone.

Bumps version to 4.2.1.
v4.2.1
2026-04-26 05:09:21 +00:00
Claude 265b0b95de feat(v4.2.0): smart NAS for AI — phone works standalone, opt-in sync
Repositioning: autoMate is "a smart NAS for AI", not "a chat hub". The
phone APK and PWA now work without a hub at all (local mode, notes +
memory in IndexedDB). Connecting to a hub is a one-step "Sync &
connect" action that pushes local data up, pulls hub data down, and
flips the SPA into connected mode for the next reload.

Local mode (phone-first)

- New automate/frontend/local-store.js: IndexedDB store for notes +
  memory with full CRUD, search, tags, pin, and an export/import that
  supports last-write-wins merge.
- app.js: detects connectivity at boot via /api/health, sets
  storageMode = 'local' | 'connected', dispatches notes ops to the
  right backend.
- A persistent yellow banner across the top of the SPA in local mode,
  with an inline "hub URL → Sync & connect" control.
- Files / Reminders / Models / Tools / Connect AI tabs each render an
  honest "needs hub" placeholder when in local mode — no fake-working
  UI, clear next step.

APK (Android)

- MainActivity drops the forced hub-URL prompt. Loads the SPA, lets it
  detect mode. Saved hub URL (from previous sessions) still gets
  injected so connected mode persists.
- versionCode 2 / versionName 4.2.0.

Repositioning everywhere

- Welcome modal headline: "A smart NAS for AI."
- Top-level page title, FastAPI app title/description, CLI description,
  pyproject description, package docstring all rewritten around
  "warehouse / storage / tool library, plug any LLM in".
- README + README_CN rewritten: smart-NAS framing, two-level deployment
  (local-only vs hub), four-mode connect snippets, mobile install paths.
- New docs/sync.md: deployment shapes, free vs (planned) paid tiers,
  conflict-resolution roadmap, privacy notes.

Bumps version to 4.2.0.
v4.2.0
2026-04-26 04:24:36 +00:00
Claude 9cabf2df0e fix(android): self-contained APK that doesn't depend on Pages
Replaces the Bubblewrap/TWA approach (which needed a public PWA URL
and was the reason no APK landed in v4.1.0) with a from-scratch native
Android project under android/.

What's in the APK
- Kotlin AppCompat activity (MainActivity.kt) hosting a single WebView
- The full automate/frontend/ SPA bundled into app/src/main/assets/ at
  build time — no GitHub Pages, no external manifest, the APK is
  self-contained
- First-launch dialog asks for the hub URL (laptop LAN IP or relay),
  saves it in SharedPreferences, injects it into the SPA's localStorage
  so all the existing remote-hub plumbing just works
- Menu: Change hub URL · Reload
- Launcher icons in all 5 standard densities, generated from the PWA
  icon

CI changes
- android job no longer needs the pages job at all
- Uses temurin JDK 17 + setup-android@v3 + setup-gradle@v3
- Stamps the version tag into app/build.gradle's versionName, then
  `gradle assembleDebug` and uploads the resulting APK
- Signed with the standard Android debug keystore so users can sideload
  the APK from the GitHub Release without us shipping private keys

iOS reality
- New docs/mobile.md spells out: iOS = PWA only (Apple Developer fee,
  Xcode-on-macOS, App Store review = not happening for a free OSS tool).
  Safari "Add to Home Screen" is the iOS install path; documented step
  by step.

Bumps version to 4.1.1.
v4.1.1
2026-04-26 04:12:02 +00:00
Claude a919482fb4 fix(ci): unblock release when Pages isn't enabled; bump 5.0.0 → 4.1.0
The previous run failed at actions/configure-pages because the repo
didn't have Pages enabled, which then took down the whole release job
(it depended on `pages` and `android`).

Two-part fix:

- Pass `enablement: true` to actions/configure-pages so it auto-enables
  Pages on first run with the existing pages: write permission.
- Mark the `pages` job continue-on-error: true at the job level. Drop
  `pages` and `android` from `release.needs`. The release now hard-depends
  only on resolve + the binary build matrix; Pages/APK are best-effort
  and the release simply omits any artifact that didn't materialise
  (`fail_on_unmatched_files: false`).

Also: this iteration is additive, not a breaking change. Roll back the
version from 5.0.0 to 4.1.0 — semver minor bump for the personal-infra
features (notes / files / reminders / memory / Web Push / PWA assets).
v4.1.0
2026-04-26 04:04:59 +00:00
Claude 23454bd88a feat(v5): personal-infra layer — notes / files / reminders / memory + PWA + APK
Major repositioning from "another chat hub" to "the brain behind any AI
you already use". Don't switch chat apps; switch what's behind them.

New core capabilities (each is both a UI tab and a tool category)

- notes/        Markdown documents, tags, search, pin. notes.{create, search,
                read, update, delete} as tools.
- files/        Content-addressed local vault, dedup by SHA-256, multipart
                upload, streaming download. files.{put, list, read, delete}.
- reminders/    Background scheduler thread polls every 30s; due reminders
                fan out as Web Push to subscribed PWAs. Recurring (hourly/
                daily/weekly) supported. reminders.{create, list, snooze,
                dismiss}.
- memory/       Long-term key-value facts. memory.{set, get, list, delete}.

Web Push (VAPID)

- VAPID keypair auto-generated on first run, stashed in DB.
- /api/push/{config,subscribe,test} for the PWA to subscribe.
- service-worker.js handles 'push' and 'notificationclick' events.
- pywebpush dep added (graceful fallback if not installed).

UI restructure

- Top nav: Notes | Files | Reminders | Connect AI | Tools | Models | Help.
- Chat tab gone from main nav (still exists for debug; agent loop unchanged).
- Welcome modal copy: "Your AI's brain. Don't switch chat apps."
- Empty states + 'Enable notifications' card in Reminders.

Mobile / multi-platform packaging

- New `pages` job in build.yml: deploys frontend/ to GitHub Pages so the
  PWA has a public HTTPS origin.
- `android` job updated: Bubblewrap reads the manifest from the GH Pages
  URL and builds a TWA APK. Best-effort (continue-on-error) — a missing
  APK doesn't block the release.
- Web Push subscription survives the PWA being installed to home screen,
  so reminders fire even when the app is closed.

Backend wiring

- 6 new SQLite tables, indexed for the queries each module uses.
- 5 new API routers mounted under /api.
- 4 new tool categories registered first in the catalog (these are
  autoMate's identity now).
- Background scheduler started from server state; stops cleanly.
- python-multipart + pywebpush added as core deps.

README, frontend headline, welcome wizard all rewritten around the new
"personal infra, bring any AI" positioning.

Bumps version to 5.0.0.
v5.0.0
2026-04-26 03:57:49 +00:00
Claude 03696953c7 feat: PWA on phone + remote-hub config + relay client scaffold
Ships the infrastructure for the "any AI, anywhere" story without yet
adding a chat UI on the phone (the phone is a controller, not a host).

PWA
- manifest.webmanifest, service-worker.js, and 32/192/512 icons added
  to automate/frontend/. The SW caches the SPA shell offline-first;
  /api and /oauth always go to the network.
- index.html links the manifest, registers the SW, sets theme-color
  and apple-mobile-web-app-capable so iOS Safari treats it as a real
  app when added to the home screen.
- Help tab gets a "Use it on your phone" section walking the user
  through `automate serve --host 0.0.0.0` → find LAN IP → open in
  mobile Chrome → Add to Home Screen.

Remote hub
- app.js now reads localStorage `automate-hub-base` and prefixes every
  fetch + WebSocket URL with it. Default empty = use the current origin.
- New "Connect this UI to a different hub" panel in Help lets the user
  point the (PWA) UI at any reachable hub URL — useful when a phone's
  installed PWA needs to reach the laptop on a different IP, or via the
  relay.

Relay client
- New `automate.relay` module: persistent WS to a relay endpoint,
  forwards inbound HTTP frames into the local FastAPI app.
- New CLI subcommand `automate relay <url> --token …`.
- `relay` extra in pyproject (websockets + httpx).
- docs/relay.md fully specifies the wire protocol, threat model, and a
  ~150-line FastAPI sample relay implementation, plus the roadmap
  (E2E encryption, WS tunnelling, hosted relay).

Android
- New `android` job in build.yml uses Bubblewrap to attempt a TWA APK.
  Marked continue-on-error: a missing APK doesn't block the release.
  Recommended path remains "install the PWA from the hub URL".

Bumps version to 4.0.5.
v4.0.5
2026-04-26 03:39:45 +00:00
Claude 193cdcfd28 feat(ui): guided setup wizard + 'Connect any AI' tab + snippet endpoint
Two big additions, both pointing at the same insight: autoMate isn't only
for the chat in its own window — it's a hub that any AI should be able to
plug into.

Setup wizard
- Replaces the cold "fill out this modal" flow with a 3-step page wizard:
  pick a provider (7 popular ones surfaced as cards) → guided "get your
  key" with deep-link → paste + auto-test + auto-activate → 🎉 done page
  with three follow-up suggestions (open chat / connect more AIs / wire
  in tools).
- Triggered from the welcome modal, the Chat empty state, and any time
  the user has no model configured. Reuses the saveAndUse() machinery
  underneath, so no double implementation.

Connect AI tab (new top-level tab)
- New /api/connect endpoint emits four ready-to-paste snippets, each
  parameterised with the user's local base URL:
    mcp       — full MCP config JSON for Claude Code / Cursor / Cline /
                Kimi K2 / etc.
    http      — system-prompt fragment for any LLM that can call URLs
                ("POST /api/agent/run with this body, use it whenever
                the user asks for something concrete")
    bridge    — shell wrapper + system prompt for tool-less LLMs (basic
                Ollama, web chat) that can only emit text
    discover  — OpenAPI URL for agents that can read schemas
- Each snippet has a one-click Copy button + clear "use this when…" line.
- Security note explains the 127.0.0.1 binding and how to opt into LAN
  exposure.

Polish
- Welcome modal subtitle now leads with "one hub, any AI" instead of
  just "chat in this window".
- Help tab opens with a blue banner pointing at Connect AI.
- Chat empty state has a third link: "Use from a different AI".

README rewritten — leads with "one hub, any AI", followed by the four
connection modes table, before the install instructions.

Bumps version to 4.0.4.
v4.0.4
2026-04-26 03:24:32 +00:00
Claude dbdcb2a558 fix(ui): one-click model + integration setup, sensible defaults
Configuring a model used to be: paste key → click Save → close modal →
find card again → click "Use this". Way too many steps. Plus the default
model for some providers required tier upgrades the user didn't have
(e.g. Kimi defaulted to kimi-k2-0711-preview).

Models tab
- ONE button: "Save and use this provider" — saves credentials, runs
  a 1-token test call, sets as active, closes the modal on success.
- API key is the only field shown by default. Base URL + model name
  collapsed into "Advanced".
- Defaults changed to the most-universal models per provider:
    Anthropic   claude-opus-4-7   →  claude-sonnet-4-6
    Kimi        kimi-k2-0711-preview → moonshot-v1-8k
    GLM         glm-4.6           →  glm-4-flash  (free)
    Doubao      doubao-seed-1-6   →  (none — clarified that Ark uses
                                       endpoint IDs, not model names)
- Test failures get a diagnostic hint (401/404/403/timeout patterns).

Tools tab
- Per-integration "How to get this" block in the modal — each of the 31
  integrations now has a label, the right deep-link to the page where
  you create the token, and a one-line guide.
- Single password field + ONE button: "Save and connect".
- OAuth flow tucked under "Use OAuth instead (advanced)" — keeps the
  page clean for the 90% case where pasting a token is fine.
- Search box at the top to filter the 31 cards.
- Inline success/error feedback, modal auto-closes on success.

Bumps version to 4.0.3.
v4.0.3
2026-04-26 03:05:44 +00:00
Claude 334df381f7 feat(ui): first-run welcome wizard + Help tab + better empty states
The previous build dropped a brand-new user into a chat box with no
guidance. Now:

- Welcome modal auto-opens on first visit when no provider is configured.
  Three numbered steps + a "Configure my first model →" button that
  jumps to the Models tab. Persists dismissal in localStorage.
- New Help tab — quickstart, runnable examples (with "Try it" buttons),
  browser-extension instructions, MCP setup snippet for Claude Code /
  Cursor / Cline / Kimi, full tool catalog by category, privacy notes.
- Chat tab: when no model is active, shows an empty-state CTA pointing
  to Models instead of letting the user send a doomed message.
- Quick prompts in the Help tab are categorised by which subsystem they
  exercise, so users learn the model by trying.

Bumps version to 4.0.2.
v4.0.2
2026-04-26 02:52:29 +00:00
Claude 67a1aefb41 fix(cli): default to serve when no subcommand given
Double-clicking automate.exe used to print argparse help and exit, which
looked like a crash to anyone expecting a GUI to pop up. Treat empty
argv as `serve` so the BS hub boots and the browser auto-opens. CLI
users still get help via `automate -h`.

Also makes the startup banner more legible so the URL is obvious in the
console window that appears on Windows double-click.

Bumps version to 4.0.1.
v4.0.1
2026-04-26 02:40:34 +00:00
Claude 63e9b7a9c5 release: v4.0.0 v4.0.0 2026-04-26 02:26:58 +00:00
Claude 778f262b07 ci: also trigger Build & Release on release-v* branch push
Allows kicking off a release in environments that can push branches but
not tags (e.g. some hosted git proxies). The resolve job derives the tag
from the branch name (release-vX.Y.Z → vX.Y.Z), creates the tag, and the
final release step deletes the trigger branch on success.

Tag push, branch push, and workflow_dispatch all converge on the same
build matrix.
v1.0.0
2026-04-26 02:23:31 +00:00
Claude 813274e207 ci: trigger Build & Release on tag push, make PyPI publish opt-in
build.yml
- now triggers on push tag v* AND workflow_dispatch
- replaces the tag-creating job with a small resolver that uses
  GITHUB_REF_NAME on push, or creates the tag on workflow_dispatch
- adds a wheel job so the GitHub Release also carries the .whl + .tar.gz
- release notes match the new install matrix (binary/pip/docker/extension)

publish.yml
- restricted to workflow_dispatch only — PyPI trusted publisher needs a
  one-time setup; auto-publish would fail noisily until that's in place
2026-04-26 02:21:57 +00:00
Claude 6c7d6e41da fix(packaging): PyInstaller entry script + path-relative spec
PyInstaller treats the entry script as a top-level module, so
automate/__main__.py's relative import (`from .cli import main`) blew up
at runtime. Add packaging/launcher.py as a thin absolute-import wrapper
and point the spec at it.

Spec file now resolves all paths via SPEC location so the build runs
correctly from the project root (which is what the GitHub Actions
workflow does).

Verified locally: 37MB Linux x64 binary, doctor + serve work, /api/status
and /openapi.json return 200.

https://claude.ai/code/session_01KLygewzdXxieWmndwGVBEf
2026-04-26 02:17:49 +00:00
Claude f11b562695 feat: browser extension, packaging revamp, integrations folded into package
Browser extension (extension/)
- Manifest V3 service worker holds a WebSocket to the local hub and
  dispatches commands against the user's real browser — their tabs,
  cookies, logged-in sessions
- Popup shows pairing status; auto-reconnect with exponential backoff and
  a chrome.alarms keepalive ping so the worker isn't suspended mid-call
- Content script handles DOM operations (CSS or text= selectors)
- Tools exposed: bx.{tabs,open,activate,close,navigate,screenshot,click,
  type,extract,scroll,eval}

Bridge
- automate/extension_bus.py bridges sync tool handlers ↔ async WS via a
  threading.Event + asyncio.Queue, single-extension semantics
- automate/server/api/extension.py mounts /api/extension/{ws,status}
- /api/status now reports extension_connected; UI shows a live dot

Packaging
- packaging/automate.spec — PyInstaller spec wired to automate/__main__,
  bundles the static SPA, excludes heavy ML deps
- .github/workflows/build.yml — manually-triggered Windows / macOS-arm64 /
  Linux build matrix that also packs the extension and publishes a
  Release with all four artifacts
- Dockerfile + .dockerignore — python:3.12-slim base with Playwright
  Chromium preinstalled; binds 0.0.0.0:8765, mounts /data
- Wheel + sdist build verified locally (102KB wheel installs into a
  clean venv, `automate doctor` reports 22 tools / 25 providers; bound
  server returns 200 on / and correct status JSON)

Restructure
- integrations/ → automate/integrations/ for one-package cohesion;
  adapter import path updated; setuptools find scope tightened
- README + README_CN: new install matrix (pip / binary / Docker /
  extension), project-layout map, updated tool inventory

https://claude.ai/code/session_01KLygewzdXxieWmndwGVBEf
2026-04-26 02:11:23 +00:00
Claude 9a3ef7b114 feat: v1.0.0 — redesign as a BS scheduling hub
Rebuild the project around a single thesis: any LLM can plan, but it can't
reach into your local shell, your browser session, or your SaaS accounts.
autoMate is the executor that fills that gap.

What's new
- automate/ package with FastAPI server, SQLite + Fernet credential vault
- 25-provider LLM catalog (OpenAI / Anthropic / Gemini / Kimi / Qwen /
  DeepSeek / Doubao / GLM / Yi / MiniMax / Hunyuan / Baichuan / StepFun /
  Mistral / Grok / OpenRouter / Groq / Together / Fireworks / DeepInfra /
  Cohere / Ollama / LM Studio / vLLM)
- Tool registry feeds three doorways from one source of truth: REST,
  WebSocket, and stdio MCP
- Three local executors with proper isolation: shell.exec, script.run
  (Python/Bash/Node), browser.* (Playwright), desktop.* (pyautogui)
- 31 SaaS integrations adapted into the registry via a shim — drop-in
  reuse of the existing integrations/ tree
- OAuth click-through for GitHub / Notion / Slack / Linear / 飞书 / 钉钉
  with state token + encrypted client_secret storage
- Static SPA (Tailwind + Alpine, no build step) for onboarding, model
  config, tool marketplace, live chat, run history
- automate {serve,mcp,doctor} CLI

Removed
- Old top-level entry points (cli.py, mcp_server.py, install.py, main.spec)
- auto_control/, core/, util/ legacy modules superseded by automate/
- cloud_vision.py (HF Inference Endpoints flow can return as an optional
  tool later)
- task_demonstration.json (10MB demo data not needed in the package)
- .github/workflows/build.yml (PyInstaller path; pip install + automate
  serve is the new install story)

Smoke tested: 19 REST endpoints + 1 WebSocket + OAuth callback all live,
frontend served, 25 providers + 31 integrations + 11 local tools registered.

https://claude.ai/code/session_01KLygewzdXxieWmndwGVBEf
2026-04-26 01:55:53 +00:00
Claude 691cac50d2 docs: remove demo video from all READMEs
https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
2026-04-23 23:50:26 +00:00
Claude 7165ed2961 feat: v0.8.0 — 31 platforms, competitive positioning, local-first
Merged from claude/optimize-multi-platform-uz5mK:
- 5 new integrations: Stripe, Shopify, Confluence, Asana, Monday.com
- All 3 READMEs updated with competitive comparison vs Composio/Zapier
- New "local-first, zero cloud dependency" positioning angle
- pyproject.toml bumped to v0.8.0

https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
2026-04-23 23:41:10 +00:00
Claude afe1f14de7 feat: v0.8.0 — expand to 31 platforms, add competitive positioning
New integrations (5):
- Stripe: balance, customers, payments, subscriptions, products
- Shopify: products, orders, customers, collections, shop info
- Confluence (Atlassian): search/get/create pages, list spaces
- Asana: workspaces, projects, tasks, create/update tasks
- Monday.com: boards, items, groups via GraphQL

Updated:
- integrations/__init__.py: register all 31 integrations
- mcp_server.py: updated instructions with new platforms
- pyproject.toml: bump to v0.8.0, 31 platforms in description
- README.md / README_CN.md / README_JA.md:
  - Updated platform count to 31
  - Added competitive comparison table vs Composio/Zapier/Claude Connectors
  - New tagline: local-first, zero cloud dependency
  - New FAQ entry on competitor differentiation
  - Added Payments & E-commerce section (Stripe + Shopify)
  - Moved Twilio to Messaging section (fits better)

https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
2026-04-23 23:41:06 +00:00
Claude 40eab99974 feat: v0.7.0 — API Tool Center with 26 platform integrations
Merge claude/optimize-multi-platform-uz5mK

autoMate now operates as both an API Tool Center (26 platforms, activated
by env vars) and a desktop GUI automation tool. Integrations auto-register
when their env vars are present; unused ones are silently skipped.

Chinese platforms (8): 飞书, 钉钉, 企业微信, 微信公众号, 微博, Gitee, 语雀, 高德地图
Messaging (6): Slack, Telegram, Discord, Microsoft Teams, Zoom, Twitter/X
DevOps (3): GitHub, GitLab, Sentry
Project mgmt (6): Notion, Airtable, Linear, Jira, Trello, HubSpot
Email/marketing (3): SendGrid, Twilio, Mailchimp

https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
2026-04-23 05:45:54 +00:00
Claude 1264fdd202 feat: v0.7.0 — expand to 26 platform integrations
Add 12 more integrations across Chinese platforms, DevOps, project
management, and email/marketing categories:

Chinese: Gitee (码云), 语雀 (Yuque), 高德地图 (Amap)
Messaging: Microsoft Teams (webhook), Zoom (OAuth2 meetings)
DevOps: GitLab (issues, MRs, pipelines), Sentry (error tracking)
Project mgmt: Trello (boards/cards), HubSpot (contacts/deals)
Email/marketing: SendGrid, Twilio (SMS), Mailchimp

Also add PUT method to BaseIntegration for PATCH-style upserts.
Update FastMCP instructions and all three READMEs for 26 platforms.

https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
2026-04-23 05:45:21 +00:00
Claude c3dc324142 feat: v0.6.0 — API Tool Center with 14 platform integrations
Add integrations/ plugin framework that auto-registers MCP tools for any
platform whose env vars are present. Covers 5 Chinese platforms (飞书,
钉钉, 企业微信, 微信公众号, 微博) and 9 international platforms (Slack,
GitHub, Telegram, Discord, Twitter/X, Notion, Airtable, Linear, Jira).

- integrations/base.py: BaseIntegration ABC with HTTP helpers
- integrations/{feishu,dingtalk,wecom,weixin,weibo}.py: Chinese platforms
- integrations/{slack,github_api,telegram,discord,twitter}.py: Intl messaging
- integrations/{notion,airtable,linear,jira}.py: Productivity platforms
- integrations/__init__.py: register_all() auto-discovery
- mcp_server.py: call register_all(mcp) at startup; update FastMCP instructions
- pyproject.toml: bump to v0.6.0; add integrations* to package discovery
- README{,_CN,_JA}.md: rewrite positioning as API Tool Center + desktop automation

https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
2026-04-23 05:34:01 +00:00
Claude 7c5e79577b feat: v0.5.0 — cloud vision via HF Inference Endpoints
Add cloud_vision.py contributed by @kvk-code:
- OmniParser V2 screen parsing via HuggingFace endpoints (no local GPU)
- UI-TARS / Qwen-VL action reasoning via cloud VLM
- smart_act: full autonomous parse → reason → execute loop
- New MCP tools: cloud_vision_config, warm_endpoints, parse_screen,
  reason_action, smart_act
- Logging to ~/.automate/logs/

Update all READMEs with two-mode architecture (basic / cloud vision)
and @latest tag in all config examples.

https://claude.ai/code/session_01DMcu2ZyvS47ZgEg64QN1iF
v0.5.0
2026-04-22 08:26:45 +00:00
Dongle e001e19db0 Merge pull request #151 from kvk-code/feat/cloud-vision
feat: Cloud vision — screen parsing + action reasoning via HF Inference Endpoints
2026-04-22 16:20:58 +08:00
kvk-code 2905aab6f3 fix: parse UI-TARS action format with nested parentheses
- Add _parse_coordinates() to handle UI-TARS formats:
  - start_box='(x, y)' and start_point='(x, y)'
  - Simple 'x, y' and parenthesized '(x, y)'
  - Truncated variants from incomplete model output

- Fix smart_act action extraction with paren counting:
  - Regex now matches opening paren only
  - Depth-based extraction handles nested parens
  - Fallback for truncated output

- Fix type annotation for pyautogui.screenshot region param

This fixes 'invalid literal for int()' errors when UI-TARS
returns actions like: click(start_box='(166, 88)')
2026-04-18 23:01:31 +05:30