chore: import upstream snapshot with attribution
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:30:44 +08:00
commit bcbd1bdb22
5748 changed files with 562488 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from mirage.resource.gmail.config import GmailConfig
__all__ = ["GmailConfig", "GmailResource"]
def __getattr__(name: str):
if name == "GmailResource":
from mirage.resource.gmail.gmail import GmailResource
return GmailResource
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
+19
View File
@@ -0,0 +1,19 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from mirage.core.google.config import GoogleConfig
class GmailConfig(GoogleConfig):
pass
+55
View File
@@ -0,0 +1,55 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
from mirage.accessor.gmail import GmailAccessor
from mirage.core.gmail.glob import resolve_glob as _resolve_glob
from mirage.core.google._client import TokenManager
from mirage.resource.base import BaseResource
from mirage.resource.gmail.config import GmailConfig
from mirage.resource.gmail.prompt import PROMPT, WRITE_PROMPT
from mirage.types import ResourceName
class GmailResource(BaseResource):
name: str = ResourceName.GMAIL
caches_reads: bool = True
PROMPT: str = PROMPT
WRITE_PROMPT: str = WRITE_PROMPT
def __init__(self, config: GmailConfig) -> None:
super().__init__()
self.config = config
self._token_manager = TokenManager(config)
self.accessor = GmailAccessor(self.config, self._token_manager)
from mirage.commands.builtin.gmail import COMMANDS
from mirage.ops.gmail import OPS as GMAIL_VFS_OPS
for fn in COMMANDS:
self.register(fn)
for fn in GMAIL_VFS_OPS:
self.register_op(fn)
async def resolve_glob(self, paths, prefix: str = ""):
return await _resolve_glob(self.accessor, paths, index=self._index)
async def fingerprint(self, path: str) -> str | None:
lookup = await self._index.get(path)
return lookup.entry.remote_time if lookup.entry else None
def get_state(self) -> dict:
return self.config_state(self.config)
def load_state(self, state: dict) -> None:
pass
+98
View File
@@ -0,0 +1,98 @@
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
PROMPT = """\
{prefix}
<label>/
<yyyy-mm-dd>/
<subject>__<message-id>.gmail.json # email JSON file (the email itself)
<subject>__<message-id>/ # attachments dir, only if any
<attachment-filename>
Email body is in the .gmail.json file. The sibling dir holds attachments
only. Read with `cat`/`head`/`jq` on `<path>.gmail.json` (keep the suffix).
Commands: cat, ls, head, tail, nl, wc, stat, find, tree, grep, rg, jq,
basename, dirname, realpath, gws-gmail-read, gws-gmail-triage.
No others (no readFile, etc.).
Path: <label>/<yyyy-mm-dd>/<subject>__<message-id>.gmail.json
<label> Gmail label (INBOX, SENT, DRAFT, IMPORTANT, STARRED,
TRASH, SPAM, or any user label)
<yyyy-mm-dd> date the message was received, used for date narrowing
(ls {prefix}/INBOX/2026-05-03/ pushes after:/before: into the
Gmail query - much cheaper than scanning the whole label)
<subject> sanitized subject (don't construct it; ls the date dir)
<message-id> Gmail message ID
email JSON structure (mirage-processed, NOT the raw Gmail API response):
{{
"id": "...",
"thread_id": "...",
"from": {{ "name": "...", "email": "..." }},
"to": [ {{ "name": "...", "email": "..." }} ],
"cc": [ ... ],
"subject": "...",
"date": "Mon, 3 May 2026 10:00:00 -0700",
"body_text": "decoded plain-text body",
"snippet": "first ~200 chars from Gmail",
"labels": [ "INBOX", "IMPORTANT", ... ],
"attachments": [
{{ "id": "...", "filename": "invoice.pdf",
"mime_type": "application/pdf", "size": 12345 }}
]
}}
Attachments: each message with attachments has a sibling directory at
<subject>__<message-id>/ (same name as the .gmail.json file but without
the extension). Cat a file inside to download bytes. grep -r over a
date dir skips these binary files automatically.
After a grep/rg hit, the result line points to .../<subject>__<id>.gmail.json
— the sibling attachments dir is NOT in grep output. Once you have the
message id (or the .gmail.json path), ls the same path with .gmail.json
stripped to list attachments directly:
ls {prefix}/INBOX/2026-05-03/<subject>__<message-id>/
ENOENT means the message has no attachments.
Useful jq paths:
.subject
.from.email
.body_text
.labels[]
.attachments[] | .filename
Read commands:
gws-gmail-read --id <message-id> # same shape as cat
gws-gmail-triage --query "is:unread" --max 20 # summary list (id, from,
# subject, date, snippet)"""
WRITE_PROMPT = """\
Write commands:
gws-gmail-send --to "to@email.com" --subject "Hi" --body "..."
gws-gmail-reply --message-id <id> --body "..."
gws-gmail-reply-all --message-id <id> --body "..."
gws-gmail-forward --message-id <id> --to "to@email.com"
Body gotcha: bash double-quoted "...\\n..." is NOT a newline.
Use $'line1\\nline2' (ANSI-C quoting) or "$(printf '...\\n...')"
if you need real newlines in the body.
Delete:
rm {prefix}/<label>/<yyyy-mm-dd>/<subject>__<message-id>.gmail.json
# moves the message to Trash
rm -f <path> # ignore if missing
Only operates on .gmail.json files; label/, date/, and the
attachments folder cannot be removed (they are virtual)."""