Repository navigation
Expand file tree
/
Copy pathruntime-support.ts
More file actions
48 lines (44 loc) · 2.78 KB
/
Copy pathruntime-support.ts
File metadata and controls
48 lines (44 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* CodeNomad's Images gallery, Design agent and Images settings consume the image
* tool contract of upstream anomalyco/opencode#60258: one name,
* `experimental_image_generate`, for the tool, its permission action, its job type
* and its completion notice's `metadata.source`, and the tool on unless
* `experimental.image_generate` is `false`. The minimum also provides the native
* replay contract read by the pinned client reducer and codecs (`native` provider
* data, `metadata.keepID` compactions, `native.messages` windows) and Code Mode
* jobs that keep JavaScript run-to-completion (scripts/test-codemode-jobs-native.mjs).
* OpenCode reads data stored by older releases. See
* dev-docs/OPENCODE_COMPATIBILITY.md for the demonstrated boundary.
*/
export const MINIMUM_OPENCODE_VERSION = "2.2.3"
/** Qualification target, independent of the technically required minimum. */
export const RECOMMENDED_OPENCODE_VERSION = "2.2.5"
export const OPENCODE_UPDATE_REQUIRED = "opencode_update_required"
export function isBelowOpenCodeMinimum(version: string): boolean {
// These historical V2 beta publications predate the stable event contract.
if (/^0\.0\.0-beta-\d+$/.test(version)) return true
const match = /^(\d+)\.(\d+)\.(\d+)(?:\+[\w.-]+)?$/.exec(version)
// Custom/prerelease labels are unverified, not automatically incompatible.
// Their authenticated API contract is inspected before functional requests.
if (!match) return false
const [major, minor, patch] = match.slice(1).map(Number)
const [minimumMajor, minimumMinor, minimumPatch] = MINIMUM_OPENCODE_VERSION.split(".").map(Number)
return major! < minimumMajor! || (major === minimumMajor && (minor! < minimumMinor!
|| (minor === minimumMinor && patch! < minimumPatch!)))
}
export type OpenCodeIncompatibility = "native_contract" | "canonical_api" | "session_environment"
export class UnsupportedOpenCodeError extends Error {
readonly code = OPENCODE_UPDATE_REQUIRED
readonly statusCode = 426
readonly minimumVersion = MINIMUM_OPENCODE_VERSION
constructor(readonly actualVersion: string, readonly reason: OpenCodeIncompatibility = "native_contract") {
super(`${OPENCODE_UPDATE_REQUIRED}: OpenCode ${actualVersion}; ${reason === "native_contract"
? `requires the experimental_image_generate tool contract, native replay and compaction contract (native, metadata.keepID) and Code Mode job ordering of ${MINIMUM_OPENCODE_VERSION}`
: reason === "session_environment" ? "requires PUT /api/session/{sessionID}/environment with variables"
: "does not expose the canonical session, permission, Form and inbox API contract"}`)
this.name = "UnsupportedOpenCodeError"
}
}
export function assertSupportedOpenCode(version: string): void {
if (isBelowOpenCodeMinimum(version)) throw new UnsupportedOpenCodeError(version)
}