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
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:
@@ -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.linear.config import LinearConfig
|
||||
|
||||
__all__ = ["LinearConfig", "LinearResource"]
|
||||
|
||||
|
||||
def __getattr__(name: str):
|
||||
if name == "LinearResource":
|
||||
from mirage.resource.linear.linear import LinearResource
|
||||
return LinearResource
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
@@ -0,0 +1,22 @@
|
||||
# ========= 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 pydantic import BaseModel, SecretStr
|
||||
|
||||
|
||||
class LinearConfig(BaseModel):
|
||||
api_key: SecretStr
|
||||
workspace: str | None = None
|
||||
team_ids: list[str] | None = None
|
||||
base_url: str = "https://api.linear.app/graphql"
|
||||
@@ -0,0 +1,63 @@
|
||||
# ========= 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.linear import LinearAccessor
|
||||
from mirage.core.linear.glob import resolve_glob as _resolve_glob
|
||||
from mirage.core.linear.read import read
|
||||
from mirage.core.linear.readdir import readdir
|
||||
from mirage.core.linear.stat import stat
|
||||
from mirage.resource.base import BaseResource
|
||||
from mirage.resource.linear.config import LinearConfig
|
||||
from mirage.resource.linear.prompt import PROMPT, WRITE_PROMPT
|
||||
from mirage.types import ResourceName
|
||||
|
||||
_LINEAR_OPS = {
|
||||
"read_bytes": read,
|
||||
"readdir": readdir,
|
||||
"stat": stat,
|
||||
}
|
||||
|
||||
|
||||
class LinearResource(BaseResource):
|
||||
|
||||
name: str = ResourceName.LINEAR
|
||||
caches_reads: bool = True
|
||||
_ops: dict = _LINEAR_OPS
|
||||
PROMPT: str = PROMPT
|
||||
WRITE_PROMPT: str = WRITE_PROMPT
|
||||
|
||||
def __init__(self, config: LinearConfig) -> None:
|
||||
super().__init__()
|
||||
self.config = config
|
||||
self.accessor = LinearAccessor(self.config)
|
||||
from mirage.commands.builtin.linear import COMMANDS
|
||||
from mirage.ops.linear import OPS as LINEAR_VFS_OPS
|
||||
|
||||
for fn in COMMANDS:
|
||||
self.register(fn)
|
||||
for fn in LINEAR_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
|
||||
@@ -0,0 +1,153 @@
|
||||
# ========= 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}
|
||||
teams/
|
||||
<team-key>__<team-name>__<team-id>/
|
||||
team.json
|
||||
members/
|
||||
<display-name>__<user-id>.json
|
||||
issues/
|
||||
<issue-key>__<issue-id>/
|
||||
issue.json
|
||||
comments.jsonl
|
||||
projects/
|
||||
<name>__<project-id>.json
|
||||
cycles/
|
||||
<name>__<cycle-id>.json
|
||||
Always ls directories first to discover exact names.
|
||||
|
||||
Folder/file name anatomy: every entity-named segment is
|
||||
<sanitized-human-readable>__<id>
|
||||
The human-readable part is sanitized — don't construct it; ls the
|
||||
parent dir to discover exact entry names.
|
||||
IDs are the LAST "__"-separated segment. To extract:
|
||||
{prefix}/teams/STR__Strukto-ai__<team-id>/ -> <team-id>
|
||||
{prefix}/teams/.../issues/STR-42__<issue-id>/ -> <issue-id>
|
||||
{prefix}/teams/.../members/Alice__<user-id>.json -> <user-id>
|
||||
|
||||
All cat output is mirage-normalized (snake_case keys), NOT the raw
|
||||
Linear GraphQL response. Shapes:
|
||||
|
||||
team.json:
|
||||
{{
|
||||
"team_id": "...", "team_key": "STR", "team_name": "Strukto",
|
||||
"name": "...", "description": "...", "timezone": "...",
|
||||
"updated_at": "...",
|
||||
"states": [
|
||||
{{ "state_id": "...", "state_name": "Todo", "type": "unstarted" }},
|
||||
... # one element per workflow state
|
||||
]
|
||||
}}
|
||||
|
||||
issue.json:
|
||||
{{
|
||||
"issue_id": "...", "issue_key": "STR-42",
|
||||
"title": "...", "description": "...",
|
||||
"team_id": "...", "team_key": "...", "team_name": "...",
|
||||
"project_id": "...", "project_name": "...",
|
||||
"cycle_id": "...", "cycle_name": "...", "cycle_number": 7,
|
||||
"state_id": "...", "state_name": "In Progress",
|
||||
"assignee_id": "...", "assignee_email": "...", "assignee_name": "...",
|
||||
"creator_id": "...", "creator_email": "...", "creator_name": "...",
|
||||
"priority": 2, # 0=none 1=urgent 2=high 3=medium 4=low
|
||||
"label_ids": ["..."],
|
||||
"label_names": ["bug", "frontend"],
|
||||
"created_at": "...", "updated_at": "...", "url": "..."
|
||||
}}
|
||||
|
||||
comments.jsonl: # one normalized comment per line
|
||||
{{ "comment_id": "...", "issue_id": "...", "issue_key": "STR-42",
|
||||
"user_id": "...", "user_email": "...", "user_name": "...",
|
||||
"body": "...", "created_at": "...", "updated_at": "...",
|
||||
"url": "..." }}
|
||||
|
||||
project.json:
|
||||
{{
|
||||
"project_id": "...", "team_id": "...",
|
||||
"name": "...", "description": "...", "state": "started",
|
||||
"lead_id": "...", "updated_at": "...", "url": "...",
|
||||
"issue_count": 12,
|
||||
"issues": [
|
||||
{{ "issue_id": "...", "issue_key": "STR-42", "title": "...",
|
||||
"state_id": "...", "state_name": "In Progress", "url": "..." }}
|
||||
]
|
||||
}}
|
||||
|
||||
cycle.json:
|
||||
{{
|
||||
"cycle_id": "...", "team_id": "...",
|
||||
"name": "...", "number": 7,
|
||||
"starts_at": "...", "ends_at": "...",
|
||||
"updated_at": "...", "url": "..."
|
||||
}}
|
||||
|
||||
user.json:
|
||||
{{
|
||||
"user_id": "...", "name": "...", "display_name": "...",
|
||||
"email": "...", "is_active": true, "is_admin": false,
|
||||
"updated_at": "...", "url": "..."
|
||||
}}
|
||||
|
||||
Useful jq paths:
|
||||
.issue_key # issue.json
|
||||
.state_name # issue.json
|
||||
.assignee_email # issue.json
|
||||
.label_names[] # issue.json
|
||||
.issues[] | select(.state_name == "In Progress") # project.json
|
||||
.states[].state_name # team.json
|
||||
[inputs] | length # comments.jsonl: count
|
||||
[inputs | select(.user_email == "x")] | length # comments.jsonl
|
||||
|
||||
Read commands:
|
||||
linear-search --query "bug login" # full-text across all issues"""
|
||||
|
||||
WRITE_PROMPT = """\
|
||||
Write commands (flags use UNDERSCORES, not hyphens; --issue_id and
|
||||
--issue_key are interchangeable on every issue command):
|
||||
|
||||
linear-issue-create --team_id <team-id> \\
|
||||
--title "Title" --description "Body"
|
||||
# or: --description_file /path/to/desc.md
|
||||
|
||||
linear-issue-update --issue_key STR-42 \\
|
||||
[--title "New title"] [--description "..." | --description_file ...]
|
||||
|
||||
linear-issue-assign --issue_key STR-42 --assignee_email user@example.com
|
||||
# or: --assignee_id <user-id>
|
||||
|
||||
linear-issue-transition --issue_key STR-42 --state_name "In Review"
|
||||
# or: --state_id <state-id>
|
||||
|
||||
linear-issue-set-priority --issue_key STR-42 --priority 2
|
||||
# 0=none 1=urgent 2=high 3=medium 4=low
|
||||
|
||||
linear-issue-set-project --issue_key STR-42 --project_id <project-id>
|
||||
|
||||
linear-issue-add-label --issue_key STR-42 --label_id <label-id>
|
||||
|
||||
linear-issue-comment-add --issue_key STR-42 --body "comment"
|
||||
# or: --body_file /path/to/comment.md
|
||||
|
||||
linear-issue-comment-update --comment_id <comment-id> --body "..."
|
||||
|
||||
IDs come from the path:
|
||||
{prefix}/teams/STR__Strukto-ai__<team-id>/ -> --team_id
|
||||
{prefix}/teams/.../issues/STR-42__<issue-id>/ -> --issue_id
|
||||
{prefix}/teams/.../projects/Roadmap__<project-id>.json -> --project_id
|
||||
|
||||
Successful create returns JSON like:
|
||||
{"issue_id": "<uuid>", "issue_key": "STR-23", "title": "...", ...}
|
||||
Empty stdout means the call failed -- inspect stderr or retry."""
|
||||
Reference in New Issue
Block a user