@tiangong-ai/cli 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -2
- package/README.md +15 -2
- package/dist/research/workspace/broker.js +1 -2
- package/dist/research/workspace/broker.js.map +1 -1
- package/dist/research/workspace/executor.js +24 -9
- package/dist/research/workspace/executor.js.map +1 -1
- package/dist/research/workspace/platform-capabilities.d.ts +25 -0
- package/dist/research/workspace/platform-capabilities.js +87 -0
- package/dist/research/workspace/platform-capabilities.js.map +1 -0
- package/dist/research/workspace/preflight.d.ts +1 -1
- package/dist/research/workspace/review-executor.js +29 -2
- package/dist/research/workspace/review-executor.js.map +1 -1
- package/dist/research/workspace/sanitization.js +2 -2
- package/dist/research/workspace/sanitization.js.map +1 -1
- package/dist/research/workspace/scientific-objects.js +8 -3
- package/dist/research/workspace/scientific-objects.js.map +1 -1
- package/dist/research/workspace/setup.js +51 -48
- package/dist/research/workspace/setup.js.map +1 -1
- package/dist/research/workspace/storage.d.ts +24 -1
- package/dist/research/workspace/storage.js +400 -7
- package/dist/research/workspace/storage.js.map +1 -1
- package/dist/research/workspace/workspace.js +17 -2
- package/dist/research/workspace/workspace.js.map +1 -1
- package/package.json +4 -1
|
@@ -10,6 +10,7 @@ import { inspectResearchContext } from "./context.js";
|
|
|
10
10
|
import { inspectCapabilityCredentialEnvironment, loadCapabilityCredentialMapForIds, reconcileCapabilityCredentialEnvironment, setCapabilityCredentialValue, } from "./credentials.js";
|
|
11
11
|
import { configureExternalSkillProfile, configureTiangongDatabaseCapability, doctorExternalCapabilities, EXTERNAL_SKILL_CONTEXT_PROFILE, EXTERNAL_SKILL_MEDIA_PROFILE, EXTERNAL_SKILL_PROFILE, reconcileSetupManagedCapabilities, } from "./external-skills.js";
|
|
12
12
|
import { appendJournalEvent } from "./journal.js";
|
|
13
|
+
import { researchPlatformCapabilities } from "./platform-capabilities.js";
|
|
13
14
|
import { validateResearchPolicyPack } from "./research-policy.js";
|
|
14
15
|
import { configuredResearchSecrets, isSensitiveEnvironmentName, sanitizeResearchRecord, sanitizeResearchText, } from "./sanitization.js";
|
|
15
16
|
import { inspectResearchSetupCatalog, RESEARCH_SETUP_CREDENTIALS, RESEARCH_SETUP_INSTALLER, RESEARCH_SETUP_SETTINGS, RESEARCH_SETUP_SKILLS, resolveSetupSkills, setupSkill, setupSource, setupTargetRoot, verifyResearchSetupRuntimeContract, } from "./setup-catalog.js";
|
|
@@ -1245,13 +1246,8 @@ export async function doctorResearchSetup(workspace, options = {}) {
|
|
|
1245
1246
|
return `${command} is executable (${sanitizeResearchText(result.stdout.trim()).slice(0, 120)}).`;
|
|
1246
1247
|
});
|
|
1247
1248
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
const status = await inspectReviewerBridgeStatus(root);
|
|
1251
|
-
return `Owner-controlled reviewer sidecar is ready; version=${status.packageVersion}; key=${status.keyFingerprint.slice(0, 12)}.`;
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
else if (platform() === "win32") {
|
|
1249
|
+
const platformCapabilities = researchPlatformCapabilities(platform());
|
|
1250
|
+
if (!platformCapabilities.nativeReviewerExecution) {
|
|
1255
1251
|
const production = plan.workspace.mode === "production-research";
|
|
1256
1252
|
checks.push({
|
|
1257
1253
|
id: "platform-sandbox",
|
|
@@ -1259,24 +1255,30 @@ export async function doctorResearchSetup(workspace, options = {}) {
|
|
|
1259
1255
|
scope: "research-core",
|
|
1260
1256
|
status: production ? "fail" : "warn",
|
|
1261
1257
|
detail: production
|
|
1262
|
-
?
|
|
1263
|
-
:
|
|
1258
|
+
? `Production research execution is unsupported on ${platformCapabilities.platform} because no approved capsule sandbox is available.`
|
|
1259
|
+
: `${platformCapabilities.platform} is configuration/smoke-only; it can inspect setup state but cannot start a native reviewer or reviewer sidecar.`,
|
|
1264
1260
|
minimumAction: production
|
|
1265
1261
|
? "Run production research on macOS with sandbox-exec or Linux with Bubblewrap."
|
|
1266
|
-
: "Use macOS or Linux before switching this workspace to production-research mode.",
|
|
1262
|
+
: "Use macOS or Linux before switching this workspace to production-research mode or starting a reviewer sidecar.",
|
|
1267
1263
|
blocking: production,
|
|
1268
1264
|
requiredFor: production ? ["setup", "research-core"] : [],
|
|
1269
1265
|
});
|
|
1270
1266
|
}
|
|
1267
|
+
else if (plan.reviewerExecution.transport === "sandbox-bridge") {
|
|
1268
|
+
await setupDoctorCheck(checks, "platform-sandbox", "runtime", async () => {
|
|
1269
|
+
const status = await inspectReviewerBridgeStatus(root);
|
|
1270
|
+
return `Owner-controlled reviewer sidecar is ready; version=${status.packageVersion}; key=${status.keyFingerprint.slice(0, 12)}.`;
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1271
1273
|
else {
|
|
1272
1274
|
await setupDoctorCheck(checks, "platform-sandbox", "runtime", async () => {
|
|
1273
|
-
if (
|
|
1275
|
+
if (platformCapabilities.nativeIsolationProvider === "sandbox-exec") {
|
|
1274
1276
|
const info = await lstat("/usr/bin/sandbox-exec").catch(() => undefined);
|
|
1275
1277
|
if (!info?.isFile())
|
|
1276
1278
|
throw new Error("/usr/bin/sandbox-exec is unavailable");
|
|
1277
1279
|
return "macOS sandbox-exec is available.";
|
|
1278
1280
|
}
|
|
1279
|
-
if (
|
|
1281
|
+
if (platformCapabilities.nativeIsolationProvider === "bubblewrap") {
|
|
1280
1282
|
const result = await runner({
|
|
1281
1283
|
command: "bwrap",
|
|
1282
1284
|
args: ["--version"],
|
|
@@ -1288,7 +1290,7 @@ export async function doctorResearchSetup(workspace, options = {}) {
|
|
|
1288
1290
|
throw new Error("Bubblewrap is unavailable");
|
|
1289
1291
|
return "Linux Bubblewrap is available.";
|
|
1290
1292
|
}
|
|
1291
|
-
throw new Error(
|
|
1293
|
+
throw new Error(`Research execution is unsupported on ${platformCapabilities.platform}`);
|
|
1292
1294
|
});
|
|
1293
1295
|
}
|
|
1294
1296
|
checks.push({
|
|
@@ -1700,47 +1702,48 @@ export async function checkResearchSetupUpdates(workspace, environment = process
|
|
|
1700
1702
|
export async function clearStaleSetupLock(workspace) {
|
|
1701
1703
|
const root = requireAbsoluteWorkspace(resolve(workspace));
|
|
1702
1704
|
const lockPath = workspacePaths(root).setupLock;
|
|
1703
|
-
|
|
1704
|
-
if (!info)
|
|
1705
|
-
return;
|
|
1706
|
-
if (!info.isFile() || info.isSymbolicLink()) {
|
|
1707
|
-
throw setupError({
|
|
1708
|
-
code: "RESEARCH_SETUP_LOCK_INVALID",
|
|
1709
|
-
step: "retry",
|
|
1710
|
-
reason: "Setup lock is not a regular file.",
|
|
1711
|
-
minimumAction: "Inspect the lock path manually; it will not be removed automatically.",
|
|
1712
|
-
retryCommand: `tiangong-ai research setup status --workspace ${root} --json`,
|
|
1713
|
-
exitCode: 3,
|
|
1714
|
-
});
|
|
1715
|
-
}
|
|
1716
|
-
let payload;
|
|
1705
|
+
let release;
|
|
1717
1706
|
try {
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1707
|
+
release = await acquireFileLock(lockPath, {
|
|
1708
|
+
operation: "research.setup.lock-recovery",
|
|
1709
|
+
acquiredAt: new Date().toISOString(),
|
|
1710
|
+
});
|
|
1722
1711
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1712
|
+
catch (error) {
|
|
1713
|
+
if (error instanceof CliError && error.code === "RESEARCH_WORKSPACE_LOCKED") {
|
|
1714
|
+
const details = isObject(error.details) ? error.details : {};
|
|
1715
|
+
if (details.ownerState === "alive") {
|
|
1716
|
+
throw new CliError("Setup is already running in another live process.", {
|
|
1717
|
+
code: "RESEARCH_SETUP_LOCK_ACTIVE",
|
|
1718
|
+
exitCode: 3,
|
|
1719
|
+
details: {
|
|
1720
|
+
ownerState: "alive",
|
|
1721
|
+
operation: typeof details.operation === "string" ? details.operation : null,
|
|
1722
|
+
acquiredAt: typeof details.acquiredAt === "string" ? details.acquiredAt : null,
|
|
1723
|
+
minimumAction: "Wait for the active setup operation to finish, then retry; do not delete lock state manually.",
|
|
1724
|
+
},
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1727
|
+
throw new CliError("Setup lock ownership cannot yet be verified safely.", {
|
|
1728
|
+
code: "RESEARCH_SETUP_LOCK_UNVERIFIABLE",
|
|
1732
1729
|
exitCode: 3,
|
|
1730
|
+
details: {
|
|
1731
|
+
ownerState: "unknown",
|
|
1732
|
+
retryAfterSeconds: typeof details.retryAfterSeconds === "number" ? details.retryAfterSeconds : null,
|
|
1733
|
+
minimumAction: "Wait for the reported lease interval and retry; do not delete lock state manually.",
|
|
1734
|
+
},
|
|
1733
1735
|
});
|
|
1734
1736
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1737
|
+
throw new CliError("Setup lock state is unreadable or unsafe.", {
|
|
1738
|
+
code: "RESEARCH_SETUP_LOCK_INVALID",
|
|
1739
|
+
exitCode: 3,
|
|
1740
|
+
details: {
|
|
1741
|
+
ownerState: "unknown",
|
|
1742
|
+
minimumAction: "Inspect workspace filesystem permissions and lock-state integrity; do not delete lock state manually.",
|
|
1743
|
+
},
|
|
1744
|
+
});
|
|
1742
1745
|
}
|
|
1743
|
-
await
|
|
1746
|
+
await release();
|
|
1744
1747
|
}
|
|
1745
1748
|
function parseResearchSetupPlan(value) {
|
|
1746
1749
|
if (!isObject(value) ||
|