mirror of
https://github.com/Orkas-AI/Orkas.git
synced 2026-11-09 17:39:33 -10:00
Add device-local CLI and merchant connector workflows with catalog-guided
setup, scoped authorization, encrypted credentials, and action confirmation.
Extend task queues, retry recovery, project to-dos, library processing, local
agent inputs, Office artifacts, and desktop notification/navigation handling.
Update shared agents, skills, tool contracts, resource fixtures, and coverage.
Preserve newer conversation drafts and reference identities across delayed
send acceptance and navigation. Publish process-test readiness atomically
so cleanup scenarios cannot observe a partially written PID record.
Retain the independent date version, Linux source runtime, existing BYO
provider policies, production API-key access, and open-source settings.
Prompt confirmation:
Confirmed-by: Requester in the current implementation task
Scope: Apply the existing approved shared agent, skill, task, and connector
capabilities within the documented open-source product boundaries.
Prompt audit:
- Keep: Commander and actor task identity, ordered execution, user input,
project context, and tool-use responsibilities in the shared prompt
templates and their existing assembly path. Type: resident.
Why: These clauses determine behavior across ordinary turns; the update
preserves the shared product's source-of-truth context and recovery
ownership without adding an independent open-source policy layer.
- Keep: Project-task, scheduling, memory, connector setup, UI artifact,
image/video composition, Office, and SEO workflows in their owning
skills and referenced guides. Type: on-demand.
Why: Load specialized procedures only for the corresponding work; retain
source metadata and dependency ownership rather than duplicate those
procedures in every actor prompt.
- Keep: Scoped tool schemas, queue/permission state, persisted recovery
evidence, output storage, resource manifests, and deterministic validators
at their existing host boundaries. Type: non-prompt enforcement.
Why: Code and structured events own the invariants and prevent the prompt
from becoming a second authorization, persistence, or execution engine.
- Drop: Hosted account, membership, cloud/relay, telemetry, internal debug,
managed voice, watermark, welcome, and official updater instructions or
affordances from the public execution paths. Type: source-only/on-demand.
Why: Those paths require services absent from the open-source product;
shared local operations and public API-key/BYO capabilities remain usable.
Validation: Full deterministic JavaScript and resource suites, platform
native and GUI checks, typechecks, startup smoke, public endpoint contracts,
Office artifact/fixture smoke, and desktop E2E are recorded with the frozen
tree with emitted-log review.
156 lines
5.7 KiB
PowerShell
156 lines
5.7 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string]$PcRoot = '',
|
|
[string]$Architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version Latest
|
|
|
|
if (-not $PcRoot) {
|
|
$PcRoot = Split-Path -Parent $PSScriptRoot
|
|
}
|
|
|
|
$runtimeRoot = Join-Path $PcRoot 'resources\runtime'
|
|
$manifestPath = Join-Path $runtimeRoot 'manifest.json'
|
|
$manifest = Get-Content -Raw -LiteralPath $manifestPath | ConvertFrom-Json
|
|
|
|
$platformKey = switch ($Architecture) {
|
|
'X64' { 'win32-x64' }
|
|
'Arm64' { 'win32-arm64' }
|
|
default { throw "Unsupported Windows architecture for the bundled Node runtime: $Architecture" }
|
|
}
|
|
|
|
$nodeSpec = $manifest.node
|
|
$assetProperty = $nodeSpec.assets.PSObject.Properties[$platformKey]
|
|
if (-not $assetProperty) {
|
|
throw "Node runtime asset is missing from the manifest: $platformKey"
|
|
}
|
|
$asset = $assetProperty.Value
|
|
$nodeRoot = Join-Path (Join-Path $runtimeRoot 'node') $platformKey
|
|
$nodeExe = Join-Path $nodeRoot 'node.exe'
|
|
$npmCmd = Join-Path $nodeRoot 'npm.cmd'
|
|
$npxCmd = Join-Path $nodeRoot 'npx.cmd'
|
|
$markerPath = Join-Path $nodeRoot '.orkas-runtime.json'
|
|
|
|
function Test-InstalledNode {
|
|
if (-not (Test-Path -LiteralPath $nodeExe -PathType Leaf) -or
|
|
-not (Test-Path -LiteralPath $npmCmd -PathType Leaf) -or
|
|
-not (Test-Path -LiteralPath $npxCmd -PathType Leaf) -or
|
|
-not (Test-Path -LiteralPath $markerPath -PathType Leaf)) {
|
|
return $false
|
|
}
|
|
try {
|
|
$marker = Get-Content -Raw -LiteralPath $markerPath | ConvertFrom-Json
|
|
if ($marker.schema -ne 1 -or
|
|
$marker.kind -ne 'node' -or
|
|
$marker.platformKey -ne $platformKey -or
|
|
$marker.version -ne $nodeSpec.version -or
|
|
$marker.sha256 -ne $asset.sha256) {
|
|
return $false
|
|
}
|
|
$version = (& $nodeExe --version 2>$null).Trim()
|
|
return $LASTEXITCODE -eq 0 -and $version -eq "v$($nodeSpec.version)"
|
|
} catch {
|
|
return $false
|
|
}
|
|
}
|
|
|
|
if (Test-InstalledNode) {
|
|
Write-Host "[node-bootstrap] bundled Node $($nodeSpec.version) is ready"
|
|
return
|
|
}
|
|
|
|
$nodeParent = Split-Path -Parent $nodeRoot
|
|
New-Item -ItemType Directory -Force -Path $nodeParent | Out-Null
|
|
$tempRoot = Join-Path $nodeParent ('.bootstrap-{0}-{1}' -f $PID, [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds())
|
|
$archivePath = Join-Path $tempRoot $asset.name
|
|
$extractRoot = Join-Path $tempRoot 'extract'
|
|
$payloadRoot = Join-Path $tempRoot 'payload'
|
|
$backupRoot = "$nodeRoot.bak-$PID"
|
|
|
|
try {
|
|
New-Item -ItemType Directory -Force -Path $extractRoot, $payloadRoot | Out-Null
|
|
Write-Host "[node-bootstrap] downloading Node $($nodeSpec.version) for $platformKey..."
|
|
Invoke-WebRequest -UseBasicParsing -Uri $asset.url -OutFile $archivePath -TimeoutSec 600
|
|
|
|
$actualSize = (Get-Item -LiteralPath $archivePath).Length
|
|
if ($actualSize -ne [int64]$asset.size) {
|
|
throw "Node archive size mismatch: expected $($asset.size), got $actualSize"
|
|
}
|
|
$actualSha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $archivePath).Hash.ToLowerInvariant()
|
|
if ($actualSha256 -ne ([string]$asset.sha256).ToLowerInvariant()) {
|
|
throw "Node archive SHA-256 mismatch"
|
|
}
|
|
|
|
Expand-Archive -LiteralPath $archivePath -DestinationPath $extractRoot -Force
|
|
$sourceRoot = Get-ChildItem -LiteralPath $extractRoot -Directory |
|
|
Where-Object { $_.Name -like 'node-v*' } |
|
|
Select-Object -First 1
|
|
if (-not $sourceRoot) {
|
|
throw 'Node archive did not contain the expected top-level directory'
|
|
}
|
|
Get-ChildItem -LiteralPath $sourceRoot.FullName -Force |
|
|
Copy-Item -Destination $payloadRoot -Recurse -Force
|
|
|
|
$payloadNode = Join-Path $payloadRoot 'node.exe'
|
|
$payloadNpm = Join-Path $payloadRoot 'npm.cmd'
|
|
$payloadNpx = Join-Path $payloadRoot 'npx.cmd'
|
|
if (-not (Test-Path -LiteralPath $payloadNode -PathType Leaf) -or
|
|
-not (Test-Path -LiteralPath $payloadNpm -PathType Leaf) -or
|
|
-not (Test-Path -LiteralPath $payloadNpx -PathType Leaf)) {
|
|
throw 'Node archive is missing node.exe, npm.cmd, or npx.cmd'
|
|
}
|
|
$version = (& $payloadNode --version).Trim()
|
|
if ($LASTEXITCODE -ne 0 -or $version -ne "v$($nodeSpec.version)") {
|
|
throw "Node self-check failed: expected v$($nodeSpec.version), got $version"
|
|
}
|
|
|
|
$marker = [ordered]@{
|
|
schema = 1
|
|
kind = 'node'
|
|
platformKey = $platformKey
|
|
version = $nodeSpec.version
|
|
source = $nodeSpec.source
|
|
release = $nodeSpec.release
|
|
asset = $asset.name
|
|
sha256 = $asset.sha256
|
|
size = [int64]$asset.size
|
|
installedAt = [DateTime]::UtcNow.ToString('o')
|
|
}
|
|
$markerJson = $marker | ConvertTo-Json
|
|
$markerEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
[System.IO.File]::WriteAllText(
|
|
(Join-Path $payloadRoot '.orkas-runtime.json'),
|
|
$markerJson,
|
|
$markerEncoding
|
|
)
|
|
|
|
if (Test-Path -LiteralPath $backupRoot) {
|
|
Remove-Item -Recurse -Force -LiteralPath $backupRoot
|
|
}
|
|
if (Test-Path -LiteralPath $nodeRoot) {
|
|
Move-Item -LiteralPath $nodeRoot -Destination $backupRoot
|
|
}
|
|
try {
|
|
Move-Item -LiteralPath $payloadRoot -Destination $nodeRoot
|
|
if (Test-Path -LiteralPath $backupRoot) {
|
|
Remove-Item -Recurse -Force -LiteralPath $backupRoot
|
|
}
|
|
} catch {
|
|
if (Test-Path -LiteralPath $nodeRoot) {
|
|
Remove-Item -Recurse -Force -LiteralPath $nodeRoot
|
|
}
|
|
if (Test-Path -LiteralPath $backupRoot) {
|
|
Move-Item -LiteralPath $backupRoot -Destination $nodeRoot
|
|
}
|
|
throw
|
|
}
|
|
|
|
Write-Host "[node-bootstrap] Node $($nodeSpec.version) is ready"
|
|
} finally {
|
|
if (Test-Path -LiteralPath $tempRoot) {
|
|
Remove-Item -Recurse -Force -LiteralPath $tempRoot
|
|
}
|
|
}
|