@tiangong-ai/cli 0.0.36 → 0.0.37
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 +2 -2
- package/README.md +38 -2
- package/dist/research/orchestration.js +36 -1
- package/dist/research/orchestration.js.map +1 -1
- package/dist/research/workspace/acquisition-routes.d.ts +14 -0
- package/dist/research/workspace/acquisition-routes.js +45 -0
- package/dist/research/workspace/acquisition-routes.js.map +1 -0
- package/dist/research/workspace/broker.js +54 -10
- package/dist/research/workspace/broker.js.map +1 -1
- package/dist/research/workspace/downloads.d.ts +6 -0
- package/dist/research/workspace/downloads.js +32 -8
- package/dist/research/workspace/downloads.js.map +1 -1
- package/dist/research/workspace/evidence-exhaustion.d.ts +45 -0
- package/dist/research/workspace/evidence-exhaustion.js +365 -0
- package/dist/research/workspace/evidence-exhaustion.js.map +1 -0
- package/dist/research/workspace/native-activity.d.ts +6 -0
- package/dist/research/workspace/native-activity.js +24 -7
- package/dist/research/workspace/native-activity.js.map +1 -1
- package/dist/research/workspace/preflight.js +18 -2
- package/dist/research/workspace/preflight.js.map +1 -1
- package/dist/research/workspace/projects.js +52 -0
- package/dist/research/workspace/projects.js.map +1 -1
- package/dist/research/workspace/runtime.d.ts +151 -3
- package/dist/research/workspace/runtime.js +176 -5
- package/dist/research/workspace/runtime.js.map +1 -1
- package/dist/research/workspace/scientific-design.d.ts +23 -0
- package/dist/research/workspace/scientific-design.js +176 -0
- package/dist/research/workspace/scientific-design.js.map +1 -1
- package/dist/research/workspace/setup-catalog.js +2 -2
- package/dist/research/workspace/types.d.ts +27 -0
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ import { stageEvidenceArtifacts } from "./artifacts.js";
|
|
|
9
9
|
import { commitDiscoveryDecisions, materializeDiscoveryEvidence } from "./discovery.js";
|
|
10
10
|
import { inspectDiscoveryProgress } from "./discovery-status.js";
|
|
11
11
|
import { downloadBindingRecordSchema } from "./downloads.js";
|
|
12
|
+
import { parseEvidenceExhaustionHandoff, validateEvidenceExhaustionHandoff, } from "./evidence-exhaustion.js";
|
|
12
13
|
import { loadProjectEvidenceReceipts, stageProjectEvidence } from "./evidence.js";
|
|
13
14
|
import { appendEvidenceLedgerEvent, evidenceLedgerPath, listEvidenceCandidates, registerProjectInputCandidates, } from "./evidence-ledger.js";
|
|
14
15
|
import { executeAgent } from "./executor.js";
|
|
@@ -24,13 +25,34 @@ import { configuredResearchSecrets, sanitizeResearchRecord, sanitizeResearchText
|
|
|
24
25
|
import { parseEvidenceRecord, schemaForDiscoveryAssessmentBatch, parseStructuredStageOutput, schemaForStage, StructuredOutputError, } from "./schemas.js";
|
|
25
26
|
import { canonicalJson, ensureDirectory, fileRecord, isObject, pathExists, readJsonFile, regularTreeFiles, resolveContained, sha256File, sha256Text, workspacePaths, writeJsonAtomic, writeTextAtomic, } from "./storage.js";
|
|
26
27
|
import { loadWorkspaceConfig, verifyDoctorAttestation, withWorkspaceLock } from "./workspace.js";
|
|
28
|
+
function identifierSetSchema(minItems, maxItems) {
|
|
29
|
+
return {
|
|
30
|
+
type: "array",
|
|
31
|
+
minItems,
|
|
32
|
+
maxItems,
|
|
33
|
+
uniqueItems: true,
|
|
34
|
+
items: { type: "string", pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$" },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
27
37
|
export const researchHandoffRecordSchema = {
|
|
28
|
-
$id: "https://schemas.tiangong.ai/research/handoff-request-
|
|
38
|
+
$id: "https://schemas.tiangong.ai/research/handoff-request-v2.json",
|
|
29
39
|
type: "object",
|
|
30
40
|
additionalProperties: false,
|
|
31
|
-
required: [
|
|
41
|
+
required: [
|
|
42
|
+
"schemaVersion",
|
|
43
|
+
"kind",
|
|
44
|
+
"state",
|
|
45
|
+
"reasonCode",
|
|
46
|
+
"summary",
|
|
47
|
+
"requestedActions",
|
|
48
|
+
"evidenceGaps",
|
|
49
|
+
],
|
|
32
50
|
properties: {
|
|
33
|
-
schemaVersion: { type: "integer", const:
|
|
51
|
+
schemaVersion: { type: "integer", const: 2 },
|
|
52
|
+
kind: {
|
|
53
|
+
type: "string",
|
|
54
|
+
enum: ["interactive-challenge", "external-wait", "evidence-exhausted"],
|
|
55
|
+
},
|
|
34
56
|
state: {
|
|
35
57
|
type: "string",
|
|
36
58
|
enum: ["user-action-required", "external-response-required"],
|
|
@@ -51,7 +73,92 @@ export const researchHandoffRecordSchema = {
|
|
|
51
73
|
uniqueItems: true,
|
|
52
74
|
items: { type: "string", minLength: 1, maxLength: 500 },
|
|
53
75
|
},
|
|
76
|
+
exhaustion: {
|
|
77
|
+
type: "object",
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
required: ["missingEvidenceRoleIds", "routeAttempts", "remainingRouteIds"],
|
|
80
|
+
properties: {
|
|
81
|
+
missingEvidenceRoleIds: identifierSetSchema(1, 100),
|
|
82
|
+
routeAttempts: {
|
|
83
|
+
type: "array",
|
|
84
|
+
minItems: 1,
|
|
85
|
+
maxItems: 100,
|
|
86
|
+
items: {
|
|
87
|
+
type: "object",
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
required: ["routeId", "terminalEventHashes", "outcome"],
|
|
90
|
+
properties: {
|
|
91
|
+
routeId: { type: "string", pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$" },
|
|
92
|
+
terminalEventHashes: {
|
|
93
|
+
type: "array",
|
|
94
|
+
minItems: 1,
|
|
95
|
+
maxItems: 100,
|
|
96
|
+
uniqueItems: true,
|
|
97
|
+
items: { type: "string", pattern: "^[a-f0-9]{64}$" },
|
|
98
|
+
},
|
|
99
|
+
outcome: {
|
|
100
|
+
type: "string",
|
|
101
|
+
enum: ["completed-insufficient", "access-blocked", "deterministic-unavailable"],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
remainingRouteIds: identifierSetSchema(0, 100),
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
accessRequests: {
|
|
110
|
+
type: "array",
|
|
111
|
+
minItems: 0,
|
|
112
|
+
maxItems: 100,
|
|
113
|
+
items: {
|
|
114
|
+
type: "object",
|
|
115
|
+
additionalProperties: false,
|
|
116
|
+
required: [
|
|
117
|
+
"id",
|
|
118
|
+
"routeId",
|
|
119
|
+
"resourceType",
|
|
120
|
+
"resourceName",
|
|
121
|
+
"officialLocator",
|
|
122
|
+
"evidenceRoleIds",
|
|
123
|
+
"rationale",
|
|
124
|
+
"alternativesTriedRouteIds",
|
|
125
|
+
"requestedAction",
|
|
126
|
+
"resumeCriteria",
|
|
127
|
+
"costStatus",
|
|
128
|
+
],
|
|
129
|
+
properties: {
|
|
130
|
+
id: { type: "string", pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$" },
|
|
131
|
+
routeId: { type: "string", pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$" },
|
|
132
|
+
resourceType: {
|
|
133
|
+
type: "string",
|
|
134
|
+
enum: [
|
|
135
|
+
"database-subscription",
|
|
136
|
+
"article-purchase",
|
|
137
|
+
"institutional-access",
|
|
138
|
+
"licensed-dataset",
|
|
139
|
+
"owner-provided-material",
|
|
140
|
+
"external-data-request",
|
|
141
|
+
"field-data-collection",
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
resourceName: { type: "string", minLength: 3, maxLength: 500 },
|
|
145
|
+
officialLocator: { type: ["string", "null"], format: "uri" },
|
|
146
|
+
evidenceRoleIds: identifierSetSchema(1, 100),
|
|
147
|
+
rationale: { type: "string", minLength: 8, maxLength: 2_000 },
|
|
148
|
+
alternativesTriedRouteIds: identifierSetSchema(1, 100),
|
|
149
|
+
requestedAction: { type: "string", minLength: 8, maxLength: 1_000 },
|
|
150
|
+
resumeCriteria: { type: "string", minLength: 8, maxLength: 1_000 },
|
|
151
|
+
costStatus: { type: "string", enum: ["unknown", "provider-quote-required"] },
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
54
155
|
},
|
|
156
|
+
allOf: [
|
|
157
|
+
{
|
|
158
|
+
if: { properties: { kind: { const: "evidence-exhausted" } } },
|
|
159
|
+
then: { required: ["exhaustion", "accessRequests"] },
|
|
160
|
+
},
|
|
161
|
+
],
|
|
55
162
|
};
|
|
56
163
|
export async function runResearchWorkspace(root, options, packageExecutor = executeAgent) {
|
|
57
164
|
return runResearchWorkspaceInternal(root, options, packageExecutor, false);
|
|
@@ -299,6 +406,21 @@ export async function prepareNativeResearchStage(input) {
|
|
|
299
406
|
maxWallSeconds: config.budget.packageMaxWallSeconds[input.stage],
|
|
300
407
|
},
|
|
301
408
|
commands: {
|
|
409
|
+
inspectAccess: project.scientificDesign
|
|
410
|
+
? {
|
|
411
|
+
argv: [
|
|
412
|
+
"tiangong-ai",
|
|
413
|
+
"research",
|
|
414
|
+
"project",
|
|
415
|
+
"access",
|
|
416
|
+
"status",
|
|
417
|
+
project.id,
|
|
418
|
+
"--workspace",
|
|
419
|
+
input.root,
|
|
420
|
+
"--json",
|
|
421
|
+
],
|
|
422
|
+
}
|
|
423
|
+
: null,
|
|
302
424
|
requestHandoff: {
|
|
303
425
|
argv: [
|
|
304
426
|
"tiangong-ai",
|
|
@@ -519,6 +641,7 @@ export async function prepareNativeResearchStage(input) {
|
|
|
519
641
|
rules: [
|
|
520
642
|
"Current native host performs producer reasoning; the CLI does not spawn a producer.",
|
|
521
643
|
"Native Web/Browser activity is visible in the evidence ledger but becomes admissible only after broker/input formalization and strict assessment.",
|
|
644
|
+
"An interactive challenge pauses immediately. A material evidence-exhausted handoff is valid only after inspectAccess proves every required plan-bound agent route with exact terminal event hashes.",
|
|
522
645
|
"When the next material step requires user authorization or an external response, request a durable handoff and stop; do not keep searching low-yield substitutes.",
|
|
523
646
|
"Only broker receipts or registered immutable inputs may support discover output.",
|
|
524
647
|
"Only exact, structurally validated, content-addressed artifacts may support full-text acquisition claims.",
|
|
@@ -795,6 +918,17 @@ export async function requestResearchHandoff(input) {
|
|
|
795
918
|
details: { state: project.handoff.state },
|
|
796
919
|
});
|
|
797
920
|
}
|
|
921
|
+
const evidenceHandoff = value.kind === "evidence-exhausted"
|
|
922
|
+
? await validateEvidenceExhaustionHandoff({
|
|
923
|
+
root: input.root,
|
|
924
|
+
project,
|
|
925
|
+
state: value.state,
|
|
926
|
+
value: {
|
|
927
|
+
exhaustion: value.exhaustion,
|
|
928
|
+
accessRequests: value.accessRequests,
|
|
929
|
+
},
|
|
930
|
+
})
|
|
931
|
+
: null;
|
|
798
932
|
const activePath = nativeStageSessionPath(input.root, input.projectId);
|
|
799
933
|
const session = (await pathExists(activePath))
|
|
800
934
|
? await readNativeStageSession(input.root, input.projectId)
|
|
@@ -818,10 +952,13 @@ export async function requestResearchHandoff(input) {
|
|
|
818
952
|
const requestedAt = new Date().toISOString();
|
|
819
953
|
project.handoff = {
|
|
820
954
|
state: value.state,
|
|
955
|
+
kind: value.kind,
|
|
821
956
|
reasonCode: value.reasonCode,
|
|
822
957
|
summary: value.summary,
|
|
823
958
|
requestedActions: value.requestedActions,
|
|
824
959
|
evidenceGaps: value.evidenceGaps,
|
|
960
|
+
exhaustion: evidenceHandoff?.exhaustion ?? null,
|
|
961
|
+
accessRequests: evidenceHandoff?.accessRequests ?? [],
|
|
825
962
|
requestedAt,
|
|
826
963
|
resolvedAt: null,
|
|
827
964
|
resolutionNote: null,
|
|
@@ -830,10 +967,13 @@ export async function requestResearchHandoff(input) {
|
|
|
830
967
|
await saveProject(input.root, project);
|
|
831
968
|
const eventPayload = {
|
|
832
969
|
state: value.state,
|
|
970
|
+
kind: value.kind,
|
|
833
971
|
reasonCode: value.reasonCode,
|
|
834
972
|
summary: value.summary,
|
|
835
973
|
requestedActions: value.requestedActions,
|
|
836
974
|
evidenceGaps: value.evidenceGaps,
|
|
975
|
+
exhaustion: evidenceHandoff?.exhaustion ?? null,
|
|
976
|
+
accessRequests: evidenceHandoff?.accessRequests ?? [],
|
|
837
977
|
requestedAt,
|
|
838
978
|
interruptedSessionId: session?.packet.sessionId ?? null,
|
|
839
979
|
interruptedPackageId: session?.packet.packageId ?? null,
|
|
@@ -894,18 +1034,22 @@ function parseHandoffRequest(value) {
|
|
|
894
1034
|
const sanitized = sanitizeResearchRecord(value, configuredResearchSecrets(process.env));
|
|
895
1035
|
const allowed = new Set([
|
|
896
1036
|
"schemaVersion",
|
|
1037
|
+
"kind",
|
|
897
1038
|
"state",
|
|
898
1039
|
"reasonCode",
|
|
899
1040
|
"summary",
|
|
900
1041
|
"requestedActions",
|
|
901
1042
|
"evidenceGaps",
|
|
1043
|
+
"exhaustion",
|
|
1044
|
+
"accessRequests",
|
|
902
1045
|
]);
|
|
903
1046
|
const requestedActions = Array.isArray(sanitized.requestedActions)
|
|
904
1047
|
? sanitized.requestedActions
|
|
905
1048
|
: [];
|
|
906
1049
|
const evidenceGaps = Array.isArray(sanitized.evidenceGaps) ? sanitized.evidenceGaps : [];
|
|
907
1050
|
if (Object.keys(sanitized).some((key) => !allowed.has(key)) ||
|
|
908
|
-
sanitized.schemaVersion !==
|
|
1051
|
+
sanitized.schemaVersion !== 2 ||
|
|
1052
|
+
!["interactive-challenge", "external-wait", "evidence-exhausted"].includes(String(sanitized.kind)) ||
|
|
909
1053
|
!["user-action-required", "external-response-required"].includes(String(sanitized.state)) ||
|
|
910
1054
|
typeof sanitized.reasonCode !== "string" ||
|
|
911
1055
|
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(sanitized.reasonCode) ||
|
|
@@ -925,12 +1069,39 @@ function parseHandoffRequest(value) {
|
|
|
925
1069
|
exitCode: 2,
|
|
926
1070
|
});
|
|
927
1071
|
}
|
|
1072
|
+
const kind = sanitized.kind;
|
|
1073
|
+
const state = sanitized.state;
|
|
1074
|
+
if ((kind === "interactive-challenge" && state !== "user-action-required") ||
|
|
1075
|
+
(kind === "external-wait" && state !== "external-response-required")) {
|
|
1076
|
+
throw new CliError("Handoff request failed validation.", {
|
|
1077
|
+
code: "RESEARCH_PROJECT_HANDOFF_INVALID",
|
|
1078
|
+
exitCode: 2,
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
let exhaustion = null;
|
|
1082
|
+
let accessRequests = [];
|
|
1083
|
+
if (kind === "evidence-exhausted") {
|
|
1084
|
+
const parsed = parseEvidenceExhaustionHandoff(sanitized.exhaustion, sanitized.accessRequests);
|
|
1085
|
+
exhaustion = parsed.exhaustion;
|
|
1086
|
+
accessRequests = parsed.accessRequests;
|
|
1087
|
+
}
|
|
1088
|
+
else if (sanitized.exhaustion !== undefined ||
|
|
1089
|
+
(sanitized.accessRequests !== undefined &&
|
|
1090
|
+
(!Array.isArray(sanitized.accessRequests) || sanitized.accessRequests.length > 0))) {
|
|
1091
|
+
throw new CliError("Handoff request failed validation.", {
|
|
1092
|
+
code: "RESEARCH_PROJECT_HANDOFF_INVALID",
|
|
1093
|
+
exitCode: 2,
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
928
1096
|
return {
|
|
929
|
-
|
|
1097
|
+
kind,
|
|
1098
|
+
state,
|
|
930
1099
|
reasonCode: sanitized.reasonCode,
|
|
931
1100
|
summary: sanitized.summary.trim(),
|
|
932
1101
|
requestedActions: requestedActions,
|
|
933
1102
|
evidenceGaps: evidenceGaps,
|
|
1103
|
+
exhaustion,
|
|
1104
|
+
accessRequests,
|
|
934
1105
|
};
|
|
935
1106
|
}
|
|
936
1107
|
async function executeWorkPackage(root, projectId, packageId, config, options, requestId, packageExecutor, doctorAttestation) {
|