@tiangong-ai/cli 0.0.42 → 0.0.44

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.
Files changed (57) hide show
  1. package/AGENTS.md +3 -2
  2. package/README.md +87 -24
  3. package/dist/research/orchestration.js +318 -14
  4. package/dist/research/orchestration.js.map +1 -1
  5. package/dist/research/setup-command.js +13 -1
  6. package/dist/research/setup-command.js.map +1 -1
  7. package/dist/research/workspace/acquisition.d.ts +7 -0
  8. package/dist/research/workspace/acquisition.js +37 -10
  9. package/dist/research/workspace/acquisition.js.map +1 -1
  10. package/dist/research/workspace/audit-bundle.d.ts +18 -0
  11. package/dist/research/workspace/audit-bundle.js +100 -3
  12. package/dist/research/workspace/audit-bundle.js.map +1 -1
  13. package/dist/research/workspace/content-evidence.d.ts +98 -0
  14. package/dist/research/workspace/content-evidence.js +715 -0
  15. package/dist/research/workspace/content-evidence.js.map +1 -0
  16. package/dist/research/workspace/evidence-ledger.d.ts +1 -1
  17. package/dist/research/workspace/evidence-ledger.js +2 -0
  18. package/dist/research/workspace/evidence-ledger.js.map +1 -1
  19. package/dist/research/workspace/executor.d.ts +9 -0
  20. package/dist/research/workspace/executor.js +161 -4
  21. package/dist/research/workspace/executor.js.map +1 -1
  22. package/dist/research/workspace/inference.d.ts +69 -0
  23. package/dist/research/workspace/inference.js +360 -0
  24. package/dist/research/workspace/inference.js.map +1 -0
  25. package/dist/research/workspace/native-activity.js +14 -5
  26. package/dist/research/workspace/native-activity.js.map +1 -1
  27. package/dist/research/workspace/preflight.d.ts +2 -0
  28. package/dist/research/workspace/preflight.js +6 -2
  29. package/dist/research/workspace/preflight.js.map +1 -1
  30. package/dist/research/workspace/projects.js +17 -1
  31. package/dist/research/workspace/projects.js.map +1 -1
  32. package/dist/research/workspace/publication-workflow.d.ts +26 -0
  33. package/dist/research/workspace/publication-workflow.js +314 -3
  34. package/dist/research/workspace/publication-workflow.js.map +1 -1
  35. package/dist/research/workspace/review-executor.d.ts +50 -0
  36. package/dist/research/workspace/review-executor.js +854 -0
  37. package/dist/research/workspace/review-executor.js.map +1 -0
  38. package/dist/research/workspace/runtime.js +194 -45
  39. package/dist/research/workspace/runtime.js.map +1 -1
  40. package/dist/research/workspace/schemas.js +83 -4
  41. package/dist/research/workspace/schemas.js.map +1 -1
  42. package/dist/research/workspace/scientific-review.js +57 -0
  43. package/dist/research/workspace/scientific-review.js.map +1 -1
  44. package/dist/research/workspace/setup-catalog.js +22 -2
  45. package/dist/research/workspace/setup-catalog.js.map +1 -1
  46. package/dist/research/workspace/setup-declarative.d.ts +4 -0
  47. package/dist/research/workspace/setup-declarative.js +16 -1
  48. package/dist/research/workspace/setup-declarative.js.map +1 -1
  49. package/dist/research/workspace/setup-wizard.js +46 -3
  50. package/dist/research/workspace/setup-wizard.js.map +1 -1
  51. package/dist/research/workspace/setup.d.ts +3 -1
  52. package/dist/research/workspace/setup.js +77 -19
  53. package/dist/research/workspace/setup.js.map +1 -1
  54. package/dist/research/workspace/types.d.ts +43 -1
  55. package/dist/research/workspace/workspace.js +62 -5
  56. package/dist/research/workspace/workspace.js.map +1 -1
  57. package/package.json +1 -1
@@ -15,6 +15,7 @@ import { configuredResearchSecrets, isSensitiveEnvironmentName, sanitizeResearch
15
15
  import { inspectResearchSetupCatalog, RESEARCH_SETUP_CREDENTIALS, RESEARCH_SETUP_INSTALLER, RESEARCH_SETUP_SETTINGS, RESEARCH_SETUP_SKILLS, resolveSetupSkills, setupSkill, setupSource, setupTargetRoot, verifyResearchSetupRuntimeContract, } from "./setup-catalog.js";
16
16
  import { acquireFileLock, canonicalJson, ensureDirectory, fileSize, hashRegularTree, isObject, pathExists, REGULAR_TREE_HASH_ALGORITHM, readJsonFile, sha256File, sha256Text, workspacePaths, writeJsonAtomic, writeTextAtomic, } from "./storage.js";
17
17
  import { packageRoot, packageVersion, RESEARCH_PACKAGE_NAME } from "./constants.js";
18
+ import { inspectReviewerBridgeStatus } from "./review-executor.js";
18
19
  import { exactResearchCliCommand, pinResearchCliCommand, researchSetupApplyCommand, researchSetupRetryCommand, } from "./setup-invocation.js";
19
20
  import { doctorResearchWorkspace, initializeResearchWorkspace, loadWorkspaceConfig, } from "./workspace.js";
20
21
  const RECOVERY_SKILL_NAME = "tiangong-auto-research-recovery";
@@ -38,6 +39,7 @@ export async function createResearchSetupPlan(input) {
38
39
  const scope = input.scope ?? "project";
39
40
  const agents = normalizeAgents(input.agents ?? ["codex"]);
40
41
  const agentRoutes = normalizeAgentRoutes(input.agentRoutes);
42
+ const reviewerExecution = normalizeReviewerExecution(input.reviewerExecution);
41
43
  if (input.declarativeConfigurationSha256 !== undefined &&
42
44
  !/^[0-9a-f]{64}$/.test(input.declarativeConfigurationSha256)) {
43
45
  throw setupError({
@@ -103,7 +105,19 @@ export async function createResearchSetupPlan(input) {
103
105
  const selected = resolveSetupSkills([
104
106
  ...new Set([...BRAVE_PROFILE_SKILLS[input.evidenceProfile], ...input.skillIds]),
105
107
  ]);
106
- const producerInstallTarget = agentRoutes.producerAgent === "codex" ? "codex" : "claude-code";
108
+ if ((agentRoutes.producerAgent === "workbuddy" || agentRoutes.producerAgent === "codebuddy") &&
109
+ selected.some((skill) => skill.id === "tiangong.auto-research") &&
110
+ !selected.some((skill) => skill.id === "tiangong.auto-research-workbuddy")) {
111
+ throw setupError({
112
+ code: "RESEARCH_SETUP_SELECTION_INVALID",
113
+ step: "selection",
114
+ reason: "A WorkBuddy/CodeBuddy native producer requires the thin sandboxed-IDE adapter beside the canonical orchestrator.",
115
+ minimumAction: "Select both tiangong.auto-research and tiangong.auto-research-workbuddy, or choose a Codex/Claude producer.",
116
+ retryCommand: "tiangong-ai research setup catalog --json",
117
+ exitCode: 2,
118
+ });
119
+ }
120
+ const producerInstallTarget = agentRoutes.producerAgent === "claude" ? "claude-code" : "codex";
107
121
  if (selected.some((skill) => skill.role === "orchestrator") &&
108
122
  !agents.includes(producerInstallTarget)) {
109
123
  throw setupError({
@@ -178,6 +192,7 @@ export async function createResearchSetupPlan(input) {
178
192
  credentialSources,
179
193
  settings,
180
194
  agentRoutes,
195
+ reviewerExecution,
181
196
  checks: {
182
197
  live: input.liveChecks === true,
183
198
  allowSyntheticUnstructureUpload: input.allowSyntheticUnstructureUpload === true,
@@ -1230,7 +1245,13 @@ export async function doctorResearchSetup(workspace, options = {}) {
1230
1245
  return `${command} is executable (${sanitizeResearchText(result.stdout.trim()).slice(0, 120)}).`;
1231
1246
  });
1232
1247
  }
1233
- if (platform() === "win32") {
1248
+ if (plan.reviewerExecution.transport === "sandbox-bridge") {
1249
+ await setupDoctorCheck(checks, "platform-sandbox", "runtime", async () => {
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") {
1234
1255
  const production = plan.workspace.mode === "production-research";
1235
1256
  checks.push({
1236
1257
  id: "platform-sandbox",
@@ -1281,18 +1302,26 @@ export async function doctorResearchSetup(workspace, options = {}) {
1281
1302
  requiredFor: ["setup", "research-core"],
1282
1303
  });
1283
1304
  const reviewerCommand = plan.agentRoutes.reviewerAgent;
1284
- await setupDoctorCheck(checks, `agent.${reviewerCommand}.reviewer`, "agent", async () => {
1285
- const result = await runner({
1286
- command: reviewerCommand,
1287
- args: ["--version"],
1288
- cwd: root,
1289
- environment: agentDoctorEnvironment(environment),
1290
- timeoutMs: 30_000,
1305
+ if (plan.reviewerExecution.transport === "sandbox-bridge") {
1306
+ await setupDoctorCheck(checks, `agent.${reviewerCommand}.reviewer`, "agent", async () => {
1307
+ const status = await inspectReviewerBridgeStatus(root);
1308
+ return `${reviewerCommand} reviewer is delegated to the exact-version owner-controlled sidecar (${status.keyFingerprint.slice(0, 12)}).`;
1291
1309
  });
1292
- if (result.exitCode !== 0)
1293
- throw new Error(`${reviewerCommand} is not executable`);
1294
- return `${reviewerCommand} reviewer CLI is executable (${sanitizeResearchText(result.stdout.trim()).slice(0, 160)}).`;
1295
- });
1310
+ }
1311
+ else {
1312
+ await setupDoctorCheck(checks, `agent.${reviewerCommand}.reviewer`, "agent", async () => {
1313
+ const result = await runner({
1314
+ command: reviewerCommand,
1315
+ args: ["--version"],
1316
+ cwd: root,
1317
+ environment: agentDoctorEnvironment(environment),
1318
+ timeoutMs: 30_000,
1319
+ });
1320
+ if (result.exitCode !== 0)
1321
+ throw new Error(`${reviewerCommand} is not executable`);
1322
+ return `${reviewerCommand} reviewer CLI is executable (${sanitizeResearchText(result.stdout.trim()).slice(0, 160)}).`;
1323
+ });
1324
+ }
1296
1325
  await setupDoctorCheck(checks, "agent-route-config", "agent", async () => {
1297
1326
  const config = await loadWorkspaceConfig(root);
1298
1327
  if (config.producer.executionMode !== "native-host" ||
@@ -1307,7 +1336,7 @@ export async function doctorResearchSetup(workspace, options = {}) {
1307
1336
  !config.reviewer.pricing)) {
1308
1337
  throw new Error("Production agent models and reviewed pricing are incomplete.");
1309
1338
  }
1310
- return `${config.producer.agent}(native-host) -> ${config.reviewer.agent}(headless-cli).`;
1339
+ return `${config.producer.agent}(native-host) -> ${config.reviewer.agent}(headless-cli) via ${config.reviewerExecution.transport}.`;
1311
1340
  });
1312
1341
  const selected = plan.selection.skillIds.map(setupSkill);
1313
1342
  const installations = await inspectSelectedInstallations(plan, selected, environment);
@@ -1780,6 +1809,10 @@ function parseResearchSetupPlan(value) {
1780
1809
  Object.values(value.settings).some((item) => typeof item !== "string") ||
1781
1810
  !isObject(value.agentRoutes) ||
1782
1811
  !validAgentRoutes(value.agentRoutes) ||
1812
+ !isObject(value.reviewerExecution) ||
1813
+ (value.reviewerExecution.transport !== "native-direct" &&
1814
+ value.reviewerExecution.transport !== "sandbox-bridge") ||
1815
+ value.reviewerExecution.isolationProvider !== "platform-capsule" ||
1783
1816
  !isObject(value.checks) ||
1784
1817
  typeof value.checks.live !== "boolean" ||
1785
1818
  typeof value.checks.allowSyntheticUnstructureUpload !== "boolean" ||
@@ -1864,6 +1897,10 @@ function assertPlanMatchesCatalog(plan) {
1864
1897
  if (canonicalJson(plan.agentRoutes) !== canonicalJson(normalizeAgentRoutes(plan.agentRoutes))) {
1865
1898
  throw planCatalogDrift("agent routes");
1866
1899
  }
1900
+ if (canonicalJson(plan.reviewerExecution) !==
1901
+ canonicalJson(normalizeReviewerExecution(plan.reviewerExecution))) {
1902
+ throw planCatalogDrift("reviewer execution transport");
1903
+ }
1867
1904
  if (canonicalJson(plan.install.agents) !== canonicalJson(normalizeAgents(plan.install.agents))) {
1868
1905
  throw planCatalogDrift("agent selection order or duplicates");
1869
1906
  }
@@ -1893,7 +1930,7 @@ function validAgentRoutes(value) {
1893
1930
  ]);
1894
1931
  if (Object.keys(value).some((key) => !allowed.has(key)))
1895
1932
  return false;
1896
- if ((value.producerAgent !== "codex" && value.producerAgent !== "claude") ||
1933
+ if (!["codex", "claude", "workbuddy", "codebuddy"].includes(String(value.producerAgent)) ||
1897
1934
  (value.reviewerAgent !== "codex" && value.reviewerAgent !== "claude") ||
1898
1935
  value.producerAgent === value.reviewerAgent ||
1899
1936
  !(value.producerModel === null || typeof value.producerModel === "string") ||
@@ -2004,6 +2041,22 @@ function normalizedCredentialSources(selected, supplied) {
2004
2041
  })
2005
2042
  .sort((left, right) => left.id.localeCompare(right.id));
2006
2043
  }
2044
+ function normalizeReviewerExecution(value) {
2045
+ const transport = value?.transport ?? "native-direct";
2046
+ const isolationProvider = value?.isolationProvider ?? "platform-capsule";
2047
+ if ((transport !== "native-direct" && transport !== "sandbox-bridge") ||
2048
+ isolationProvider !== "platform-capsule") {
2049
+ throw setupError({
2050
+ code: "RESEARCH_SETUP_REVIEW_TRANSPORT_INVALID",
2051
+ step: "reviewer-execution",
2052
+ reason: "Reviewer execution must explicitly use native-direct or sandbox-bridge with the platform capsule.",
2053
+ minimumAction: "Choose native-direct on a normal host, or sandbox-bridge with an owner-started sidecar outside the IDE sandbox.",
2054
+ retryCommand: "tiangong-ai research setup plan --help",
2055
+ exitCode: 2,
2056
+ });
2057
+ }
2058
+ return { transport, isolationProvider };
2059
+ }
2007
2060
  function normalizeAgentRoutes(value) {
2008
2061
  const producerAgent = normalizeAgentKind(value?.producerAgent ?? "codex", "producer");
2009
2062
  const reviewerAgent = normalizeAgentKind(value?.reviewerAgent ?? (producerAgent === "codex" ? "claude" : "codex"), "reviewer");
@@ -2029,11 +2082,15 @@ function normalizeAgentRoutes(value) {
2029
2082
  function normalizeAgentKind(value, label) {
2030
2083
  if (value === "codex" || value === "claude")
2031
2084
  return value;
2085
+ if (label === "producer" && (value === "workbuddy" || value === "codebuddy"))
2086
+ return value;
2032
2087
  throw setupError({
2033
2088
  code: "RESEARCH_SETUP_AGENT_ROUTE_INVALID",
2034
2089
  step: "agent-route",
2035
- reason: `${label} agent must be codex or claude.`,
2036
- minimumAction: "Choose Codex or Claude Code and keep the reviewer on the other family.",
2090
+ reason: label === "producer"
2091
+ ? "producer agent must be codex, claude, workbuddy, or codebuddy."
2092
+ : "reviewer agent must be codex or claude.",
2093
+ minimumAction: "Choose the current native producer host and keep the reviewer on an independent Codex or Claude CLI family.",
2037
2094
  retryCommand: "tiangong-ai research setup plan --help",
2038
2095
  exitCode: 2,
2039
2096
  });
@@ -2193,6 +2250,7 @@ async function configureAgentRoutes(plan) {
2193
2250
  ...config,
2194
2251
  producer: setupAgentRoute(config.producer, plan.agentRoutes.producerAgent, "native-host", plan.agentRoutes.producerModel, plan.agentRoutes.producerPricing),
2195
2252
  reviewer: setupAgentRoute(config.reviewer, plan.agentRoutes.reviewerAgent, "headless-cli", plan.agentRoutes.reviewerModel, plan.agentRoutes.reviewerPricing),
2253
+ reviewerExecution: plan.reviewerExecution,
2196
2254
  };
2197
2255
  await writeJsonAtomic(paths.config, updated);
2198
2256
  }
@@ -2201,7 +2259,7 @@ function setupAgentRoute(current, agent, executionMode, plannedModel, plannedPri
2201
2259
  return {
2202
2260
  agent,
2203
2261
  executionMode,
2204
- binary: agent === "codex" ? "codex" : "claude",
2262
+ binary: agent === "codex" ? "codex" : agent === "claude" ? "claude" : `${agent}-native-host`,
2205
2263
  model: plannedModel ?? (sameAgent ? current.model : null),
2206
2264
  effort: sameAgent ? (current.effort ?? "low") : "low",
2207
2265
  ...(agent === "codex" ? { verbosity: sameAgent ? (current.verbosity ?? "low") : "low" } : {}),
@@ -3959,7 +4017,7 @@ async function appendSemanticScholarLiveCheck(checks, input) {
3959
4017
  const headers = new Headers({ Accept: "application/json" });
3960
4018
  if (apiKey)
3961
4019
  headers.set("x-api-key", apiKey);
3962
- const url = "https://api.semanticscholar.org/graph/v1/paper/search?query=reproducible%20research&limit=1&fields=paperId";
4020
+ const url = "https://api.semanticscholar.org/graph/v1/paper/DOI:10.1038/s41586-020-2649-2?fields=paperId";
3963
4021
  try {
3964
4022
  let response;
3965
4023
  let retryAfterSeconds = null;