mirror of
https://github.com/ComposioHQ/composio.git
synced 2026-09-22 11:46:35 +08:00
0abc629f5d
Rebuilds the Effect v4 port on top of `next` at `effect@4.0.0-rc.112` (the newest release that clears the repository's 3-day `minimumReleaseAge` gate). The three v3-compatible preparation PRs (#4358, #4359, #4360) already landed on `next`, so this PR is now only the cutover. ## What changes - Pins `effect`, `@effect/platform-bun`, and `@effect/vitest` to exact `4.0.0-rc.112`; drops `@effect/cli`, `@effect/platform`, `@effect/platform-node`, and the `toml` override that existed only for `@effect/cli`. The `ts/vendor/effect` source oracle moves to the `effect@4.0.0-rc.112` release commit. - Services become `Context.Service` classes with explicit `Default` layers; `Either` becomes `Result`; `ParseResult` becomes `Schema.SchemaError`; platform modules come from `effect/FileSystem`, `effect/Path`, `effect/PlatformError`, `effect/unstable/process`, and `effect/unstable/http`. - The runner drives `Command.runWith` with v4's default help and error rendering. `CliError.ShowHelp` carries its own exit code, help for non-explicit invocations renders on stderr, and "Did you mean?" suggestions render. `command-introspection.ts` is gone: v4 renders the resolved command's help and the "missing value" tip itself. - `composio --version`, `composio -v`, and `composio version` print the same bare semver (`GlobalFlag.Version` is not enabled; the flag spellings are rewritten to the `version` command before parsing). - Root `--log-level` is a shared flag applied after the subcommand tree is attached, so `composio --log-level Debug <subcommand>` both parses and takes effect. - Every `Flag.boolean` carries an explicit default, because rc.112 makes boolean flags required when omitted. - A `Result` is not an `Effect` at runtime in rc.112 even though the type checker accepts `yield*` on it (the fiber dies with "Not a valid effect"); every `Result` is lifted with `Effect.fromResult`, and the skill/AGENTS guidance says so. - Every `ChildProcess.make` site passes `extendEnv: true`, because rc.112 no longer inherits the parent environment by default. - `--log-level` and `COMPOSIO_LOG_LEVEL` are exact-match on the `LogLevel` names (`All`, `Fatal`, `Error`, `Warn`, `Info`, `Debug`, `Trace`, `None`) with no case folding, per the earlier review decision; README updated. - Spawned children pass `extendEnv: true`, because rc.112's `ChildProcess` no longer inherits the parent environment by default. - ISO timestamps decode through `Schema.DateTimeUtcFromString`; `Schema.DateTimeUtc` is no longer a string codec in rc.112. - `ConfigProvider.fromEnv()` snapshots the environment at construction in v4, so providers that must observe later changes are built per read (`plugin-hint.ts`, `install.cmd.ts`, `config.ts`) and tests use a live-env provider helper. - `cli-keyring` and `json-schema-to-effect-schema` are ported alongside (the latter on `Schema.makeFilter`). - The `effect-v4` skill, the `cli-command` and `typescript-testing` references, `ts/packages/cli/AGENTS.md`, and the oxlint config are updated to the rc.112 reality. The skill's example checker (`.agents/skills/effect-v4/scripts/check-examples.mjs`, lifted from #3851) compiles every TypeScript block in the skill against the pinned packages. - The `js-yaml` overrides move to the 4.3.2 / 3.15.2 lines that GHSA-2883-xcg3-v3hh requires; `pnpm audit --prod` is clean apart from the already-ignored `extract-zip` advisory. ## Behaviour notes - `composio <unknown> --help` now prints the root help with exit 0 (v4's global `--help` handling); `composio <unknown>` without `--help` still fails with the unknown-subcommand error. ## Validation - `pnpm --filter @composio/cli typecheck` (src + test): 0 errors - `pnpm --filter @composio/cli test`: 127 files, 1325 tests pass, 1 skipped; `validate:boundaries` and `validate:skills` pass - `@composio/cli-keyring` and `@composio/json-schema-to-effect-schema` typecheck, test, and build pass - `pnpm validate:agent-skills` and `pnpm validate:skill-routing` pass (19 skills) - oxlint clean on `ts/packages/cli`, `cli-keyring`, `json-schema-to-effect-schema` - CLI bundle and standalone binary build; smoke-checked `version`, `--version`, `-v`, `--help`, unknown subcommand, unrecognized flag, missing flag value - Docker CLI e2e suites pass against an image built from this branch: `version`, `toolkits-list`, `toolkits-info`, `toolkits-search`, `setup-plugins`, `run`. `whoami` (needs an API key), `install` (needs a release dir), and `upgrade` (needs network) were not run. No changeset: `@composio/cli` is Changesets-ignored and the ported sibling packages are private. Human-facing notes are in `ts/packages/cli/CHANGELOG.md`. https://claude.ai/code/session_01AW7ZPhfZuni6PrCJ9X86DX
109 lines
3.8 KiB
TypeScript
109 lines
3.8 KiB
TypeScript
/**
|
|
* Release artifact identity: which platform/arch each published archive targets,
|
|
* and which companion assets belong inside it.
|
|
*
|
|
* Deliberately free of Bun-only imports so the packaging rules stay unit-testable
|
|
* under Node.
|
|
*/
|
|
|
|
import { Data, Option, Result } from 'effect';
|
|
import {
|
|
RUN_COMPANION_ALL_STATIC_ASSET_RELATIVE_PATHS,
|
|
runCompanionStaticAssetRelativePathsFor,
|
|
} from '../src/services/run-companion-modules';
|
|
|
|
export type ReleaseArtifactTarget = {
|
|
readonly artifactName: string;
|
|
readonly platform: NodeJS.Platform;
|
|
readonly arch: string;
|
|
};
|
|
|
|
/**
|
|
* Every published binary artifact, mapped to the Node `platform`/`arch` pair its
|
|
* archive runs on. Artifact names use the `aarch64` spelling; Node calls the same
|
|
* architecture `arm64`.
|
|
*/
|
|
export const RELEASE_ARTIFACT_TARGETS: ReadonlyArray<ReleaseArtifactTarget> = [
|
|
{ artifactName: 'composio-darwin-aarch64', platform: 'darwin', arch: 'arm64' },
|
|
{ artifactName: 'composio-darwin-x64', platform: 'darwin', arch: 'x64' },
|
|
{ artifactName: 'composio-linux-x64', platform: 'linux', arch: 'x64' },
|
|
{ artifactName: 'composio-linux-aarch64', platform: 'linux', arch: 'arm64' },
|
|
];
|
|
|
|
/**
|
|
* Known binary artifact names (without extension).
|
|
*/
|
|
export const ARTIFACT_NAMES: ReadonlyArray<string> = RELEASE_ARTIFACT_TARGETS.map(
|
|
target => target.artifactName
|
|
);
|
|
|
|
export class UnknownReleaseArtifactError extends Data.TaggedError(
|
|
'scripts/UnknownReleaseArtifactError'
|
|
)<{
|
|
readonly artifactName: string;
|
|
}> {
|
|
get message(): string {
|
|
return `Unknown release artifact ${this.artifactName}. Expected one of: ${ARTIFACT_NAMES.join(', ')}.`;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolve an artifact name to its platform/arch. The mapping is total over
|
|
* {@link RELEASE_ARTIFACT_TARGETS}; anything else fails instead of silently
|
|
* producing an archive with no platform-specific assets.
|
|
*/
|
|
export const releaseArtifactTargetFor = (
|
|
artifactName: string
|
|
): Result.Result<ReleaseArtifactTarget, UnknownReleaseArtifactError> =>
|
|
Result.fromOption(
|
|
Option.fromUndefinedOr(
|
|
RELEASE_ARTIFACT_TARGETS.find(target => target.artifactName === artifactName)
|
|
),
|
|
() => new UnknownReleaseArtifactError({ artifactName })
|
|
);
|
|
|
|
export type ArchiveCompanionEntryKind = 'copy' | 'placeholder';
|
|
|
|
export type ArchiveCompanionEntry = {
|
|
readonly relativePath: string;
|
|
readonly kind: ArchiveCompanionEntryKind;
|
|
};
|
|
|
|
/**
|
|
* Decide how each companion asset enters one archive.
|
|
*
|
|
* An archive already carries a platform-specific `composio` binary, so only one
|
|
* of the four codex-acp binaries inside it can ever execute. The other three are
|
|
* ~651 MB that every machine unpacking this archive downloads, stores, and can
|
|
* never run.
|
|
*
|
|
* They cannot simply be dropped. A CLI released before 2026-08-18 verifies a
|
|
* downloaded upgrade package against all four codex-acp paths and refuses to
|
|
* install one that is missing any of them, so omitting them breaks
|
|
* `composio upgrade` for every client already in the field. An empty placeholder
|
|
* satisfies that existence check at zero bytes, and no host ever executes a
|
|
* foreign codex-acp binary, so the placeholder is never read.
|
|
*
|
|
* Once no supported client performs that check, placeholders can become plain
|
|
* omissions.
|
|
*/
|
|
export const archiveCompanionEntries = ({
|
|
allRelativePaths,
|
|
target,
|
|
}: {
|
|
readonly allRelativePaths: ReadonlyArray<string>;
|
|
readonly target: ReleaseArtifactTarget;
|
|
}): ReadonlyArray<ArchiveCompanionEntry> => {
|
|
const executableHere = new Set(runCompanionStaticAssetRelativePathsFor(target));
|
|
const foreignCodexPaths = new Set(
|
|
RUN_COMPANION_ALL_STATIC_ASSET_RELATIVE_PATHS.filter(
|
|
relativePath => !executableHere.has(relativePath)
|
|
)
|
|
);
|
|
|
|
return allRelativePaths.map(relativePath => ({
|
|
relativePath,
|
|
kind: foreignCodexPaths.has(relativePath) ? ('placeholder' as const) : ('copy' as const),
|
|
}));
|
|
};
|