feat: integrate mobile work chat and Gitea delivery

This commit is contained in:
sai karthik
2026-07-26 00:50:11 +05:30
parent 48200a11df
commit 2a0487aa6e
31 changed files with 2477 additions and 220 deletions

View File

@@ -0,0 +1,85 @@
import { readFileSync } from "node:fs";
import git from "@agentos-software/git";
import { describe, expect, it } from "vitest";
import {
getExecutableGitSoftware,
makeGitExecutablesRunnable,
} from "./agent-os-git-software";
const TAR_BLOCK_SIZE = 512;
const READ_ONLY_EXECUTABLE_MODE = Buffer.from([0xa4, 0x81, 0x00, 0x00]);
const RUNNABLE_EXECUTABLE_MODE = Buffer.from([0xed, 0x81, 0x00, 0x00]);
const readTarModes = (packageBytes: Buffer): Map<string, number> => {
const tarOffset =
16 + packageBytes.readUInt32LE(8) + packageBytes.readUInt32LE(12);
const modes = new Map<string, number>();
let offset = tarOffset;
while (
offset + TAR_BLOCK_SIZE <= packageBytes.length &&
packageBytes
.subarray(offset, offset + TAR_BLOCK_SIZE)
.some((byte) => byte !== 0)
) {
const [name = ""] = packageBytes
.subarray(offset, offset + 100)
.toString("utf-8")
.split("\0");
const mode = Number.parseInt(
packageBytes
.subarray(offset + 100, offset + 108)
.toString("ascii")
.replaceAll("\0", "")
.trim(),
8
);
const size = Number.parseInt(
packageBytes
.subarray(offset + 124, offset + 136)
.toString("ascii")
.replaceAll("\0", "")
.trim() || "0",
8
);
modes.set(name, mode);
offset +=
TAR_BLOCK_SIZE + Math.ceil(size / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
}
return modes;
};
describe("AgentOS Git software", () => {
it("marks the packaged Git commands executable", () => {
const repaired = makeGitExecutablesRunnable(readFileSync(git.packagePath));
const modes = readTarModes(repaired);
expect(modes.get("./bin/git")).toBe(0o755);
expect(modes.get("./bin/git-remote-http")).toBe(0o755);
expect(modes.get("./bin/git-remote-https")).toBe(0o755);
expect(repaired.includes(Buffer.from("0.3.0-zp.1", "ascii"))).toBe(true);
const mountIndexOffset = 16 + repaired.readUInt32LE(8);
const tarOffset = mountIndexOffset + repaired.readUInt32LE(12);
const mountIndex = repaired.subarray(mountIndexOffset, tarOffset);
expect(mountIndex.includes(READ_ONLY_EXECUTABLE_MODE)).toBe(false);
expect(
mountIndex.toString("hex").split(RUNNABLE_EXECUTABLE_MODE.toString("hex"))
.length - 1
).toBe(3);
});
it("writes a stable repaired package for the AgentOS registry", () => {
const first = getExecutableGitSoftware();
const second = getExecutableGitSoftware();
expect(second).toEqual(first);
expect(readTarModes(readFileSync(first.packagePath)).get("./bin/git")).toBe(
0o755
);
});
});

View File

@@ -0,0 +1,194 @@
import { createHash } from "node:crypto";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import git from "@agentos-software/git";
const AOS_PACKAGE_MAGIC = Buffer.from([0x89, 0x41, 0x4f, 0x53]);
const TAR_BLOCK_SIZE = 512;
const TAR_CHECKSUM_OFFSET = 148;
const TAR_CHECKSUM_SIZE = 8;
const TAR_MODE_OFFSET = 100;
const TAR_MODE_SIZE = 8;
const TAR_NAME_SIZE = 100;
const TAR_SIZE_OFFSET = 124;
const TAR_SIZE_SIZE = 12;
const GIT_EXECUTABLES = new Set([
"./bin/git",
"./bin/git-remote-http",
"./bin/git-remote-https",
]);
const UPSTREAM_GIT_PACKAGE_VERSION = Buffer.from("0.3.0-rc.2", "ascii");
const REPAIRED_GIT_PACKAGE_VERSION = Buffer.from("0.3.0-zp.1", "ascii");
const READ_ONLY_EXECUTABLE_MODE = Buffer.from([0xa4, 0x81, 0x00, 0x00]);
const RUNNABLE_EXECUTABLE_MODE = Buffer.from([0xed, 0x81, 0x00, 0x00]);
const parseTarOctal = (
packageBytes: Buffer,
offset: number,
length: number
): number => {
const value = packageBytes
.subarray(offset, offset + length)
.toString("ascii")
.replaceAll("\0", "")
.trim();
return value.length === 0 ? 0 : Number.parseInt(value, 8);
};
const readTarName = (packageBytes: Buffer, headerOffset: number): string => {
const [name = ""] = packageBytes
.subarray(headerOffset, headerOffset + TAR_NAME_SIZE)
.toString("utf-8")
.split("\0");
return name;
};
const isEmptyTarHeader = (
packageBytes: Buffer,
headerOffset: number
): boolean =>
packageBytes
.subarray(headerOffset, headerOffset + TAR_BLOCK_SIZE)
.every((byte) => byte === 0);
const writeTarChecksum = (packageBytes: Buffer, headerOffset: number): void => {
packageBytes.fill(
0x20,
headerOffset + TAR_CHECKSUM_OFFSET,
headerOffset + TAR_CHECKSUM_OFFSET + TAR_CHECKSUM_SIZE
);
let checksum = 0;
for (
let index = headerOffset;
index < headerOffset + TAR_BLOCK_SIZE;
index += 1
) {
checksum += packageBytes[index] ?? 0;
}
const encodedChecksum = `${checksum.toString(8).padStart(6, "0")}\0 `;
packageBytes.write(
encodedChecksum,
headerOffset + TAR_CHECKSUM_OFFSET,
TAR_CHECKSUM_SIZE,
"ascii"
);
};
const getTarOffset = (packageBytes: Buffer): number => {
if (
packageBytes.length < 16 ||
!packageBytes
.subarray(0, AOS_PACKAGE_MAGIC.length)
.equals(AOS_PACKAGE_MAGIC)
) {
throw new Error("Invalid AgentOS package header");
}
return 16 + packageBytes.readUInt32LE(8) + packageBytes.readUInt32LE(12);
};
export const makeGitExecutablesRunnable = (source: Uint8Array): Buffer => {
const packageBytes = Buffer.from(source);
const mountIndexOffset = 16 + packageBytes.readUInt32LE(8);
const tarOffset = getTarOffset(packageBytes);
const versionOffset = packageBytes.indexOf(
UPSTREAM_GIT_PACKAGE_VERSION,
0,
"ascii"
);
if (versionOffset === -1 || versionOffset >= tarOffset) {
throw new Error("Expected AgentOS Git package version was not found");
}
REPAIRED_GIT_PACKAGE_VERSION.copy(packageBytes, versionOffset);
let mountModeOffset = mountIndexOffset;
let repairedMountEntries = 0;
while (mountModeOffset < tarOffset) {
mountModeOffset = packageBytes.indexOf(
READ_ONLY_EXECUTABLE_MODE,
mountModeOffset
);
if (mountModeOffset < 0 || mountModeOffset >= tarOffset) {
break;
}
RUNNABLE_EXECUTABLE_MODE.copy(packageBytes, mountModeOffset);
repairedMountEntries += 1;
mountModeOffset += RUNNABLE_EXECUTABLE_MODE.length;
}
if (repairedMountEntries !== GIT_EXECUTABLES.size) {
throw new Error(
`Expected ${GIT_EXECUTABLES.size} Git mount entries, repaired ${repairedMountEntries}`
);
}
let headerOffset = tarOffset;
let repairedExecutables = 0;
while (
headerOffset + TAR_BLOCK_SIZE <= packageBytes.length &&
!isEmptyTarHeader(packageBytes, headerOffset)
) {
const name = readTarName(packageBytes, headerOffset);
const size = parseTarOctal(
packageBytes,
headerOffset + TAR_SIZE_OFFSET,
TAR_SIZE_SIZE
);
if (GIT_EXECUTABLES.has(name)) {
packageBytes.write(
"0000755\0",
headerOffset + TAR_MODE_OFFSET,
TAR_MODE_SIZE,
"ascii"
);
writeTarChecksum(packageBytes, headerOffset);
repairedExecutables += 1;
}
headerOffset +=
TAR_BLOCK_SIZE + Math.ceil(size / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
}
if (repairedExecutables !== GIT_EXECUTABLES.size) {
throw new Error(
`Expected ${GIT_EXECUTABLES.size} Git executables, repaired ${repairedExecutables}`
);
}
return packageBytes;
};
let cachedGitSoftware: { readonly packagePath: string } | undefined;
export const getExecutableGitSoftware = (): {
readonly packagePath: string;
} => {
if (cachedGitSoftware) {
return cachedGitSoftware;
}
const source = readFileSync(git.packagePath);
const repaired = makeGitExecutablesRunnable(source);
const digest = createHash("sha256")
.update(repaired)
.digest("hex")
.slice(0, 16);
const cacheDirectory = path.join(tmpdir(), "zopu-agentos-software");
const packagePath = path.join(cacheDirectory, `git-${digest}.aospkg`);
mkdirSync(cacheDirectory, { recursive: true });
if (!existsSync(packagePath)) {
writeFileSync(packagePath, repaired);
}
cachedGitSoftware = { packagePath };
return cachedGitSoftware;
};

View File

@@ -1,15 +1,16 @@
/* eslint-disable max-classes-per-file -- the AgentOS service and its tagged error form one adapter contract. */
import codex from "@agentos-software/codex-cli";
import git from "@agentos-software/git";
import { agentOS as createAgentOsActor } from "@rivet-dev/agentos";
import type { AgentOSConfigInput } from "@rivet-dev/agentos";
import { Context, Effect, Layer, Schema } from "effect";
import { getExecutableGitSoftware } from "./agent-os-git-software";
const withGitSoftware = (
config: AgentOSConfigInput<undefined>
): AgentOSConfigInput<undefined> => ({
...config,
software: [git, ...(config.software ?? [])],
software: [getExecutableGitSoftware(), ...(config.software ?? [])],
});
export class AgentOsError extends Schema.TaggedErrorClass<AgentOsError>()(
@@ -83,7 +84,7 @@ export const createAgentOsActorEffect = Effect.fn("createAgentOsActorEffect")(
// ---------------------------------------------------------------------------
/** Software bundle for a Codex-capable VM: the Codex harness plus git. */
export const codexSoftware = [codex, git] as const;
export const codexSoftware = [codex, getExecutableGitSoftware()] as const;
/** Model-provider env that Codex reads inside the VM. Pass this to the session's
* `env` when opening a Codex session (`agent: "codex"`). */

View File

@@ -73,6 +73,16 @@ describe("project workspace primitives", () => {
operation._tag === "Exec" && operation.command.includes("git clone")
)
).toBe(true);
const checkoutOperation = plan.operations.find(
(operation) => operation._tag === "Exec"
);
expect(checkoutOperation?._tag).toBe("Exec");
if (checkoutOperation?._tag === "Exec") {
expect(checkoutOperation.command).not.toContain("--single-branch");
expect(checkoutOperation.command).toContain(
"checkout -b 'work/issue-7-abc123'"
);
}
});
it("rejects unsafe sources and control-file paths", () => {

View File

@@ -260,17 +260,18 @@ const makeCheckoutCommand = (input: {
readonly sourceUrl: string;
}): string => {
const checkout = shellQuote(input.checkoutPath);
const baseBranch = shellQuote(input.baseBranch);
const branch = shellQuote(input.branchName);
const originBaseBranch = shellQuote(`origin/${input.baseBranch}`);
const branchRef = shellQuote(
`${input.checkoutPath}/.git/refs/heads/${input.branchName}`
);
const source = shellQuote(input.sourceUrl);
return [
"set -eu",
`mkdir -p ${shellQuote(WORKSPACE_PATH)}`,
`if [ ! -d ${checkout}/.git ]; then git clone --branch ${baseBranch} --single-branch ${source} ${checkout}; fi`,
`if [ "$(git -C ${checkout} branch --show-current)" != ${branch} ]; then git -C ${checkout} show-ref --verify --quiet refs/heads/${branch} && git -C ${checkout} checkout ${branch} || git -C ${checkout} checkout -b ${branch} ${originBaseBranch}; fi`,
`printf '%s\\n' "$(git -C ${checkout} branch --show-current)" "$(git -C ${checkout} rev-parse HEAD)"`,
`if [ ! -d ${checkout}/.git ]; then git clone ${source} ${checkout}; fi`,
`if [ -f ${branchRef} ]; then git -C ${checkout} checkout ${branch}; else git -C ${checkout} checkout -b ${branch}; fi`,
`printf '%s\\n' ${branch} "$(git -C ${checkout} rev-parse HEAD)"`,
].join(" && ");
};