mirror of
https://github.com/Orkas-AI/Orkas.git
synced 2026-11-07 06:16:03 -10:00
Preserve keyboard focus and single activation across task-board refreshes. Add task-scoped grants, partial-permission recovery, validated CLI attachments, device-local project directories, and the public model catalog update.
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: Recorded 11,721 deterministic tests, 538 resource tests, 1,248 native tests, five GUI checks and 198 reconciled desktop scenarios; final keyboard owner regressions also passed. Initial failed runs and classified warnings are retained in validation evidence.
208 lines
7.7 KiB
JavaScript
208 lines
7.7 KiB
JavaScript
'use strict';
|
|
|
|
const { spawnSync } = require('node:child_process');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { sharpPreparationFiles } = require('../bin/native-package-gate.cjs');
|
|
const {
|
|
ensureFile,
|
|
isMachArch,
|
|
markerMatches,
|
|
packagePath,
|
|
packageVersion,
|
|
readLockPackage,
|
|
scriptHashes,
|
|
writeMarker,
|
|
} = require('./native-prepare-cache.cjs');
|
|
|
|
const PC_DIR = path.resolve(__dirname, '..');
|
|
const LOCK_FILE = path.join(PC_DIR, 'package-lock.json');
|
|
const CACHE_HELPER = path.join(__dirname, 'native-prepare-cache.cjs');
|
|
const TARGET_PLATFORM = 'darwin';
|
|
|
|
function npmCmd(platform = process.platform) {
|
|
return platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
}
|
|
|
|
function run(cwd, command, args, options = {}) {
|
|
const result = spawnSync(command, args, {
|
|
cwd,
|
|
stdio: options.stdio || 'inherit',
|
|
encoding: options.encoding,
|
|
shell: false,
|
|
});
|
|
if (result.error) throw result.error;
|
|
if (result.status !== 0) {
|
|
throw new Error(`${command} ${args.join(' ')} failed with exit code ${result.status}`);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function npmPack(cwd, spec) {
|
|
const result = run(cwd, npmCmd(), ['pack', spec, '--json'], {
|
|
encoding: 'utf8',
|
|
stdio: ['ignore', 'pipe', 'inherit'],
|
|
});
|
|
const packs = JSON.parse(result.stdout);
|
|
const filename = packs?.[0]?.filename;
|
|
if (!filename) {
|
|
throw new Error(`npm pack ${spec} did not report an output filename`);
|
|
}
|
|
return path.join(cwd, filename);
|
|
}
|
|
|
|
function ensureEsbuildPackage(platformName) {
|
|
const packageName = `@esbuild/${platformName}`;
|
|
const required = [path.join(PC_DIR, 'node_modules', '@esbuild', platformName, 'bin', 'esbuild')];
|
|
ensurePackageFromRegistry(packageName, required);
|
|
}
|
|
|
|
function allFilesExist(files) {
|
|
return files.every((file) => fs.existsSync(file) && fs.statSync(file).isFile());
|
|
}
|
|
|
|
function ensurePackageFromRegistry(packageName, requiredFiles = []) {
|
|
const version = readLockPackage(LOCK_FILE, packageName);
|
|
const targetDir = packagePath(PC_DIR, packageName);
|
|
|
|
if (packageVersion(PC_DIR, packageName) === version && allFilesExist(requiredFiles)) {
|
|
console.log(`[prepare-mac-native-deps] reusing ${packageName}@${version}`);
|
|
return;
|
|
}
|
|
|
|
console.log(`[prepare-mac-native-deps] ensuring ${packageName}@${version}`);
|
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'orkas-mac-native-deps-'));
|
|
try {
|
|
const tarball = npmPack(tmpDir, `${packageName}@${version}`);
|
|
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
const archiveName = path.basename(tarball);
|
|
const localTarball = path.join(targetDir, archiveName);
|
|
fs.copyFileSync(tarball, localTarball);
|
|
try {
|
|
run(targetDir, 'tar', ['-xzf', archiveName, '--strip-components=1']);
|
|
} finally {
|
|
fs.rmSync(localTarball, { force: true });
|
|
}
|
|
} finally {
|
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
function removeDirectories(parentDir, shouldRemove) {
|
|
if (!fs.existsSync(parentDir) || !fs.statSync(parentDir).isDirectory()) {
|
|
return;
|
|
}
|
|
for (const entry of fs.readdirSync(parentDir, { withFileTypes: true })) {
|
|
if (entry.isDirectory() && shouldRemove(entry.name)) {
|
|
fs.rmSync(path.join(parentDir, entry.name), { recursive: true, force: true });
|
|
}
|
|
}
|
|
}
|
|
|
|
function expectedState(targetArch) {
|
|
return {
|
|
schema: 1,
|
|
platform: TARGET_PLATFORM,
|
|
arch: targetArch,
|
|
scriptHashes: scriptHashes({
|
|
prepareMacNativeDeps: __filename,
|
|
nativePrepareCache: CACHE_HELPER,
|
|
nativePackageGate: require.resolve('../bin/native-package-gate.cjs'),
|
|
}),
|
|
packages: {
|
|
[`@esbuild/darwin-${targetArch}`]: readLockPackage(LOCK_FILE, `@esbuild/darwin-${targetArch}`),
|
|
[`sqlite-vec-darwin-${targetArch}`]: readLockPackage(LOCK_FILE, `sqlite-vec-darwin-${targetArch}`),
|
|
[`@napi-rs/canvas-darwin-${targetArch}`]: readLockPackage(LOCK_FILE, `@napi-rs/canvas-darwin-${targetArch}`),
|
|
[`@img/sharp-darwin-${targetArch}`]: readLockPackage(LOCK_FILE, `@img/sharp-darwin-${targetArch}`),
|
|
[`@img/sharp-libvips-darwin-${targetArch}`]: readLockPackage(LOCK_FILE, `@img/sharp-libvips-darwin-${targetArch}`),
|
|
},
|
|
};
|
|
}
|
|
|
|
function assertMachArch(label, file, targetArch) {
|
|
ensureFile(label, file);
|
|
if (!isMachArch(file, targetArch)) {
|
|
throw new Error(`${label} is not macOS ${targetArch}: ${file}`);
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const targetArch = process.argv[2] || process.env.ORKAS_TARGET_ARCH || process.arch;
|
|
if (!['arm64', 'x64'].includes(targetArch)) {
|
|
throw new Error(`[prepare-mac-native-deps] unsupported macOS arch: ${targetArch}`);
|
|
}
|
|
|
|
fs.mkdirSync(path.join(PC_DIR, 'node_modules', '@esbuild'), { recursive: true });
|
|
fs.mkdirSync(path.join(PC_DIR, 'node_modules', '@img'), { recursive: true });
|
|
|
|
const state = expectedState(targetArch);
|
|
const sharpVersion = state.packages[`@img/sharp-darwin-${targetArch}`];
|
|
const sharpFiles = sharpPreparationFiles('darwin', targetArch, sharpVersion);
|
|
const required = {
|
|
esbuild: path.join(PC_DIR, 'node_modules', '@esbuild', `darwin-${targetArch}`, 'bin', 'esbuild'),
|
|
sqliteVec: path.join(PC_DIR, 'node_modules', `sqlite-vec-darwin-${targetArch}`, 'vec0.dylib'),
|
|
canvas: path.join(PC_DIR, 'node_modules', '@napi-rs', `canvas-darwin-${targetArch}`, `skia.darwin-${targetArch}.node`),
|
|
sharp: path.join(PC_DIR, 'node_modules', sharpFiles.binding),
|
|
sharpVips: path.join(PC_DIR, 'node_modules', sharpFiles.cpp),
|
|
};
|
|
const requiredFiles = Object.values(required);
|
|
const targetFilesMatch = () => requiredFiles.every((file) => isMachArch(file, targetArch));
|
|
if (markerMatches(PC_DIR, state, requiredFiles, targetFilesMatch)) {
|
|
console.log(`[prepare-mac-native-deps] using cached macOS ${targetArch} native dependencies`);
|
|
return;
|
|
}
|
|
|
|
ensureEsbuildPackage(`darwin-${targetArch}`);
|
|
ensurePackageFromRegistry(`sqlite-vec-darwin-${targetArch}`, [required.sqliteVec]);
|
|
ensurePackageFromRegistry(`@napi-rs/canvas-darwin-${targetArch}`, [required.canvas]);
|
|
ensurePackageFromRegistry(`@img/sharp-darwin-${targetArch}`, [required.sharp]);
|
|
ensurePackageFromRegistry(`@img/sharp-libvips-darwin-${targetArch}`, [required.sharpVips]);
|
|
|
|
console.log(`[prepare-mac-native-deps] pruning non-${targetArch} native runtime packages`);
|
|
removeDirectories(path.join(PC_DIR, 'node_modules', '@esbuild'), (name) => name !== `darwin-${targetArch}`);
|
|
removeDirectories(path.join(PC_DIR, 'node_modules'), (name) => /^sqlite-vec-(?!darwin-)/i.test(name) || (/^sqlite-vec-darwin-/i.test(name) && name !== `sqlite-vec-darwin-${targetArch}`));
|
|
removeDirectories(path.join(PC_DIR, 'node_modules', '@napi-rs'), (name) => /^canvas-/i.test(name) && name !== `canvas-darwin-${targetArch}`);
|
|
removeDirectories(path.join(PC_DIR, 'node_modules', '@anush008'), (name) => /^tokenizers-/i.test(name) && name !== 'tokenizers-darwin-universal');
|
|
removeDirectories(path.join(PC_DIR, 'node_modules', '@img'), (name) => (
|
|
(/^sharp-(darwin|linux|win32)-/i.test(name) && name !== `sharp-darwin-${targetArch}`)
|
|
|| (/^sharp-libvips-/i.test(name) && name !== `sharp-libvips-darwin-${targetArch}`)
|
|
));
|
|
|
|
assertMachArch(
|
|
`macOS ${targetArch} esbuild runtime binary`,
|
|
required.esbuild,
|
|
targetArch,
|
|
);
|
|
assertMachArch(
|
|
`macOS ${targetArch} sqlite-vec runtime binary`,
|
|
required.sqliteVec,
|
|
targetArch,
|
|
);
|
|
assertMachArch(
|
|
`macOS ${targetArch} canvas runtime binary`,
|
|
required.canvas,
|
|
targetArch,
|
|
);
|
|
assertMachArch(
|
|
`macOS ${targetArch} sharp runtime binding`,
|
|
required.sharp,
|
|
targetArch,
|
|
);
|
|
assertMachArch(
|
|
`macOS ${targetArch} sharp libvips runtime`,
|
|
required.sharpVips,
|
|
targetArch,
|
|
);
|
|
writeMarker(PC_DIR, state);
|
|
}
|
|
|
|
module.exports = {
|
|
allFilesExist,
|
|
npmCmd,
|
|
removeDirectories,
|
|
};
|
|
|
|
if (require.main === module) main();
|