fix(agent-grok): use json import for manifest metadata (#2040)
This commit is contained in:
parent
19fcf42f20
commit
cdd1030d8d
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
"@aoagents/ao": minor
|
||||
"@aoagents/ao-cli": minor
|
||||
"@aoagents/ao-web": minor
|
||||
"@aoagents/ao-plugin-agent-grok": minor
|
||||
---
|
||||
|
||||
Load agent-grok package metadata through JSON import attributes so packaged web and CLI runtimes do not keep a publish-host package.json lookup. This also raises the Node.js engine floor to 20.18.3+, where JSON modules with import attributes are non-experimental.
|
||||
|
|
@ -45,7 +45,7 @@ Agent Orchestrator manages fleets of AI coding agents working in parallel on you
|
|||
|
||||
## Quick Start
|
||||
|
||||
> **Prerequisites:** [Node.js 20+](https://nodejs.org), [Git 2.25+](https://git-scm.com), [`gh` CLI](https://cli.github.com), and:
|
||||
> **Prerequisites:** [Node.js 20.18.3+](https://nodejs.org), [Git 2.25+](https://git-scm.com), [`gh` CLI](https://cli.github.com), and:
|
||||
> - **macOS / Linux:** [tmux](https://github.com/tmux/tmux/wiki/Installing) — install via `brew install tmux` or `sudo apt install tmux`.
|
||||
> - **Windows:** PowerShell 7+ recommended. tmux is **not** required — AO uses native ConPTY via the `runtime-process` plugin (the default on Windows). Set `AO_SHELL=bash` if you have Git Bash and prefer it.
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ For AI agent-specific guidance (including high-risk files like `types.ts`, `life
|
|||
|
||||
## Getting Started
|
||||
|
||||
**Prerequisites**: Node.js 20+, pnpm 9.15+, Git 2.25+
|
||||
**Prerequisites**: Node.js 20.18.3+, pnpm 9.15+, Git 2.25+
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ComposioHQ/agent-orchestrator.git
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "Orchestrate parallel AI coding agents across any runtime, any repo, any issue tracker",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=20.18.3"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.4",
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ npm install -g @aoagents/ao
|
|||
|
||||
> **Nightly builds** (latest `main`): `npm install -g @aoagents/ao@nightly` — back to stable with `@latest`.
|
||||
|
||||
**Prerequisites:** [Node.js 20+](https://nodejs.org), [Git 2.25+](https://git-scm.com), the [`gh` CLI](https://cli.github.com), and at least one coding-agent CLI (e.g. [Claude Code](https://www.anthropic.com/claude-code)).
|
||||
**Prerequisites:** [Node.js 20.18.3+](https://nodejs.org), [Git 2.25+](https://git-scm.com), the [`gh` CLI](https://cli.github.com), and at least one coding-agent CLI (e.g. [Claude Code](https://www.anthropic.com/claude-code)).
|
||||
|
||||
- **macOS / Linux:** [tmux](https://github.com/tmux/tmux/wiki/Installing) — `brew install tmux` or `sudo apt install tmux`.
|
||||
- **Windows:** PowerShell 7+ recommended; tmux is **not** required (AO uses native ConPTY via the `process` runtime).
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
"url": "https://github.com/ComposioHQ/agent-orchestrator/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=20.18.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aoagents/ao-cli": "workspace:*"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
"url": "https://github.com/ComposioHQ/agent-orchestrator/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=20.18.3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc && node --input-type=commonjs -e \"require('fs').cpSync('src/assets','dist/assets',{recursive:true})\"",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
"url": "https://github.com/ComposioHQ/agent-orchestrator/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
"node": ">=20.18.3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import type { AgentLaunchConfig, RuntimeHandle, Session } from "@aoagents/ao-core";
|
||||
import { createRequire } from "node:module";
|
||||
import packageJson from "../../package.json" with { type: "json" };
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const packageJson = require("../../package.json") as {
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
};
|
||||
const PACKAGE_NAME_PREFIX = "@aoagents/ao-plugin-agent-";
|
||||
const pluginName = packageJson.name.startsWith(PACKAGE_NAME_PREFIX)
|
||||
? packageJson.name.slice(PACKAGE_NAME_PREFIX.length)
|
||||
|
|
@ -144,6 +138,7 @@ beforeEach(() => {
|
|||
|
||||
describe("manifest", () => {
|
||||
it("has correct Grok manifest", () => {
|
||||
expect(manifest.version).toBe(packageJson.version);
|
||||
expect(manifest).toEqual({
|
||||
name: pluginName,
|
||||
slot: "agent",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import ts from "typescript";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import packageJson from "../../package.json" with { type: "json" };
|
||||
import { manifest } from "../index.js";
|
||||
|
||||
const testFilePath = fileURLToPath(import.meta.url);
|
||||
const packageRoot = path.resolve(path.dirname(testFilePath), "../..");
|
||||
const sourcePath = path.join(packageRoot, "src/index.ts");
|
||||
|
||||
const forbiddenPackageMetadataLookups = [
|
||||
"createRequire(import.meta.url)",
|
||||
'require("../package.json")',
|
||||
'readFileSync(new URL("../package.json", import.meta.url))',
|
||||
];
|
||||
|
||||
function assertPackageMetadataImportPattern(label: string, source: string): void {
|
||||
for (const forbidden of forbiddenPackageMetadataLookups) {
|
||||
expect(source, `${label} must not contain ${forbidden}`).not.toContain(forbidden);
|
||||
}
|
||||
|
||||
const packageJsonImports = [...source.matchAll(/from\s+["']\.\.\/package\.json["'][^;]*/g)].map(
|
||||
(match) => match[0],
|
||||
);
|
||||
|
||||
expect(packageJsonImports.length, `${label} imports ../package.json`).toBeGreaterThan(0);
|
||||
for (const importStatement of packageJsonImports) {
|
||||
expect(
|
||||
importStatement,
|
||||
`${label} package.json import must use a JSON import attribute`,
|
||||
).toMatch(/\swith\s*\{\s*type:\s*["']json["']\s*\}/);
|
||||
}
|
||||
}
|
||||
|
||||
function compileAgentGrokTo(outDir: string): void {
|
||||
const configPath = path.join(packageRoot, "tsconfig.json");
|
||||
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
||||
if (configFile.error) {
|
||||
throw new Error(
|
||||
ts.formatDiagnosticsWithColorAndContext([configFile.error], {
|
||||
getCanonicalFileName: (fileName) => fileName,
|
||||
getCurrentDirectory: ts.sys.getCurrentDirectory,
|
||||
getNewLine: () => ts.sys.newLine,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const parsedConfig = ts.parseJsonConfigFileContent(
|
||||
configFile.config,
|
||||
ts.sys,
|
||||
packageRoot,
|
||||
{
|
||||
declaration: false,
|
||||
declarationMap: false,
|
||||
outDir,
|
||||
sourceMap: false,
|
||||
},
|
||||
configPath,
|
||||
);
|
||||
|
||||
const program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options);
|
||||
const emitResult = program.emit();
|
||||
const diagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
||||
if (emitResult.emitSkipped || diagnostics.length > 0) {
|
||||
const message =
|
||||
diagnostics.length > 0
|
||||
? ts.formatDiagnosticsWithColorAndContext(diagnostics, {
|
||||
getCanonicalFileName: (fileName) => fileName,
|
||||
getCurrentDirectory: ts.sys.getCurrentDirectory,
|
||||
getNewLine: () => ts.sys.newLine,
|
||||
})
|
||||
: "TypeScript emit skipped without diagnostics.";
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
describe("package metadata import", () => {
|
||||
it("keeps manifest version in sync with package.json", () => {
|
||||
expect(manifest.version).toBe(packageJson.version);
|
||||
});
|
||||
|
||||
it("uses JSON import attributes in the source runtime module", async () => {
|
||||
const source = await readFile(sourcePath, "utf8");
|
||||
assertPackageMetadataImportPattern("src/index.ts", source);
|
||||
});
|
||||
|
||||
it("uses JSON import attributes in the compiled runtime module", async () => {
|
||||
const outDir = await mkdtemp(path.join(tmpdir(), "ao-agent-grok-"));
|
||||
|
||||
try {
|
||||
compileAgentGrokTo(outDir);
|
||||
const compiledSource = await readFile(path.join(outDir, "index.js"), "utf8");
|
||||
assertPackageMetadataImportPattern("compiled index.js", compiledSource);
|
||||
} finally {
|
||||
await rm(outDir, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -22,17 +22,11 @@ import {
|
|||
type WorkspaceHooksConfig,
|
||||
} from "@aoagents/ao-core";
|
||||
import { execFile } from "node:child_process";
|
||||
import { createRequire } from "node:module";
|
||||
import { setTimeout as sleep } from "node:timers/promises";
|
||||
import { promisify } from "node:util";
|
||||
import which from "which";
|
||||
import packageJson from "../package.json" with { type: "json" };
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const packageJson = require("../package.json") as {
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
};
|
||||
const PACKAGE_NAME_PREFIX = "@aoagents/ao-plugin-agent-";
|
||||
const pluginName = packageJson.name.startsWith(PACKAGE_NAME_PREFIX)
|
||||
? packageJson.name.slice(PACKAGE_NAME_PREFIX.length)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.node.json",
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
"bugs": {
|
||||
"url": "https://github.com/ComposioHQ/agent-orchestrator/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.18.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"provenance": true
|
||||
|
|
|
|||
Loading…
Reference in New Issue