Commit Graph

36 Commits

Author SHA1 Message Date
Teknium a641644f12 fix(paths): display_hermes_home renders POSIX separators on Windows — kills ~/AppData\Local\hermes chimeras in tool schemas and user-facing messages (#97137) 2026-08-28 05:45:00 -07:00
teknium1 1c9433897c chore(skills): standards sweep — bring 42 bundled/optional skills up to hardline
Audited all 191 in-repo skills (77 bundled, 114 optional) against the
authoring standards (AGENTS.md hardline + PR #80800). Fixed 42:

- 8 overlong descriptions rewritten to <= 60 chars, one sentence, period
  (one-three-one-rule 525ch, drug-discovery 405ch, web-pentest 358ch,
  fitness-nutrition 352ch, neuroskill-bci 332ch, oss-forensics 320ch,
  computer-use 307ch, memento-flashcards 252ch)
- 24 skills with missing frontmatter fields: author (credited from git
  history: f-trycua, SHL0MS, teyrebaz33, haileymarshall, FurkanL0,
  teknium1), license, version, platforms, tags
- 7 machine-local paths scrubbed (/home/bb, /home/user, /home/ubuntu ->
  portable placeholders)
- 11 marketing-word intros reworded (Comprehensive/state-of-the-art)
- docs catalogs + per-skill pages regenerated, scope-disciplined

Deferred (not in this PR):
- 14 frontmatter/dir name mismatches — open PR #42788 already proposes
  the dir-rename approach for 4 of them; resolve there as one class
- 2 skills over 100k chars (pytorch-fsdp 159k, research-paper-writing
  103k) — need content splits into references/, separate PRs
- comfyui dangling related_skill resolves after the name-mismatch class
2026-08-08 15:27:29 -07:00
teknium1 ac662c3f71 chore(skills/google-workspace): fold daily-brief into references/, not a sibling skill
The brief is single-connector (every command comes from google-workspace),
so it ships as references/daily-brief.md with a pointer + load trigger in
SKILL.md — progressive disclosure instead of a new skill-index entry.
Contributor's procedure preserved (half-open day windows, mail-to-meeting
linking with fuzzy-match discipline, 7-section brief, bounded actions);
credit noted in the reference header. Tests (8) guard the wiring and
disciplines. Version 1.1.0 -> 1.2.0.
2026-08-08 05:59:37 -07:00
Eugeniusz Gilewski 64dd865912 fix(deps): repair Google transitive security floors (#72108)
Google API and authentication packages permit vulnerable httplib2 and pyasn1
transitives, while the Workspace and Google Chat runtime installers previously
treated any importable version as sufficient. Existing environments could
therefore remain vulnerable after the project dependency pins were repaired.

Carry the fixed versions through the Google and Vertex extras, lazy feature
requirements, lockfile, and both runtime installers. Route the documented
Google Chat installation path through its maintained secure requirements
instead of an unconstrained direct pip command.

Detect stale distributions, install only unsatisfied requirements, and verify
the result before continuing. Behavioral tests cover those repair invariants
without freezing manifests, lockfiles, or complete package sets.

Related #72108
Extracted from #72840
Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
2026-07-31 23:18:38 -07:00
Yorkstone Supplies (sycamoregroupltd) 37e42808e7 fix(security): pin httplib2==0.32.0 in setup.py REQUIRED_PACKAGES (GHSA-j5g9-f88f-gfj3)
The previous fix (904ade32b) pinned httplib2==0.32.0 in pyproject.toml's
google extra and tools/lazy_deps.py's skill.google_workspace, but missed
a third install path: skills/productivity/google-workspace/scripts/setup.py
REQUIRED_PACKAGES. A user following the --install-deps path could still
resolve httplib2 via unpinned ranges.

This commit:
1. Exact-pins all four Google packages in REQUIRED_PACKAGES to match
   pyproject.toml and lazy_deps.py contracts exactly.
2. Adds a focused regression test that parses setup.py's REQUIRED_PACKAGES
   via AST and asserts every pin matches the other two install paths.

Changelog: fix(security), test(security)
2026-07-31 22:28:21 -07:00
teknium1 75e0d52034 fix(windows): sweep remaining bare read_text/write_text sites + linter rule
AST-driven pass over every Path.read_text()/write_text() without an
explicit encoding= across non-test code: 71 sites in 34 files
(skills_hub, hermes_cli/main+profiles+service_manager+container_boot,
mem0/hindsight/honcho plugins, achievements dashboard, release/CI
scripts, productivity+comfyui skill helpers, agent/*). Verified zero
positional-encoding collisions before insertion; per-file compile()
check after.

Adds a check-windows-footguns rule flagging bare single-line
read_text/write_text (multi-line forms stay covered by the AST guard
test from #38985). Together with the salvaged contributor commits this
retires the ~169-site bare file-I/O class (#37423's long tail).
2026-07-24 17:10:39 -07:00
Stoltemberg c89481db5e fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428)
On Windows with Chinese locale (GBK), subprocess.run(text=True) without
explicit encoding causes UnicodeDecodeError crashes. This fix adds
encoding='utf-8', errors='replace' to all subprocess.run() and
subprocess.Popen() calls that use text=True across 76 non-test Python files.

Fixes #53428 (master tracker for Windows GBK locale crash).

Note: credential_pool.py and electron changes excluded per reviewer request —
those will be submitted as separate focused PRs.
2026-07-24 11:45:57 -07:00
ethernet d84e11af4d rip out brew + pip/PyPI wheel support (#68217)
Removes Homebrew and PyPI wheel/sdist as Hermes distribution paths while
preserving the supported source, Docker, and Nix workflows.

Changes:
- Removes the Homebrew formula, PyPI publish workflow, sdist manifest
  (MANIFEST.in), and wheel/sdist release-attachment logic from scripts/release.py.
- Keeps setuptools metadata and entry points required by editable installs
  and Docker/Nix builds, but adds a setup.py guard that rejects wheel/sdist
  builds outside a sealed Nix derivation (HERMES_NIX_BUILD=1).
- Removes pip/Homebrew install detection, PyPI update checks, the pip
  self-update path, the deprecation-banner state, the postinstall subcommand,
  wheel data-directory fallbacks in agent/i18n.py and hermes_constants.py,
  and the ACP Registry manifest/version-lockstep release logic.
- Adds /nix/store/ path detection so `nix run` / `nix profile install`
  installs (which don't set HERMES_MANAGED) are correctly identified as
  "nix" rather than falling through to "git"/"unknown".
- Retired install-method values ("pip", "homebrew") in existing
  .install_method stamps (both code-scoped and home-scoped) are ignored by
  the allowlist reader and fall through to "unknown" instead of resurrecting
  a retired enum value.
- Updates Nix packaging to ship bare runtime data (locales, optional-mcps)
  through store symlinks and wrapper env vars instead of wheel data-files.
- Removes the ACP Registry manifest/icon and their version-lockstep tests.
- Deletes or rewrites packaging, pip-update, Homebrew, and ACP Registry
  tests; adds parametrized coverage for the packaging build guard covering
  BOTH sdist and wheel paths (the guards live in separate cmdclass entries
  — a passing sdist test proves nothing about the wheel path).
- Updates installation/platform documentation and related user-facing copy.
- Adjusts the supply-chain scan so deleted install-hook files do not trigger
  a finding, while additions or modifications still require the existing
  ci-reviewed label gate.

Supported installation paths (unchanged):
- git installer (install.sh)
- Docker
- Nix/NixOS
- editable development installs (uv sync, uv pip install -e ., pip install -e .)
2026-07-22 16:51:01 -04:00
Ben Barclay 7c00ffd92c fix(google-workspace): fall back to uv when venv has no pip (#39516)
The Hermes Docker image's venv is built with `uv sync`, which does not
bootstrap pip into the venv. When the google-workspace setup script needs
to install its deps and the running interpreter has no pip,
`sys.executable -m pip install` dead-ends with "No module named pip"
(reported via Discord support).

install_deps() now falls back to `uv pip install --python <interpreter>`
when the pip path fails and uv is on PATH. uv installs into the exact
interpreter the script is running under without needing pip present, so
the pip-less venv self-heals (e.g. a dep evicted on image update, or a
build without the [google]/[all] extra). On environments with neither
pip nor uv, the [google] extra hint is printed as before.

Verified E2E against nousresearch/hermes-agent:latest: under the venv
python with a missing dep, --install-deps now prints "Dependencies
installed." and exits 0 instead of failing.

Adds TestInstallDeps regression coverage: pip path, uv fallback,
uv-not-consulted-when-pip-works control, and both no-installer-available
and uv-also-fails failure cases.
2026-06-05 13:30:02 +10:00
Donovan Yohan 8bd00607dc fix(google-workspace): handle Gmail header casing case-insensitively
Normalize Gmail API message header names to lowercase before lookup so
gmail get/search/reply populate to/subject/from regardless of the casing
the message was stored with. Emit conventional MIME header casing
(To/Subject/Cc/From) on send and reply.

Fixes #34806

Co-authored-by: Donovan Yohan <donovan-yohan@users.noreply.github.com>
2026-05-30 02:38:18 -07:00
Zyrixtrex 87c6edc1d0 fix(skills): add timeout to Google OAuth urlopen calls 2026-05-19 00:11:44 -07:00
kshitij 5fba236644 chore: ruff auto-fix PLR6201 resweep — tuple → set in membership tests (#27355)
Six days after #23937 (608 fixes) the codebase had accumulated 241 new
PLR6201 violations. Same mechanical `x in (...)` → `x in {...}` fix,
same zero-risk profile: set lookup is O(1) vs O(n) for tuple and the
two are semantically equivalent for hashable scalar membership tests.

All 241 instances fixed via `ruff check --select PLR6201 --fix
--unsafe-fixes`, zero remaining. Every changed value is a hashable
scalar (str/int/None/enum/signal); no risk of unhashable runtime
errors. No behavior change.

Test plan:
- 119 files changed, +244/-244 (net zero) — exactly one-line edits
- `ruff check` clean afterward
- Compile checks pass on the largest touched files (cli.py, run_agent.py,
  gateway/run.py, gateway/platforms/discord.py, model_tools.py)
- Subset broad test run on tests/gateway/ tests/hermes_cli/ tests/agent/
  tests/tools/: 18187 passed, 59 pre-existing failures (verified against
  origin/main with the same shape — identical failure count, identical
  category — all xdist test-order flakes unrelated to this change)

Follows the same template as PR #23937 ([tracker: #23972](https://github.com/NousResearch/hermes-agent/issues/23972)).
2026-05-17 02:29:41 -07:00
Teknium 98db898c0b feat(skills): declare platforms frontmatter for all 79 undeclared built-in skills
Completes the Windows-gating coverage for the built-in skills/ tree. Every
bundled SKILL.md now carries an explicit platforms: declaration so the
loader (agent.skill_utils.skill_matches_platform) can skip-load skills
that don't fit the current OS.

74 skills declared cross-platform (platforms: [linux, macos, windows]):
  Creative (16): ascii-art, ascii-video, architecture-diagram, baoyu-comic,
    baoyu-infographic, claude-design, creative-ideation, design-md,
    excalidraw, humanizer, manim-video, p5js, pixel-art,
    popular-web-designs, pretext, sketch, songwriting-and-ai-music,
    touchdesigner-mcp
  Autonomous agents: claude-code, codex, hermes-agent, opencode
  Data/devops: jupyter-live-kernel, kanban-orchestrator, kanban-worker,
    webhook-subscriptions, dogfood, codebase-inspection
  GitHub: github-auth, github-code-review, github-issues,
    github-pr-workflow, github-repo-management
  Media: gif-search, heartmula, songsee, spotify, youtube-content
  MCP / email / gaming / notes / smart-home: native-mcp, himalaya,
    pokemon-player, obsidian, openhue
  mlops (non-broken): weights-and-biases, huggingface-hub, llama-cpp,
    outlines, segment-anything-model, dspy, trl-fine-tuning
  Productivity: airtable, google-workspace, linear, maps, nano-pdf,
    notion, ocr-and-documents, powerpoint
  Red-teaming / research: godmode, arxiv, blogwatcher, llm-wiki,
    polymarket
  Software-dev: debugging-hermes-tui-commands, hermes-agent-skill-authoring,
    node-inspect-debugger, plan, requesting-code-review, spike,
    subagent-driven-development, systematic-debugging,
    test-driven-development, writing-plans
  Misc: yuanbao

5 skills gated from Windows (platforms: [linux, macos]):
  mlops/inference/vllm (serving-llms-vllm)
    vLLM is officially Linux-only; Windows requires WSL.
  mlops/training/axolotl
    Axolotl's flash-attn + deepspeed + bitsandbytes stack is Linux-first.
  mlops/training/unsloth
    Requires Triton + xformers + flash-attn — Linux only in practice.
  mlops/models/audiocraft (audiocraft-audio-generation)
    torchaudio ffmpeg backend + encodec dependencies are Linux-first.
  mlops/inference/obliteratus
    Research abliteration workflow; relies on Linux-focused pytorch
    kernels and MLX — no first-class Windows path.

Same strict-over-lenient policy as the optional-skills sweep: when the
underlying tool's Windows support is rough, missing, or WSL-only, gate the
skill. Easier to un-gate after verified Windows support lands than to leak
partial support that manifests as mid-task failures.

Combined with prior commits in this branch, every bundled SKILL.md
(skills/ + optional-skills/) now has a platforms: declaration.
2026-05-08 14:27:40 -07:00
Teknium e43d2fe520 feat(google-workspace): Drive write ops + Docs/Sheets create/append (#21895)
Expand the google-workspace skill beyond read-only access to Drive and
Docs. Sheets already had full scope — just adds the missing create verb.

New subcommands:
- drive get        : metadata for a single file
- drive upload     : upload a local file (auto MIME detection)
- drive download   : download or export (Docs/Sheets/Slides export to pdf/csv/pdf by default)
- drive create-folder
- drive share      : user/group/domain/anyone + reader/writer/etc.
- drive delete     : default trashes (reversible); --permanent skips the trash
- sheets create    : new spreadsheet with optional first-tab name
- docs create      : new doc, optional initial body
- docs append      : append text at end of an existing doc

Scope changes:
- drive.readonly     -> drive
- documents.readonly -> documents

Existing users with old tokens will hit the existing partial-scope
warning path (AUTHENTICATED (partial) ...) — the troubleshooting table
now points them at $GSETUP --revoke + redo steps 3-5 to pick up the
write scopes.
2026-05-08 07:27:32 -07:00
Teknium 83c23e8861 fix(google-workspace): cleanup for --check-live salvage
Small follow-ups on top of #19643:
- check_auth() takes quiet kwarg to suppress its AUTHENTICATED print
  when called from check_auth_live(), so the final status line reflects
  the live-call outcome only.
- Drop redundant _ensure_deps() call in check_auth_live() (check_auth()
  already calls it).
- Add AUTHOR_MAP entry for ygd58 so release attribution script works.
2026-05-08 04:50:43 -07:00
ygd58 617ac0535b fix: correct docstring syntax error in check_auth_live 2026-05-08 04:50:43 -07:00
ygd58 5fa493a2ca fix(google-workspace): detect disabled_client in --check and add --check-live
setup.py --check only validated token shape/expiry but did not detect
when Google had disabled the OAuth client or account. Users got
AUTHENTICATED even when actual API calls failed with disabled_client.

Changes:
- Catch disabled_client and invalid_client in check_auth() refresh
  path with actionable guidance (check Cloud Console, check account
  status, do not retry)
- Add check_auth_live() that performs a real Calendar API call to
  detect disabled_client errors that survive token refresh
- Add --check-live CLI flag backed by check_auth_live()

Fixes #19570
2026-05-08 04:50:43 -07:00
briandevans 81cd678291 fix(google-workspace): restore required_credential_files in SKILL.md (#16452)
PR #9931 ("feat(google-workspace): add --from flag for custom sender display name")
accidentally removed the required_credential_files frontmatter block that tells
hermes to bind-mount google_token.json and google_client_secret.json into Docker
and Modal remote terminals before running setup.py.

Without this header the credential files are never registered in the session-scoped
ContextVar, so get_credential_file_mounts() returns an empty list at container
creation time and the OAuth files are invisible inside the sandbox.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 12:43:14 -07:00
Teknium e3921e7ca4 docs(skills): compress 74 built-in skill descriptions to <=60 chars
Target: every skill's description fits in a one-line gateway menu and
leads with trigger keywords an agent would match on. Drops filler like
'Use this skill to', 'A skill for', 'This skill provides'.

Before: max description length was 791 chars (architecture-diagram),
74 of 81 built-in skills were >60 chars.

After: max 60, mean 54, all 81 built-in skills <=60.

Rewritten with double-quoted YAML scalars to preserve Chinese/arrow
glyphs (baoyu-comic, yuanbao, youtube-content).
2026-04-26 21:50:56 -07:00
xiahu88988 898ccfd667 fix(skills): honor scope query from Google OAuth redirect URL
Parse scope from the raw callback URL before stripping the auth code so Flow.fetch_token matches user-granted scopes. Add regression test for dual-scope callbacks.

Made-with: Cursor
2026-04-26 21:08:19 -07:00
Teknium 13038dc747 fix(skills): ship google-workspace deps as [google] extra; make setup.py 3.9-parseable
Closes #13626.

Two follow-ups on top of the _hermes_home helper from @jerome-benoit's #12729:

1. Declare a [google] optional extra in pyproject.toml
   (google-api-python-client, google-auth-oauthlib, google-auth-httplib2) and
   include it in [all]. Packagers (Nix flake, Homebrew) now ship the deps by
   default, so `setup.py --check` does not need to shell out to pip at
   runtime — the imports succeed and install_deps() is never reached.
   This fixes the Nix breakage where pip/ensurepip are stripped.

2. Add `from __future__ import annotations` to setup.py so the PEP 604
   `str | None` annotation parses on Python 3.9 (macOS system python).
   Previously system python3 SyntaxError'd before any code ran.

install_deps() error message now also points users at the extra instead of
just the raw pip command.
2026-04-24 16:45:27 -07:00
Jérôme Benoit c34d3f4807 fix(skills): factor HERMES_HOME resolution into shared _hermes_home helper
The three google-workspace scripts (setup.py, google_api.py, gws_bridge.py)
each had their own way of resolving HERMES_HOME:

- setup.py imported hermes_constants (crashes outside Hermes process)
- google_api.py used os.getenv inline (no strip, no empty handling)
- gws_bridge.py defined its own local get_hermes_home() (duplicate)

Extract the common logic into _hermes_home.py which:
- Delegates to hermes_constants when available (profile support, etc.)
- Falls back to os.getenv with .strip() + empty-as-unset handling
- Provides display_hermes_home() with ~/ shortening for profiles

All three scripts now import from _hermes_home instead of duplicating.

7 regression tests cover the fallback path: env var override, default
~/.hermes, empty env var, display shortening, profile paths, and
custom non-home paths.

Closes #12722
2026-04-24 16:45:27 -07:00
LeonSGP43 daef0519e9 fix(google-workspace): normalize authorized user token writes 2026-04-16 04:22:16 -07:00
Teknium e402906d48 fix: five HERMES_HOME profile-isolation leaks (#10570)
* fix: show correct env var name in provider API key error (#9506)

The error message for missing provider API keys dynamically built
the env var name as PROVIDER_API_KEY (e.g. ALIBABA_API_KEY), but
some providers use different names (alibaba uses DASHSCOPE_API_KEY).
Users following the error message set the wrong variable.

Fix: look up the actual env var from PROVIDER_REGISTRY before
building the error. Falls back to the dynamic name if the registry
lookup fails.

Closes #9506

* fix: five HERMES_HOME profile-isolation leaks (#5947)

Bug A: Thread session_title from session_db to memory provider init kwargs
so honcho can derive chat-scoped session keys instead of falling back to
cwd-based naming that merges all gateway users into one session.

Bug B: Replace 14 hardcoded ~/.hermes/skills/ paths across 10 skill files
with HERMES_HOME-aware alternatives (${HERMES_HOME:-$HOME/.hermes} in
shell, os.environ.get('HERMES_HOME', ...) in Python).

Bug C: install.sh now respects HERMES_HOME env var and adds --hermes-home
flag. Previously --dir only set INSTALL_DIR while HERMES_HOME was always
hardcoded to $HOME/.hermes.

Bug D: Remove hardcoded ~/.hermes/honcho.json fallback in resolve_config_path().
Non-default profiles no longer silently inherit the default profile's honcho
config. Falls through to ~/.honcho/config.json (global) instead.

Bug E: Guard _edit_skill, _patch_skill, _delete_skill, _write_file, and
_remove_file against writing to skills found in external_dirs. Skills
outside the local SKILLS_DIR are now read-only from the agent's perspective.

Closes #5947
2026-04-15 17:09:41 -07:00
Misturi dedc4600dd fix(skills): handle missing fields in Google Workspace token file gracefully instead of crashing with KeyError 2026-04-15 03:45:09 -07:00
Teknium b24e5ee4b0 feat(google-workspace): add --from flag for custom sender display name (#9931)
Adds --from flag to gmail send and gmail reply commands, allowing agents
to customize the From header display name when sharing the same email
account. Usage: --from '"Agent Name" <user@example.com>'

Also syncs repo google_api.py with the deployed standalone implementation
(replaces outdated gws_bridge thin wrapper), adds dedicated docs page
under Features > Skills, and updates sidebar navigation.

Requested by community user @Maxime44.
2026-04-14 16:55:34 -07:00
Teknium e9168f917e fix: handle HTTP errors gracefully in gws_bridge token refresh
Instead of crashing with a raw urllib traceback on refresh failure,
print a clean error message and suggest re-running setup.py.
2026-04-09 14:28:35 -07:00
Teknium 73eb59db8d fix: follow-up fixes for google-workspace gws migration
- Fix npm package name: @anthropic -> @googleworkspace/cli
- Add Homebrew install option
- Fix calendar_list to respect --start/--end args (uses raw Calendar
  API for date ranges, +agenda helper for default 7-day view)
- Improve check_auth partial scope output (list missing scopes)
- Add output format documentation with key JSON shapes
- Use npm install in troubleshooting (no Rust toolchain needed)

Follow-up to cherry-picked PR #6713
2026-04-09 14:28:35 -07:00
spideystreet 127b4caf0d feat(skills): migrate google-workspace to gws CLI backend
Migrate the google-workspace skill from custom Python API wrappers
(google-api-python-client) to Google's official Rust CLI gws
(googleworkspace/cli). Add gws_bridge.py for headless-compatible
token refresh. Fix partial OAuth scope handling.

Co-authored-by: spideystreet <dhicham.pro@gmail.com>
Cherry-picked from PR #6713
2026-04-09 14:28:35 -07:00
Zainan Victor Zhou 190471fdc0 docs: use HERMES_HOME in google-workspace skill examples
- avoid hard-coded ~/.hermes paths in the setup and API shorthands
- prefer HERMES_HOME with a sane default to /Users/peteradams/.hermes
- keep the examples aligned with profile-aware Hermes installs
2026-04-06 16:50:07 -07:00
Zainan Victor Zhou 83df001d01 fix: allow google-workspace skill scripts to run directly
- fall back to adding the repo root to sys.path when hermes_constants is not importable
- fixes direct execution of setup.py and google_api.py from the repo checkout
- keeps the upstream PR scoped to the google-workspace compatibility fix
2026-04-06 16:50:07 -07:00
kshitijk4poor 5359921199 refactor: simplify scope validation helpers in google workspace scripts
Fix double file read bug in google_api.py _missing_scopes(), consolidate
redundant _normalize_scope_values into callers, merge duplicate except blocks.
2026-04-03 17:49:18 -07:00
kshitijk4poor 37e2ef6c3f fix: protect profile-scoped google workspace oauth tokens 2026-04-03 17:49:18 -07:00
Teknium 7a3682ac3f feat: mount skill credential files + fix env passthrough for remote backends (#3671)
Two related fixes for remote terminal backends (Modal/Docker):

1. NEW: Credential file mounting system
   Skills declare required_credential_files in frontmatter. Files are
   mounted into Docker (read-only bind mounts) and Modal (mounts at
   creation + sync via exec on each command for mid-session changes).
   Google Workspace skill updated with the new field.

2. FIX: Docker backend now includes env_passthrough vars
   Skills that declare required_environment_variables (e.g. Notion with
   NOTION_API_KEY) register vars in the env_passthrough system. The
   local backend checked this, but Docker's forward_env was a separate
   disconnected list. Now Docker exec merges both sources, so
   skill-declared env vars are forwarded into containers automatically.

   This fixes the reported issue where NOTION_API_KEY in ~/.hermes/.env
   wasn't reaching the Docker container despite being registered via
   the Notion skill's prerequisites.

Closes #3665
2026-03-28 23:53:40 -07:00
teknium1 4524cddc72 fix: persist google oauth pkce for headless auth
Store the pending OAuth state and code verifier between --auth-url and --auth-code so the manual headless flow can reuse Flow.fetch_token() without disabling PKCE.
2026-03-14 22:11:34 -07:00
teknium1 669e4d0297 add experimental google workspace command center skill 2026-02-26 14:29:51 -08:00