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,322 @@
|
||||
// ========= 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. =========
|
||||
|
||||
import { resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import dotenv from "dotenv";
|
||||
import { GitHubResource, MountMode, Workspace } from "@struktoai/mirage-node";
|
||||
|
||||
const __HERE = fileURLToPath(new URL(".", import.meta.url));
|
||||
dotenv.config({ path: resolve(__HERE, "../../../.env.development") });
|
||||
|
||||
const TOKEN = process.env.GITHUB_TOKEN;
|
||||
if (TOKEN === undefined || TOKEN === "") {
|
||||
throw new Error("GITHUB_TOKEN env var is required");
|
||||
}
|
||||
|
||||
async function show(ws: Workspace, cmd: string): Promise<void> {
|
||||
try {
|
||||
const r = await ws.execute(cmd);
|
||||
console.log(r.stdoutText);
|
||||
if (r.stderrText !== "") process.stderr.write(r.stderrText);
|
||||
} catch (err) {
|
||||
process.stderr.write(
|
||||
`# ${cmd} → ${err instanceof Error ? err.message : String(err)}\n`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function header(
|
||||
ws: Workspace,
|
||||
label: string,
|
||||
cmd: string,
|
||||
): Promise<void> {
|
||||
console.log(`=== ${label} ===`);
|
||||
try {
|
||||
const r = await ws.execute(cmd);
|
||||
console.log(r.stdoutText);
|
||||
if (r.stderrText !== "") process.stderr.write(r.stderrText);
|
||||
} catch (err) {
|
||||
process.stderr.write(
|
||||
`# ${cmd} → ${err instanceof Error ? err.message : String(err)}\n`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function timed(ws: Workspace, cmd: string): Promise<[number, string]> {
|
||||
const start = performance.now();
|
||||
const r = await ws.execute(cmd);
|
||||
return [performance.now() - start, r.stdoutText];
|
||||
}
|
||||
|
||||
async function narrowCase(
|
||||
ws: Workspace,
|
||||
label: string,
|
||||
cmd: string,
|
||||
): Promise<void> {
|
||||
console.log(`\n=== ${label} ===`);
|
||||
const [ms, out] = await timed(ws, cmd);
|
||||
const lines = out.trim() === "" ? [] : out.trim().split("\n");
|
||||
console.log(` ${ms.toFixed(0)}ms results: ${String(lines.length)}`);
|
||||
for (const line of lines.slice(0, 3)) console.log(` ${line.slice(0, 150)}`);
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const resource = await GitHubResource.create({
|
||||
token: TOKEN!,
|
||||
owner: "strukto-ai",
|
||||
repo: "mirage",
|
||||
ref: "main",
|
||||
});
|
||||
const ws = new Workspace({ "/github": resource }, { mode: MountMode.READ });
|
||||
|
||||
await show(ws, "ls /github");
|
||||
await show(ws, "ls /github/python/mirage/core");
|
||||
await show(ws, "cat /github/python/pyproject.toml");
|
||||
await show(ws, "grep 'BaseResource' /github/python/mirage/resource/base.py");
|
||||
await show(ws, "grep 'import' /github/python/mirage/*");
|
||||
await show(ws, "grep 'import' /github/python/mirage/core/s3/*.py");
|
||||
await show(ws, "grep -r 'async def' /github/python/mirage/core/s3/");
|
||||
await show(ws, "find /github/mirage -name '*.py'");
|
||||
await show(ws, "stat /github/python/mirage/types.py");
|
||||
await show(ws, "du /github/python/mirage/core");
|
||||
|
||||
await header(ws, "head -n 5", "head -n 5 /github/python/pyproject.toml");
|
||||
await header(ws, "tail -n 3", "tail -n 3 /github/python/pyproject.toml");
|
||||
await header(ws, "wc", "wc /github/python/pyproject.toml");
|
||||
await header(ws, "wc -l", "wc -l /github/python/pyproject.toml");
|
||||
await header(
|
||||
ws,
|
||||
"grep -n (line numbers)",
|
||||
"grep -n 'def ' /github/python/mirage/types.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"grep -c (count)",
|
||||
"grep -c 'import' /github/python/mirage/types.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"grep -i (case insensitive)",
|
||||
"grep -i 'filestat' /github/python/mirage/types.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"grep -l (files with matches)",
|
||||
"grep -rl 'BaseResource' /github/python/mirage/resource/",
|
||||
);
|
||||
|
||||
for (const [label, cmd] of [
|
||||
[
|
||||
"grep -r mirage /github/python/mirage/core/s3/ (narrows via search.code)",
|
||||
"grep -r mirage /github/python/mirage/core/s3/",
|
||||
],
|
||||
[
|
||||
"grep -r FileType /github/python/mirage/core/s3/ (recursive scope)",
|
||||
"grep -r FileType /github/python/mirage/core/s3/",
|
||||
],
|
||||
[
|
||||
"rg mirage /github/python/mirage/core/s3/ (rg recursive scope)",
|
||||
"rg mirage /github/python/mirage/core/s3/",
|
||||
],
|
||||
[
|
||||
"grep -r GitHubAccessor /github/ (repo-root search narrowing)",
|
||||
"grep -r GitHubAccessor /github/ | sort",
|
||||
],
|
||||
] as const) {
|
||||
console.log(`\n=== ${label} ===`);
|
||||
let r;
|
||||
try {
|
||||
r = await ws.execute(cmd);
|
||||
} catch (err) {
|
||||
console.log(
|
||||
` error: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const out = r.stdoutText.trim();
|
||||
const lines = out === "" ? [] : out.split("\n");
|
||||
console.log(
|
||||
` exit=${String(r.exitCode)} matches: ${String(lines.length)}`,
|
||||
);
|
||||
if (r.stderrText.trim() !== "")
|
||||
console.log(` stderr: ${r.stderrText.trim().slice(0, 200)}`);
|
||||
for (const line of lines.slice(0, 3))
|
||||
console.log(` ${line.slice(0, 150)}`);
|
||||
}
|
||||
|
||||
// subdir + regex narrowing + -l short-circuit (issue #404). A large subdir
|
||||
// (>100 files) is what makes the per-file fallback slow; these narrow via
|
||||
// GitHub code search instead of fetching each file.
|
||||
const bigDir = "/github/python/mirage/";
|
||||
await narrowCase(
|
||||
ws,
|
||||
`grep -rln BaseResource ${bigDir} (subdir narrowing, -l short-circuit)`,
|
||||
`grep -rln BaseResource ${bigDir}`,
|
||||
);
|
||||
await narrowCase(
|
||||
ws,
|
||||
`grep -rn 'async def .*self' ${bigDir} (regex narrows via required literal 'async def ')`,
|
||||
`grep -rn 'async def .*self' ${bigDir}`,
|
||||
);
|
||||
await narrowCase(
|
||||
ws,
|
||||
`rg -l GitHubAccessor ${bigDir} (rg subdir narrowing, -l short-circuit)`,
|
||||
`rg -l GitHubAccessor ${bigDir}`,
|
||||
);
|
||||
await narrowCase(
|
||||
ws,
|
||||
`rg -l --glob '*.py' GitHubAccessor ${bigDir} (file filter applied to narrowed set)`,
|
||||
`rg -l --glob '*.py' GitHubAccessor ${bigDir}`,
|
||||
);
|
||||
await narrowCase(
|
||||
ws,
|
||||
`rg -l --type py GitHubAccessor ${bigDir} (--type filter applied to narrowed set)`,
|
||||
`rg -l --type py GitHubAccessor ${bigDir}`,
|
||||
);
|
||||
|
||||
await header(ws, "find -type d", "find /github/python/mirage/core -type d");
|
||||
await header(ws, "ls -l", "ls -l /github/python/mirage/core/s3/");
|
||||
await header(
|
||||
ws,
|
||||
"find | sort",
|
||||
"find /github/python/mirage/core/s3 -name '*.py' | sort",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"diff",
|
||||
"diff /github/python/mirage/core/s3/stat.py /github/python/mirage/core/s3/read.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"cat + pipe to wc",
|
||||
"cat /github/python/mirage/types.py | wc -l",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"grep + cut",
|
||||
"grep -n 'class ' /github/python/mirage/types.py | cut -d: -f1",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"grep + awk",
|
||||
"grep 'class ' /github/python/mirage/types.py | awk '{print $2}'",
|
||||
);
|
||||
await header(ws, "md5", "md5 /github/python/mirage/types.py");
|
||||
await header(ws, "tree", "tree /github/python/mirage/core/s3/");
|
||||
await header(ws, "find workspace.py", "find /github -name 'workspace.py'");
|
||||
await header(
|
||||
ws,
|
||||
"wc -l (lines)",
|
||||
"wc -l /github/python/mirage/workspace/workspace.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"wc -w (words)",
|
||||
"wc -w /github/python/mirage/workspace/workspace.py",
|
||||
);
|
||||
await header(ws, "jq", 'jq ".name" /github/python/pyproject.toml');
|
||||
await header(ws, "nl", "nl /github/python/mirage/types.py");
|
||||
await header(ws, "tr", "cat /github/python/mirage/types.py | tr 'a-z' 'A-Z'");
|
||||
await header(
|
||||
ws,
|
||||
"sort | uniq",
|
||||
"grep 'import' /github/python/mirage/types.py | sort | uniq",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"uniq (file path, streams via github read)",
|
||||
"uniq /github/python/mirage/types.py",
|
||||
);
|
||||
await header(ws, "sha256sum", "sha256sum /github/python/mirage/types.py");
|
||||
await header(ws, "file", "file /github/python/mirage/types.py");
|
||||
await header(
|
||||
ws,
|
||||
"basename",
|
||||
"basename /github/python/mirage/core/s3/read.py",
|
||||
);
|
||||
await header(ws, "dirname", "dirname /github/python/mirage/core/s3/read.py");
|
||||
await header(
|
||||
ws,
|
||||
"realpath",
|
||||
"realpath /github/python/mirage/../mirage/types.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"sed -n (line range)",
|
||||
"sed -n '1,3p' /github/python/mirage/types.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"sed s/// (file)",
|
||||
"sed 's/import/IMPORT/' /github/python/mirage/core/s3/read.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"awk (file)",
|
||||
"awk '{print $1}' /github/python/mirage/core/s3/read.py",
|
||||
);
|
||||
await header(
|
||||
ws,
|
||||
"cut -c (file)",
|
||||
"cut -c1-10 /github/python/mirage/types.py",
|
||||
);
|
||||
|
||||
console.log("=== grep dir operands (POSIX warn) ===");
|
||||
{
|
||||
const r = await ws.execute("grep 'import' /github/python/mirage/*");
|
||||
const out = r.stdoutText.trim();
|
||||
const err = r.stderrText.trim();
|
||||
const matches = out === "" ? 0 : out.split("\n").length;
|
||||
console.log(` exit=${String(r.exitCode)} matches: ${String(matches)}`);
|
||||
for (const line of err.split("\n").slice(0, 3)) console.log(` ${line}`);
|
||||
console.log();
|
||||
}
|
||||
|
||||
await header(
|
||||
ws,
|
||||
"diff -u",
|
||||
"diff -u /github/python/mirage/core/s3/stat.py /github/python/mirage/core/s3/read.py",
|
||||
);
|
||||
await header(ws, "tree -L", "tree -L 2 /github/python/mirage/");
|
||||
await header(ws, "rg", "rg 'BaseResource' /github/python/mirage/resource/");
|
||||
|
||||
console.log(
|
||||
"=== caching: a warm read is served from cache (no backend fetch) ===",
|
||||
);
|
||||
const cacheFile = "/github/python/mirage/workspace/workspace.py";
|
||||
const [coldMs, body] = await timed(ws, `cat ${cacheFile}`);
|
||||
const [warmMs] = await timed(ws, `cat ${cacheFile}`);
|
||||
const [grepMs] = await timed(ws, `grep 'def ' ${cacheFile}`);
|
||||
const [headMs] = await timed(ws, `head -n 5 ${cacheFile}`);
|
||||
const [tailMs] = await timed(ws, `tail -n 5 ${cacheFile}`);
|
||||
const [wcMs] = await timed(ws, `wc -l ${cacheFile}`);
|
||||
console.log(` file=${cacheFile} size=${String(body.length)}B`);
|
||||
console.log(
|
||||
` cold cat=${coldMs.toFixed(0)}ms warm cat=${warmMs.toFixed(0)}ms ` +
|
||||
`grep=${grepMs.toFixed(0)}ms head=${headMs.toFixed(0)}ms tail=${tailMs.toFixed(0)}ms ` +
|
||||
`wc=${wcMs.toFixed(0)}ms`,
|
||||
);
|
||||
console.log(
|
||||
` served_from_cache=${String(warmMs < coldMs / 5)} ` +
|
||||
`(warm speedup ${(coldMs / Math.max(warmMs, 0.001)).toFixed(0)}x)`,
|
||||
);
|
||||
|
||||
await ws.close();
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
# Browser GitHub demo
|
||||
|
||||
Demonstrates the browser `GitHubResource` calling `api.github.com` directly — no proxy server. GitHub's REST API supports CORS and uses an `Authorization` header, so the browser can talk to it directly (same model as Linear).
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
pnpm tsx examples/typescript/github/github_browser/main.ts
|
||||
```
|
||||
|
||||
`GITHUB_TOKEN` must be set (e.g. via `.env.development` at the repo root). Optional: `GITHUB_OWNER`, `GITHUB_REPO`, `GITHUB_REF`.
|
||||
|
||||
## Production note
|
||||
|
||||
Embedding a personal access token in shipped client code is fine for personal tools, internal dashboards, or post-OAuth flows where the token is already user-scoped. For untrusted clients, route through your own server using the `baseUrl` config option to point at a proxy that injects the credential server-side.
|
||||
@@ -0,0 +1,77 @@
|
||||
// ========= 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. =========
|
||||
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import dotenv from 'dotenv'
|
||||
import { GitHubResource, MountMode, Workspace } from '@struktoai/mirage-browser'
|
||||
|
||||
const __HERE = fileURLToPath(new URL('.', import.meta.url))
|
||||
dotenv.config({ path: resolve(__HERE, '../../../../.env.development') })
|
||||
|
||||
function buildConfig(): { token: string; owner: string; repo: string; ref?: string } {
|
||||
const token = process.env.GITHUB_TOKEN
|
||||
if (token === undefined || token === '') throw new Error('GITHUB_TOKEN env var is required')
|
||||
const owner = process.env.GITHUB_OWNER ?? 'strukto-ai'
|
||||
const repo = process.env.GITHUB_REPO ?? 'mirage'
|
||||
const ref = process.env.GITHUB_REF ?? 'main'
|
||||
return { token, owner, repo, ref }
|
||||
}
|
||||
|
||||
async function run(ws: Workspace, cmd: string): Promise<string> {
|
||||
console.log(`$ ${cmd}`)
|
||||
const r = await ws.execute(cmd)
|
||||
if (r.exitCode !== 0 && r.stderrText !== '') {
|
||||
console.log(` STDERR: ${r.stderrText.slice(0, 200)}`)
|
||||
}
|
||||
const out = r.stdoutText.replace(/\s+$/, '')
|
||||
if (out !== '') {
|
||||
for (const line of out.split('\n').slice(0, 12)) console.log(` ${line.slice(0, 200)}`)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const cfg = buildConfig()
|
||||
console.log(`Loading ${cfg.owner}/${cfg.repo} via @struktoai/mirage-browser …`)
|
||||
const resource = await GitHubResource.create(cfg)
|
||||
const ws = new Workspace({ '/github': resource }, { mode: MountMode.READ })
|
||||
try {
|
||||
console.log('=== BROWSER MODE: GitHubResource → api.github.com (direct, CORS) ===\n')
|
||||
|
||||
await run(ws, 'ls /github/')
|
||||
|
||||
console.log('')
|
||||
await run(ws, 'ls /github/python/mirage')
|
||||
|
||||
console.log('')
|
||||
await run(ws, 'head -n 5 /github/python/pyproject.toml')
|
||||
|
||||
console.log('')
|
||||
await run(ws, "grep 'BaseResource' /github/python/mirage/resource/base.py")
|
||||
|
||||
console.log('')
|
||||
await run(ws, 'wc -l /github/python/mirage/types.py')
|
||||
|
||||
console.log('')
|
||||
await run(ws, 'tree -L 2 /github/python/mirage/')
|
||||
} finally {
|
||||
await ws.close()
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,91 @@
|
||||
// ========= 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. =========
|
||||
|
||||
import { readdir, readFile } from "node:fs/promises";
|
||||
import { createInterface } from "node:readline/promises";
|
||||
import { resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import dotenv from "dotenv";
|
||||
import {
|
||||
GitHubResource,
|
||||
Mount,
|
||||
MountMode,
|
||||
Workspace,
|
||||
type GitHubConfig,
|
||||
} from "@struktoai/mirage-node";
|
||||
|
||||
const __HERE = fileURLToPath(new URL(".", import.meta.url));
|
||||
dotenv.config({ path: resolve(__HERE, "../../../.env.development") });
|
||||
|
||||
function buildConfig(): GitHubConfig {
|
||||
const token = process.env.GITHUB_TOKEN;
|
||||
if (token === undefined || token === "")
|
||||
throw new Error("GITHUB_TOKEN env var is required");
|
||||
const owner = process.env.GITHUB_OWNER ?? "anthropics";
|
||||
const repo = process.env.GITHUB_REPO ?? "anthropic-sdk-typescript";
|
||||
const ref = process.env.GITHUB_REF;
|
||||
return ref !== undefined
|
||||
? { token, owner, repo, ref }
|
||||
: { token, owner, repo };
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const cfg = buildConfig();
|
||||
console.log(`Loading ${cfg.owner}/${cfg.repo} …`);
|
||||
const resource = await GitHubResource.create(cfg);
|
||||
const ws = new Workspace({
|
||||
"/github": new Mount(resource, { mode: MountMode.READ, fuse: true }),
|
||||
});
|
||||
await ws.fuseReady();
|
||||
const mp = ws.fuseMountpoint as string;
|
||||
try {
|
||||
console.log(`=== FUSE MODE: mounted at ${mp} ===\n`);
|
||||
|
||||
console.log(`--- readdir() ${mp} ---`);
|
||||
const top = await readdir(mp);
|
||||
for (const r of top.slice(0, 10)) console.log(` ${r}`);
|
||||
|
||||
for (const name of ["README.md", "package.json", "pyproject.toml"]) {
|
||||
try {
|
||||
const path = `${mp}/${name}`;
|
||||
const text = await readFile(path, "utf-8");
|
||||
console.log(`\n--- readFile() ${path} (first 200 chars) ---`);
|
||||
console.log(text.slice(0, 200));
|
||||
break;
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n>>> FUSE mounted at: ${mp}`);
|
||||
console.log(">>> Open another terminal and run e.g.:");
|
||||
console.log(`>>> ls ${mp}`);
|
||||
console.log(`>>> cat ${mp}/README.md | head`);
|
||||
console.log(">>> Press Enter to unmount and exit...");
|
||||
|
||||
const rl = createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
await rl.question("");
|
||||
rl.close();
|
||||
} finally {
|
||||
await ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
// ========= 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. =========
|
||||
|
||||
import { createRequire } from 'node:module'
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import dotenv from 'dotenv'
|
||||
import { GitHubResource, MountMode, patchNodeFs, Workspace, type GitHubConfig } from '@struktoai/mirage-node'
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
const fs = require('fs') as typeof import('fs')
|
||||
|
||||
const __HERE = fileURLToPath(new URL('.', import.meta.url))
|
||||
dotenv.config({ path: resolve(__HERE, '../../../.env.development') })
|
||||
|
||||
function buildConfig(): GitHubConfig {
|
||||
const token = process.env.GITHUB_TOKEN
|
||||
if (token === undefined || token === '') throw new Error('GITHUB_TOKEN env var is required')
|
||||
const owner = process.env.GITHUB_OWNER ?? 'strukto-ai'
|
||||
const repo = process.env.GITHUB_REPO ?? 'mirage'
|
||||
const ref = process.env.GITHUB_REF ?? 'main'
|
||||
return { token, owner, repo, ref }
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const cfg = buildConfig()
|
||||
const resource = await GitHubResource.create(cfg)
|
||||
const ws = new Workspace({ '/github/': resource }, { mode: MountMode.READ })
|
||||
const restore = patchNodeFs(ws)
|
||||
try {
|
||||
console.log('=== VFS MODE: fs.readFile() reads from GitHub transparently ===\n')
|
||||
|
||||
console.log('--- fs.readdir() root ---')
|
||||
const entries = await fs.promises.readdir('/github')
|
||||
for (const e of entries.slice(0, 10)) console.log(` ${e}`)
|
||||
if (entries.length > 10) console.log(` ... (${String(entries.length)} total)`)
|
||||
|
||||
console.log('\n--- fs.readdir() python/mirage/ ---')
|
||||
const core = await fs.promises.readdir('/github/python/mirage')
|
||||
for (const c of core.slice(0, 10)) console.log(` ${c}`)
|
||||
|
||||
console.log('\n--- fs.readdir() python/mirage/core/ ---')
|
||||
const coreDirs = await fs.promises.readdir('/github/python/mirage/core')
|
||||
for (const d of coreDirs.slice(0, 10)) console.log(` ${d}`)
|
||||
if (coreDirs.length > 10) console.log(` ... (${String(coreDirs.length)} total)`)
|
||||
|
||||
console.log('\n--- open() + read pyproject.toml (first 5 lines) ---')
|
||||
const proj = await fs.promises.readFile('/github/python/pyproject.toml', 'utf-8')
|
||||
for (const line of proj.split('\n').slice(0, 5)) console.log(` ${line}`)
|
||||
|
||||
console.log('\n--- open() + read python/mirage/types.py (first 5 lines) ---')
|
||||
const types = await fs.promises.readFile('/github/python/mirage/types.py', 'utf-8')
|
||||
for (const line of types.split('\n').slice(0, 5)) console.log(` ${line}`)
|
||||
|
||||
console.log('\n--- fs.promises.stat().isDirectory() checks ---')
|
||||
const coreStat = await fs.promises.stat('/github/python/mirage/core')
|
||||
console.log(` /github/python/mirage/core: ${String(coreStat.isDirectory())}`)
|
||||
const projStat = await fs.promises.stat('/github/python/pyproject.toml')
|
||||
console.log(` /github/python/pyproject.toml: ${String(projStat.isDirectory())}`)
|
||||
|
||||
console.log('\n--- fs.promises.stat().isFile() checks ---')
|
||||
console.log(` /github/python/pyproject.toml: ${String(projStat.isFile())}`)
|
||||
console.log(` /github/python/mirage/core: ${String(coreStat.isFile())}`)
|
||||
|
||||
const records = ws.records
|
||||
const total = records.reduce((s, r) => s + (r.bytes ?? 0), 0)
|
||||
console.log(`\nStats: ${String(records.length)} ops, ${String(total)} bytes transferred`)
|
||||
} finally {
|
||||
restore()
|
||||
await ws.close()
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err: unknown) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,52 @@
|
||||
// ========= 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. =========
|
||||
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import dotenv from 'dotenv'
|
||||
import { GitHubResource, MountMode, Workspace } from '@struktoai/mirage-node'
|
||||
|
||||
const __HERE = fileURLToPath(new URL('.', import.meta.url))
|
||||
dotenv.config({ path: resolve(__HERE, '../.env.development') })
|
||||
dotenv.config({ path: '/Users/zecheng/strukto/mirage/.env.development' })
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const resource = await GitHubResource.create({
|
||||
token: process.env.GITHUB_TOKEN!,
|
||||
owner: 'strukto-ai',
|
||||
repo: 'mirage',
|
||||
ref: 'main',
|
||||
})
|
||||
const ws = new Workspace({ '/github': resource }, { mode: MountMode.READ })
|
||||
|
||||
console.log('--- ls /github/python/mirage/resource ---')
|
||||
let r = await ws.execute('ls /github/python/mirage/resource')
|
||||
console.log(r.stdoutText)
|
||||
console.log('--- stat /github/python/mirage/resource/base.py ---')
|
||||
r = await ws.execute('stat /github/python/mirage/resource/base.py')
|
||||
console.log('STDOUT:', r.stdoutText)
|
||||
console.log('STDERR:', r.stderrText)
|
||||
console.log('EXIT:', r.exitCode)
|
||||
console.log('--- cat /github/python/mirage/resource/base.py | head -n 5 ---')
|
||||
r = await ws.execute('cat /github/python/mirage/resource/base.py | head -n 5')
|
||||
console.log('STDOUT:', r.stdoutText.slice(0, 300))
|
||||
console.log('STDERR:', r.stderrText)
|
||||
console.log('EXIT:', r.exitCode)
|
||||
await ws.close()
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user