@chengxianglibra/dsh-data-analysis 0.1.1
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/LICENSE +21 -0
- package/README.md +72 -0
- package/cordis.patch.yml +11 -0
- package/lib/bin/environment.js +91 -0
- package/lib/bridges.js +11 -0
- package/lib/client.js +744 -0
- package/lib/compatibility.js +66 -0
- package/lib/datasource/access.js +60 -0
- package/lib/datasource/bridge-programs.js +80 -0
- package/lib/datasource/bridge.js +204 -0
- package/lib/datasource/credentials.js +24 -0
- package/lib/datasource/index.js +4 -0
- package/lib/datasource/shell-env.js +386 -0
- package/lib/datasource/test.js +65 -0
- package/lib/disclosure/activation.js +369 -0
- package/lib/disclosure/bridge-program.js +11 -0
- package/lib/disclosure/bridge.js +65 -0
- package/lib/disclosure/help.js +227 -0
- package/lib/disclosure/index.js +3 -0
- package/lib/environment/binding.js +273 -0
- package/lib/environment/doctor.js +123 -0
- package/lib/environment/errors.js +11 -0
- package/lib/environment/index.js +7 -0
- package/lib/environment/runtime.js +558 -0
- package/lib/environment/source.js +6 -0
- package/lib/environment/subprocess.js +178 -0
- package/lib/environment/summary.js +19 -0
- package/lib/environment/workspace.js +49 -0
- package/lib/evidence/bridge-program.js +153 -0
- package/lib/evidence/bridge.js +166 -0
- package/lib/evidence/index.js +2 -0
- package/lib/evidence/sources.js +263 -0
- package/lib/index.js +7 -0
- package/lib/plugin.js +179 -0
- package/lib/types/bridges.d.ts +11 -0
- package/lib/types/client.d.ts +125 -0
- package/lib/types/compatibility.d.ts +29 -0
- package/lib/types/datasource/access.d.ts +27 -0
- package/lib/types/datasource/bridge.d.ts +53 -0
- package/lib/types/datasource/index.d.ts +8 -0
- package/lib/types/datasource/shell-env.d.ts +38 -0
- package/lib/types/datasource/test.d.ts +32 -0
- package/lib/types/disclosure/activation.d.ts +73 -0
- package/lib/types/disclosure/bridge.d.ts +28 -0
- package/lib/types/disclosure/help.d.ts +64 -0
- package/lib/types/disclosure/index.d.ts +5 -0
- package/lib/types/environment/binding.d.ts +26 -0
- package/lib/types/environment/doctor.d.ts +8 -0
- package/lib/types/environment/errors.d.ts +7 -0
- package/lib/types/environment/index.d.ts +9 -0
- package/lib/types/environment/runtime.d.ts +17 -0
- package/lib/types/environment/source.d.ts +7 -0
- package/lib/types/environment/subprocess.d.ts +19 -0
- package/lib/types/environment/types.d.ts +96 -0
- package/lib/types/environment/workspace.d.ts +10 -0
- package/lib/types/evidence/bridge.d.ts +40 -0
- package/lib/types/evidence/index.d.ts +4 -0
- package/lib/types/evidence/sources.d.ts +57 -0
- package/lib/types/index.d.ts +9 -0
- package/lib/types/plugin.d.ts +43 -0
- package/package.json +149 -0
- package/python/report-kit/dist/dsh_data_analysis_report_kit-3.0.0-py3-none-any.whl +0 -0
- package/skills/dsh-data-analysis-report/SKILL.md +57 -0
- package/skills/dsh-data-analysis-report/assets/marivo-artifact.js +113 -0
- package/skills/dsh-data-analysis-report/assets/marivo-session-dag.js +1201 -0
- package/skills/dsh-data-analysis-report/assets/report-data.js +449 -0
package/lib/client.js
ADDED
|
@@ -0,0 +1,744 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({ id: "@chengxianglibra/dsh-data-analysis", factory: (require) => {
|
|
2
|
+
var module = { exports: {} }; var exports = module.exports;
|
|
3
|
+
"use strict";
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.inject = exports.CredentialDialogController = exports.marivoEvidenceSourcesDeliveryDefinition = exports.MARIVO_CREDENTIAL_STORAGE_PREFIX = void 0;
|
|
6
|
+
exports.marivoCredentialStorageRef = marivoCredentialStorageRef;
|
|
7
|
+
exports.parseEvidenceSourcesMeta = parseEvidenceSourcesMeta;
|
|
8
|
+
exports.parseEvidenceSourcesDurableContent = parseEvidenceSourcesDurableContent;
|
|
9
|
+
exports.evidenceSourcesDeliveryFromEvent = evidenceSourcesDeliveryFromEvent;
|
|
10
|
+
exports.evidenceSourcesForClosing = evidenceSourcesForClosing;
|
|
11
|
+
exports.selectMarivoEvidenceSources = selectMarivoEvidenceSources;
|
|
12
|
+
exports.groupMarivoEvidenceSources = groupMarivoEvidenceSources;
|
|
13
|
+
exports.parseNeedsCredentials = parseNeedsCredentials;
|
|
14
|
+
exports.shouldAutoOpen = shouldAutoOpen;
|
|
15
|
+
exports.blankCredentialValues = blankCredentialValues;
|
|
16
|
+
exports.MarivoDatasourceTestToolView = MarivoDatasourceTestToolView;
|
|
17
|
+
exports.MarivoDatasourceAccessToolView = MarivoDatasourceAccessToolView;
|
|
18
|
+
exports.MarivoEvidenceSourcesPanel = MarivoEvidenceSourcesPanel;
|
|
19
|
+
exports.apply = apply;
|
|
20
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
21
|
+
const dsh_client_ui_primitives_1 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
22
|
+
const react_1 = require("react");
|
|
23
|
+
const DATASOURCE_TEST_TOOL_NAME = 'marivo_datasource_test';
|
|
24
|
+
const DATASOURCE_ACCESS_TOOL_NAME = 'marivo_datasource_access';
|
|
25
|
+
exports.MARIVO_CREDENTIAL_STORAGE_PREFIX = 'DSH_DATA_ANALYSIS_CREDENTIAL_';
|
|
26
|
+
const EVIDENCE_SOURCES_TOOL_NAME = 'marivo_evidence_sources';
|
|
27
|
+
const EVIDENCE_SOURCES_META_KIND = 'marivo-evidence-sources';
|
|
28
|
+
const EVIDENCE_SOURCES_META_VERSION = 2;
|
|
29
|
+
const HOST_SHELL_ENVIRONMENT_NAMES = new Set([
|
|
30
|
+
'DSH_HOME',
|
|
31
|
+
'DSH_SESSION_ID',
|
|
32
|
+
'DSH_SESSION_JSONL',
|
|
33
|
+
'DSH_SHELL',
|
|
34
|
+
]);
|
|
35
|
+
const EVIDENCE_SOURCES_DURABLE_CONTENT_KIND = 'marivo-evidence-sources-card';
|
|
36
|
+
const EVIDENCE_SOURCES_DEFINITION_KIND = 'marivo-evidence-sources-delivery';
|
|
37
|
+
const EVIDENCE_SOURCES_TURN_DATA_KEY = EVIDENCE_SOURCES_DEFINITION_KIND;
|
|
38
|
+
const EVIDENCE_SOURCES_LOCALE_NAMESPACE = 'marivo-evidence-sources';
|
|
39
|
+
const EVIDENCE_SOURCES_ZH = {
|
|
40
|
+
'source.language': 'zh',
|
|
41
|
+
'source.title': '数据来源',
|
|
42
|
+
'source.summary': '{artifacts} 个分析结果 · {findings} 条 Evidence',
|
|
43
|
+
'source.artifact': '分析结果 {index}',
|
|
44
|
+
'source.findings': '{count} 条 Evidence',
|
|
45
|
+
'source.status': '状态:{value}',
|
|
46
|
+
'source.revalidation': '重新验证:{value}',
|
|
47
|
+
'source.excerptState': '摘录:{value}',
|
|
48
|
+
'source.complete': '完整',
|
|
49
|
+
'source.truncated': '已截断',
|
|
50
|
+
'source.unavailable': '不可用',
|
|
51
|
+
'source.finding': 'Finding {id}',
|
|
52
|
+
'source.artifactRef': 'Artifact {id}',
|
|
53
|
+
'source.session': 'Marivo Session {id}',
|
|
54
|
+
'source.committed': '提交 {committedAt}',
|
|
55
|
+
'source.audit': '审计详情',
|
|
56
|
+
'source.item': 'canonical item: {id}',
|
|
57
|
+
'source.locator': '定位:{value}',
|
|
58
|
+
'source.refs': '来源引用:{value}',
|
|
59
|
+
'source.environment': 'Environment {fingerprint}',
|
|
60
|
+
'source.disclaimer': '来源面板确认 Evidence 身份,不等于验证整句话、计算或业务判断。',
|
|
61
|
+
};
|
|
62
|
+
const EVIDENCE_SOURCES_EN = {
|
|
63
|
+
'source.language': 'en',
|
|
64
|
+
'source.title': 'Data sources',
|
|
65
|
+
'source.summary': '{artifacts} analysis results · {findings} Evidence findings',
|
|
66
|
+
'source.artifact': 'Analysis result {index}',
|
|
67
|
+
'source.findings': '{count} Evidence findings',
|
|
68
|
+
'source.status': 'status: {value}',
|
|
69
|
+
'source.revalidation': 'revalidation: {value}',
|
|
70
|
+
'source.excerptState': 'excerpt: {value}',
|
|
71
|
+
'source.complete': 'complete',
|
|
72
|
+
'source.truncated': 'truncated',
|
|
73
|
+
'source.unavailable': 'unavailable',
|
|
74
|
+
'source.finding': 'Finding {id}',
|
|
75
|
+
'source.artifactRef': 'Artifact {id}',
|
|
76
|
+
'source.session': 'Marivo Session {id}',
|
|
77
|
+
'source.committed': 'committed {committedAt}',
|
|
78
|
+
'source.audit': 'Audit details',
|
|
79
|
+
'source.item': 'canonical item: {id}',
|
|
80
|
+
'source.locator': 'locator: {value}',
|
|
81
|
+
'source.refs': 'source refs: {value}',
|
|
82
|
+
'source.environment': 'Environment {fingerprint}',
|
|
83
|
+
'source.disclaimer': 'This panel confirms Evidence identity; it does not validate the whole statement, calculation, or business judgment.',
|
|
84
|
+
};
|
|
85
|
+
const openedCalls = new Set();
|
|
86
|
+
function invalidCredentialReference(ref) {
|
|
87
|
+
const valid = /^[A-Za-z_][A-Za-z0-9_]*$/.test(ref);
|
|
88
|
+
return new Error(valid
|
|
89
|
+
? `Marivo datasource credential reference uses a reserved runtime namespace or Host name: ${ref}`
|
|
90
|
+
: `Marivo datasource credential reference must be a POSIX environment name: ${ref}`);
|
|
91
|
+
}
|
|
92
|
+
/** Browser-side copy of the Host mapping; contract tests keep both implementations identical. */
|
|
93
|
+
function marivoCredentialStorageRef(ref) {
|
|
94
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(ref))
|
|
95
|
+
throw invalidCredentialReference(ref);
|
|
96
|
+
const upper = ref.toUpperCase();
|
|
97
|
+
if (upper.startsWith('MARIVO_') ||
|
|
98
|
+
upper.startsWith('DSH_DATA_ANALYSIS_') ||
|
|
99
|
+
HOST_SHELL_ENVIRONMENT_NAMES.has(upper)) {
|
|
100
|
+
throw invalidCredentialReference(ref);
|
|
101
|
+
}
|
|
102
|
+
const encoded = [...ref]
|
|
103
|
+
.map((character) => character.charCodeAt(0).toString(16).padStart(2, '0').toUpperCase())
|
|
104
|
+
.join('');
|
|
105
|
+
return `${exports.MARIVO_CREDENTIAL_STORAGE_PREFIX}${encoded}`;
|
|
106
|
+
}
|
|
107
|
+
function utf8ByteLength(value) {
|
|
108
|
+
let bytes = 0;
|
|
109
|
+
for (let index = 0; index < value.length; index++) {
|
|
110
|
+
const code = value.charCodeAt(index);
|
|
111
|
+
if (code < 0x80)
|
|
112
|
+
bytes += 1;
|
|
113
|
+
else if (code < 0x800)
|
|
114
|
+
bytes += 2;
|
|
115
|
+
else if (code >= 0xd800 && code <= 0xdbff && index + 1 < value.length) {
|
|
116
|
+
const next = value.charCodeAt(index + 1);
|
|
117
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
118
|
+
bytes += 4;
|
|
119
|
+
index++;
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
bytes += 3;
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
bytes += 3;
|
|
126
|
+
}
|
|
127
|
+
return bytes;
|
|
128
|
+
}
|
|
129
|
+
function evidenceSourceIdentity(source) {
|
|
130
|
+
return JSON.stringify([source.environmentFingerprint, source.sessionId, source.findingId]);
|
|
131
|
+
}
|
|
132
|
+
function evidenceSource(value) {
|
|
133
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
134
|
+
return null;
|
|
135
|
+
const source = value;
|
|
136
|
+
const allowed = new Set([
|
|
137
|
+
'status',
|
|
138
|
+
'title',
|
|
139
|
+
'locator',
|
|
140
|
+
'excerpt',
|
|
141
|
+
'truncated',
|
|
142
|
+
'environmentFingerprint',
|
|
143
|
+
'sessionId',
|
|
144
|
+
'findingId',
|
|
145
|
+
'findingType',
|
|
146
|
+
'epistemicKind',
|
|
147
|
+
'artifactRef',
|
|
148
|
+
'canonicalItemKey',
|
|
149
|
+
'committedAt',
|
|
150
|
+
'sourceRefs',
|
|
151
|
+
'revalidation',
|
|
152
|
+
]);
|
|
153
|
+
if (Object.keys(source).length !== allowed.size ||
|
|
154
|
+
Object.keys(source).some((key) => !allowed.has(key)) ||
|
|
155
|
+
!['available', 'missing', 'unsupported'].includes(String(source.status)) ||
|
|
156
|
+
typeof source.title !== 'string' ||
|
|
157
|
+
source.title.trim() === '' ||
|
|
158
|
+
utf8ByteLength(source.title) > 2_048 ||
|
|
159
|
+
typeof source.locator !== 'string' ||
|
|
160
|
+
source.locator.trim() === '' ||
|
|
161
|
+
utf8ByteLength(source.locator) > 2_048 ||
|
|
162
|
+
(source.excerpt !== null &&
|
|
163
|
+
(typeof source.excerpt !== 'string' ||
|
|
164
|
+
source.excerpt.trim() === '' ||
|
|
165
|
+
utf8ByteLength(source.excerpt) > 4_096)) ||
|
|
166
|
+
typeof source.truncated !== 'boolean' ||
|
|
167
|
+
typeof source.environmentFingerprint !== 'string' ||
|
|
168
|
+
source.environmentFingerprint === '' ||
|
|
169
|
+
typeof source.sessionId !== 'string' ||
|
|
170
|
+
source.sessionId === '' ||
|
|
171
|
+
typeof source.findingId !== 'string' ||
|
|
172
|
+
source.findingId === '' ||
|
|
173
|
+
(source.findingType !== null &&
|
|
174
|
+
(typeof source.findingType !== 'string' || source.findingType === '')) ||
|
|
175
|
+
(source.epistemicKind !== null &&
|
|
176
|
+
(typeof source.epistemicKind !== 'string' || source.epistemicKind === '')) ||
|
|
177
|
+
typeof source.artifactRef !== 'string' ||
|
|
178
|
+
source.artifactRef === '' ||
|
|
179
|
+
(source.canonicalItemKey !== null &&
|
|
180
|
+
(typeof source.canonicalItemKey !== 'string' || source.canonicalItemKey === '')) ||
|
|
181
|
+
(source.committedAt !== null &&
|
|
182
|
+
(typeof source.committedAt !== 'string' || source.committedAt === '')) ||
|
|
183
|
+
!Array.isArray(source.sourceRefs) ||
|
|
184
|
+
source.sourceRefs.length > 100 ||
|
|
185
|
+
source.sourceRefs.some((ref) => typeof ref !== 'string' || ref === '' || utf8ByteLength(ref) > 2_048))
|
|
186
|
+
return null;
|
|
187
|
+
if (source.revalidation !== null) {
|
|
188
|
+
if (typeof source.revalidation !== 'object' ||
|
|
189
|
+
Array.isArray(source.revalidation) ||
|
|
190
|
+
source.revalidation === null)
|
|
191
|
+
return null;
|
|
192
|
+
const revalidation = source.revalidation;
|
|
193
|
+
const keys = ['status', 'semanticStatus', 'evidenceStatus', 'dependencyStatus'];
|
|
194
|
+
if (Object.keys(revalidation).length !== keys.length ||
|
|
195
|
+
Object.keys(revalidation).some((key) => !keys.includes(key)) ||
|
|
196
|
+
typeof revalidation.status !== 'string' ||
|
|
197
|
+
revalidation.status === '' ||
|
|
198
|
+
keys.slice(1).some((key) => {
|
|
199
|
+
const item = revalidation[key];
|
|
200
|
+
return item !== null && (typeof item !== 'string' || item === '');
|
|
201
|
+
}))
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
if ((source.status === 'available' &&
|
|
205
|
+
(source.excerpt === null ||
|
|
206
|
+
source.findingType === null ||
|
|
207
|
+
source.epistemicKind === null ||
|
|
208
|
+
source.canonicalItemKey === null ||
|
|
209
|
+
source.committedAt === null)) ||
|
|
210
|
+
(source.status === 'missing' &&
|
|
211
|
+
(source.excerpt !== null ||
|
|
212
|
+
source.truncated ||
|
|
213
|
+
source.findingType !== null ||
|
|
214
|
+
source.epistemicKind !== null ||
|
|
215
|
+
source.canonicalItemKey !== null ||
|
|
216
|
+
source.committedAt !== null)) ||
|
|
217
|
+
(source.status === 'unsupported' && source.excerpt !== null) ||
|
|
218
|
+
(source.truncated && source.excerpt === null))
|
|
219
|
+
return null;
|
|
220
|
+
return {
|
|
221
|
+
...source,
|
|
222
|
+
sourceRefs: [...source.sourceRefs],
|
|
223
|
+
revalidation: source.revalidation === null ? null : { ...source.revalidation },
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/** Parse the closed per-call source attachment persisted in Tool result metadata. */
|
|
227
|
+
function parseEvidenceSourcesMeta(value) {
|
|
228
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
229
|
+
return null;
|
|
230
|
+
const meta = value;
|
|
231
|
+
const allowed = new Set(['kind', 'version', 'dshSessionId', 'sources']);
|
|
232
|
+
if (Object.keys(meta).length !== allowed.size ||
|
|
233
|
+
Object.keys(meta).some((key) => !allowed.has(key)) ||
|
|
234
|
+
meta.kind !== EVIDENCE_SOURCES_META_KIND ||
|
|
235
|
+
meta.version !== EVIDENCE_SOURCES_META_VERSION ||
|
|
236
|
+
typeof meta.dshSessionId !== 'string' ||
|
|
237
|
+
meta.dshSessionId === '' ||
|
|
238
|
+
!Array.isArray(meta.sources) ||
|
|
239
|
+
meta.sources.length < 1 ||
|
|
240
|
+
meta.sources.length > 20)
|
|
241
|
+
return null;
|
|
242
|
+
const result = [];
|
|
243
|
+
const identities = new Set();
|
|
244
|
+
for (const value of meta.sources) {
|
|
245
|
+
const source = evidenceSource(value);
|
|
246
|
+
if (source === null)
|
|
247
|
+
return null;
|
|
248
|
+
const identity = evidenceSourceIdentity(source);
|
|
249
|
+
if (identities.has(identity))
|
|
250
|
+
return null;
|
|
251
|
+
identities.add(identity);
|
|
252
|
+
result.push(source);
|
|
253
|
+
}
|
|
254
|
+
return Object.freeze({
|
|
255
|
+
kind: EVIDENCE_SOURCES_META_KIND,
|
|
256
|
+
version: EVIDENCE_SOURCES_META_VERSION,
|
|
257
|
+
dshSessionId: meta.dshSessionId,
|
|
258
|
+
sources: Object.freeze(result),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/** Decode the Code Mode-only source attachment from a durable sub-dispatch result. */
|
|
262
|
+
function parseEvidenceSourcesDurableContent(value) {
|
|
263
|
+
if (!Array.isArray(value))
|
|
264
|
+
return null;
|
|
265
|
+
const cards = value.filter((item) => typeof item === 'object' &&
|
|
266
|
+
item !== null &&
|
|
267
|
+
!Array.isArray(item) &&
|
|
268
|
+
item.type === EVIDENCE_SOURCES_DURABLE_CONTENT_KIND);
|
|
269
|
+
if (cards.length !== 1)
|
|
270
|
+
return null;
|
|
271
|
+
const card = cards[0];
|
|
272
|
+
if (Object.keys(card).length !== 3 ||
|
|
273
|
+
!Number.isSafeInteger(card.turn) ||
|
|
274
|
+
card.turn < 0) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
const meta = parseEvidenceSourcesMeta(card.meta);
|
|
278
|
+
return meta === null ? null : { turn: card.turn, meta };
|
|
279
|
+
}
|
|
280
|
+
function codeEvidenceSourcesDelivery(event) {
|
|
281
|
+
if (event?.type !== 'tool/code-dispatch' ||
|
|
282
|
+
event.data?.name !== EVIDENCE_SOURCES_TOOL_NAME ||
|
|
283
|
+
event.data?.isError === true) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const card = parseEvidenceSourcesDurableContent(event.data.content);
|
|
287
|
+
return card === null ? null : { turn: card.turn, seq: event.seq, sources: card.meta.sources };
|
|
288
|
+
}
|
|
289
|
+
/** Recover one successful native or nested source attachment. */
|
|
290
|
+
function evidenceSourcesDeliveryFromEvent(event, calls = new Map()) {
|
|
291
|
+
if (event?.type === 'tool/result') {
|
|
292
|
+
if (event.surfaceOp !== 'append' || !Array.isArray(event.data?.message?.content))
|
|
293
|
+
return null;
|
|
294
|
+
const blocks = event.data.message.content.filter((item) => item?.type === 'tool-result');
|
|
295
|
+
if (blocks.length !== 1 || blocks[0].isError === true)
|
|
296
|
+
return null;
|
|
297
|
+
const callId = String(event.data.message.source?.callId ?? '');
|
|
298
|
+
if (calls.get(callId) !== EVIDENCE_SOURCES_TOOL_NAME)
|
|
299
|
+
return null;
|
|
300
|
+
const meta = parseEvidenceSourcesMeta(event.data.meta);
|
|
301
|
+
return meta === null ? null : { seq: event.seq, sources: meta.sources };
|
|
302
|
+
}
|
|
303
|
+
const delivery = codeEvidenceSourcesDelivery(event);
|
|
304
|
+
return delivery === null ? null : { seq: delivery.seq, sources: delivery.sources };
|
|
305
|
+
}
|
|
306
|
+
/** Aggregate explicit source attachments under one Harness-owned Turn key. */
|
|
307
|
+
exports.marivoEvidenceSourcesDeliveryDefinition = {
|
|
308
|
+
kind: EVIDENCE_SOURCES_DEFINITION_KIND,
|
|
309
|
+
match(event) {
|
|
310
|
+
if (event?.type === 'turn/start')
|
|
311
|
+
return { id: String(event.data.turn), role: 'start' };
|
|
312
|
+
if (event?.type === 'tool/call')
|
|
313
|
+
return { id: String(event.data.turn), role: 'update' };
|
|
314
|
+
if (event?.type === 'tool/result' && event.surfaceOp === 'append') {
|
|
315
|
+
return { id: String(event.data.turn), role: 'update' };
|
|
316
|
+
}
|
|
317
|
+
const delivery = codeEvidenceSourcesDelivery(event);
|
|
318
|
+
return delivery === null ? null : { id: String(delivery.turn), role: 'update' };
|
|
319
|
+
},
|
|
320
|
+
start(_context, match) {
|
|
321
|
+
if (match.event.type !== 'turn/start') {
|
|
322
|
+
throw new Error('Marivo Evidence source delivery start requires turn/start');
|
|
323
|
+
}
|
|
324
|
+
return { turn: match.event.data.turn, calls: new Map(), deliveries: [] };
|
|
325
|
+
},
|
|
326
|
+
update(context, match) {
|
|
327
|
+
if (match.event.type === 'tool/call') {
|
|
328
|
+
const calls = new Map(context.state.calls);
|
|
329
|
+
calls.set(String(match.event.data.callId), String(match.event.data.name));
|
|
330
|
+
return { ...context.state, calls };
|
|
331
|
+
}
|
|
332
|
+
const delivery = evidenceSourcesDeliveryFromEvent(match.event, context.state.calls);
|
|
333
|
+
return delivery === null
|
|
334
|
+
? context.state
|
|
335
|
+
: { ...context.state, deliveries: [...context.state.deliveries, delivery] };
|
|
336
|
+
},
|
|
337
|
+
buildLocationData(context, scope) {
|
|
338
|
+
if (scope !== 'turn' || context.state === undefined)
|
|
339
|
+
return null;
|
|
340
|
+
return {
|
|
341
|
+
kind: 'turn',
|
|
342
|
+
turn: context.state.turn,
|
|
343
|
+
key: EVIDENCE_SOURCES_TURN_DATA_KEY,
|
|
344
|
+
value: { deliveries: context.state.deliveries },
|
|
345
|
+
};
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
/** Successful sources completed before this exact closing Assistant message. */
|
|
349
|
+
function evidenceSourcesForClosing(owner) {
|
|
350
|
+
const data = owner?.turn?.data?.get?.(EVIDENCE_SOURCES_TURN_DATA_KEY);
|
|
351
|
+
if (typeof data !== 'object' || data === null || !Array.isArray(data.deliveries))
|
|
352
|
+
return [];
|
|
353
|
+
const deliveries = [];
|
|
354
|
+
for (const value of data.deliveries) {
|
|
355
|
+
if (typeof value !== 'object' ||
|
|
356
|
+
value === null ||
|
|
357
|
+
typeof value.seq !== 'number' ||
|
|
358
|
+
value.seq > owner.seq ||
|
|
359
|
+
!Array.isArray(value.sources)) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const parsed = value.sources.map(evidenceSource);
|
|
363
|
+
if (parsed.every((source) => source !== null)) {
|
|
364
|
+
deliveries.push({ seq: value.seq, sources: parsed });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
deliveries.sort((left, right) => left.seq - right.seq);
|
|
368
|
+
const seen = new Set();
|
|
369
|
+
return deliveries.flatMap(({ sources }) => sources.flatMap((source) => {
|
|
370
|
+
const identity = evidenceSourceIdentity(source);
|
|
371
|
+
if (seen.has(identity))
|
|
372
|
+
return [];
|
|
373
|
+
seen.add(identity);
|
|
374
|
+
return [source];
|
|
375
|
+
}));
|
|
376
|
+
}
|
|
377
|
+
function selectMarivoEvidenceSources(owner) {
|
|
378
|
+
const sources = evidenceSourcesForClosing(owner);
|
|
379
|
+
return sources.length === 0 ? null : sources;
|
|
380
|
+
}
|
|
381
|
+
/** Group source presentation only; this does not infer Evidence equivalence or compatibility. */
|
|
382
|
+
function groupMarivoEvidenceSources(sources) {
|
|
383
|
+
const groups = new Map();
|
|
384
|
+
for (const source of sources) {
|
|
385
|
+
const key = JSON.stringify([
|
|
386
|
+
source.environmentFingerprint,
|
|
387
|
+
source.sessionId,
|
|
388
|
+
source.artifactRef,
|
|
389
|
+
]);
|
|
390
|
+
const current = groups.get(key) ?? [];
|
|
391
|
+
current.push(source);
|
|
392
|
+
groups.set(key, current);
|
|
393
|
+
}
|
|
394
|
+
return [...groups.entries()].map(([key, grouped]) => ({
|
|
395
|
+
key,
|
|
396
|
+
environmentFingerprint: grouped[0].environmentFingerprint,
|
|
397
|
+
sessionId: grouped[0].sessionId,
|
|
398
|
+
artifactRef: grouped[0].artifactRef,
|
|
399
|
+
sources: grouped,
|
|
400
|
+
}));
|
|
401
|
+
}
|
|
402
|
+
function parseNeedsCredentials(text) {
|
|
403
|
+
try {
|
|
404
|
+
const value = JSON.parse(text);
|
|
405
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
406
|
+
return null;
|
|
407
|
+
const candidate = value;
|
|
408
|
+
if (candidate.status !== 'needs-credentials' ||
|
|
409
|
+
typeof candidate.name !== 'string' ||
|
|
410
|
+
!Array.isArray(candidate.refs) ||
|
|
411
|
+
!candidate.refs.every((ref) => typeof ref === 'string' && ref !== ''))
|
|
412
|
+
return null;
|
|
413
|
+
return {
|
|
414
|
+
status: 'needs-credentials',
|
|
415
|
+
name: candidate.name,
|
|
416
|
+
refs: [...new Set(candidate.refs)],
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
catch {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
function shouldAutoOpen(sessionId, callId, result) {
|
|
424
|
+
const key = `${sessionId}\u0000${callId}`;
|
|
425
|
+
if (result === null || openedCalls.has(key))
|
|
426
|
+
return false;
|
|
427
|
+
openedCalls.add(key);
|
|
428
|
+
return true;
|
|
429
|
+
}
|
|
430
|
+
function blankCredentialValues(refs) {
|
|
431
|
+
return Object.fromEntries(refs.map((ref) => [ref, '']));
|
|
432
|
+
}
|
|
433
|
+
function messageOf(value) {
|
|
434
|
+
if (value instanceof Error)
|
|
435
|
+
return value.message;
|
|
436
|
+
return typeof value === 'string' ? value : '凭证保存失败';
|
|
437
|
+
}
|
|
438
|
+
function redact(text, values) {
|
|
439
|
+
let result = text;
|
|
440
|
+
for (const value of values) {
|
|
441
|
+
if (value !== '')
|
|
442
|
+
result = result.split(value).join('[REDACTED]');
|
|
443
|
+
}
|
|
444
|
+
return result;
|
|
445
|
+
}
|
|
446
|
+
class CredentialDialogController {
|
|
447
|
+
api;
|
|
448
|
+
constructor(api) {
|
|
449
|
+
this.api = api;
|
|
450
|
+
}
|
|
451
|
+
async describe(refs) {
|
|
452
|
+
const bindings = refs.map((ref) => [ref, marivoCredentialStorageRef(ref)]);
|
|
453
|
+
const response = await this.api.credentials.describe({
|
|
454
|
+
refs: bindings.map(([, storageRef]) => storageRef),
|
|
455
|
+
});
|
|
456
|
+
if (!response.result.ok)
|
|
457
|
+
throw new Error(response.result.error.message);
|
|
458
|
+
return Object.fromEntries(bindings.map(([ref, storageRef]) => [ref, response.result.value.credentials[storageRef]]));
|
|
459
|
+
}
|
|
460
|
+
async inspect(refs) {
|
|
461
|
+
const info = await this.describe(refs);
|
|
462
|
+
const configured = Object.fromEntries(refs.map((ref) => [ref, info[ref]?.configured === true]));
|
|
463
|
+
return {
|
|
464
|
+
configured,
|
|
465
|
+
missing: refs.filter((ref) => configured[ref] !== true),
|
|
466
|
+
shouldOpen: refs.some((ref) => configured[ref] !== true),
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
async save(values) {
|
|
470
|
+
const entries = Object.entries(values);
|
|
471
|
+
const secretValues = entries.map(([, value]) => value);
|
|
472
|
+
const saved = [];
|
|
473
|
+
const errors = {};
|
|
474
|
+
for (const [ref, value] of entries) {
|
|
475
|
+
if (value === '') {
|
|
476
|
+
errors[ref] = '请输入凭证';
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
const response = await this.api.credentials.set({
|
|
481
|
+
ref: marivoCredentialStorageRef(ref),
|
|
482
|
+
value,
|
|
483
|
+
});
|
|
484
|
+
if (response.result.ok)
|
|
485
|
+
saved.push(ref);
|
|
486
|
+
else
|
|
487
|
+
errors[ref] = redact(response.result.error.message, secretValues);
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
errors[ref] = redact(messageOf(error), secretValues);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return { ok: saved.length === entries.length, saved, errors };
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
exports.CredentialDialogController = CredentialDialogController;
|
|
497
|
+
function settledText(block) {
|
|
498
|
+
if (block === null || typeof block !== 'object' || !('kind' in block))
|
|
499
|
+
return '';
|
|
500
|
+
return block.content
|
|
501
|
+
.filter((item) => item?.type === 'text')
|
|
502
|
+
.map((item) => item.text)
|
|
503
|
+
.join('');
|
|
504
|
+
}
|
|
505
|
+
const rowStyle = {
|
|
506
|
+
display: 'flex',
|
|
507
|
+
alignItems: 'center',
|
|
508
|
+
gap: 8,
|
|
509
|
+
minHeight: 32,
|
|
510
|
+
padding: '4px 8px',
|
|
511
|
+
borderRadius: 8,
|
|
512
|
+
color: 'var(--dsw-alias-text-primary, inherit)',
|
|
513
|
+
};
|
|
514
|
+
const summaryStyle = { flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' };
|
|
515
|
+
const fieldStyle = { display: 'grid', gap: 6, marginBottom: 14 };
|
|
516
|
+
const labelStyle = { display: 'flex', justifyContent: 'space-between', gap: 12, fontSize: 13 };
|
|
517
|
+
const inputStyle = {
|
|
518
|
+
width: '100%',
|
|
519
|
+
boxSizing: 'border-box',
|
|
520
|
+
padding: '8px 10px',
|
|
521
|
+
borderRadius: 6,
|
|
522
|
+
border: '1px solid var(--dsw-alias-border-subtle, #d0d0d0)',
|
|
523
|
+
color: 'inherit',
|
|
524
|
+
background: 'var(--dsw-alias-surface-primary, transparent)',
|
|
525
|
+
};
|
|
526
|
+
const errorStyle = { color: 'var(--dsw-alias-text-error, #c22)', fontSize: 12, margin: 0 };
|
|
527
|
+
function MarivoDatasourceCredentialToolView({ sessionId, callId, block, connection, toolName, }) {
|
|
528
|
+
const text = settledText(block);
|
|
529
|
+
const missing = (0, react_1.useMemo)(() => parseNeedsCredentials(text), [text]);
|
|
530
|
+
const [open, setOpen] = (0, react_1.useState)(false);
|
|
531
|
+
const [busy, setBusy] = (0, react_1.useState)(false);
|
|
532
|
+
const [credentialsReady, setCredentialsReady] = (0, react_1.useState)(false);
|
|
533
|
+
const [values, setValues] = (0, react_1.useState)({});
|
|
534
|
+
const [configured, setConfigured] = (0, react_1.useState)({});
|
|
535
|
+
const [errors, setErrors] = (0, react_1.useState)({});
|
|
536
|
+
const controller = (0, react_1.useMemo)(() => new CredentialDialogController(connection.api), [connection.api]);
|
|
537
|
+
const inspectionGeneration = (0, react_1.useRef)(0);
|
|
538
|
+
const inspectionContext = (0, react_1.useRef)({ sessionId, callId, missing, controller });
|
|
539
|
+
const autoInspectionKey = (0, react_1.useRef)(null);
|
|
540
|
+
inspectionContext.current = { sessionId, callId, missing, controller };
|
|
541
|
+
const openDialog = (0, react_1.useCallback)(async () => {
|
|
542
|
+
if (missing === null)
|
|
543
|
+
return;
|
|
544
|
+
const generation = ++inspectionGeneration.current;
|
|
545
|
+
const isCurrent = () => {
|
|
546
|
+
const current = inspectionContext.current;
|
|
547
|
+
return (generation === inspectionGeneration.current &&
|
|
548
|
+
current.sessionId === sessionId &&
|
|
549
|
+
current.callId === callId &&
|
|
550
|
+
current.missing === missing &&
|
|
551
|
+
current.controller === controller);
|
|
552
|
+
};
|
|
553
|
+
setBusy(true);
|
|
554
|
+
setValues(blankCredentialValues(missing.refs));
|
|
555
|
+
setErrors({});
|
|
556
|
+
try {
|
|
557
|
+
const status = await controller.inspect(missing.refs);
|
|
558
|
+
if (!isCurrent())
|
|
559
|
+
return;
|
|
560
|
+
setConfigured(status.configured);
|
|
561
|
+
if (!status.shouldOpen) {
|
|
562
|
+
setOpen(false);
|
|
563
|
+
setCredentialsReady(true);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
setCredentialsReady(false);
|
|
567
|
+
setOpen(true);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
catch {
|
|
571
|
+
if (!isCurrent())
|
|
572
|
+
return;
|
|
573
|
+
setConfigured(Object.fromEntries(missing.refs.map((ref) => [ref, false])));
|
|
574
|
+
setCredentialsReady(false);
|
|
575
|
+
setOpen(true);
|
|
576
|
+
}
|
|
577
|
+
finally {
|
|
578
|
+
if (isCurrent())
|
|
579
|
+
setBusy(false);
|
|
580
|
+
}
|
|
581
|
+
}, [sessionId, callId, missing, controller]);
|
|
582
|
+
(0, react_1.useEffect)(() => {
|
|
583
|
+
if (missing === null)
|
|
584
|
+
return;
|
|
585
|
+
const key = `${sessionId}\u0000${callId}`;
|
|
586
|
+
if (!shouldAutoOpen(sessionId, callId, missing) && autoInspectionKey.current !== key)
|
|
587
|
+
return;
|
|
588
|
+
autoInspectionKey.current = key;
|
|
589
|
+
void openDialog();
|
|
590
|
+
}, [sessionId, callId, missing, openDialog]);
|
|
591
|
+
const save = async () => {
|
|
592
|
+
if (missing === null)
|
|
593
|
+
return;
|
|
594
|
+
setBusy(true);
|
|
595
|
+
setErrors({});
|
|
596
|
+
const pendingValues = Object.fromEntries(missing.refs.filter((ref) => configured[ref] !== true).map((ref) => [ref, values[ref] ?? '']));
|
|
597
|
+
const outcome = await controller.save(pendingValues);
|
|
598
|
+
setValues(blankCredentialValues(missing.refs));
|
|
599
|
+
setConfigured((current) => ({
|
|
600
|
+
...current,
|
|
601
|
+
...Object.fromEntries(outcome.saved.map((ref) => [ref, true])),
|
|
602
|
+
}));
|
|
603
|
+
setErrors(outcome.errors);
|
|
604
|
+
setBusy(false);
|
|
605
|
+
if (outcome.ok) {
|
|
606
|
+
setOpen(false);
|
|
607
|
+
setCredentialsReady(true);
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
const summary = missing === null
|
|
611
|
+
? text ||
|
|
612
|
+
('kind' in block
|
|
613
|
+
? toolName === DATASOURCE_TEST_TOOL_NAME
|
|
614
|
+
? '连接测试已完成'
|
|
615
|
+
: '执行授权已完成'
|
|
616
|
+
: toolName === DATASOURCE_TEST_TOOL_NAME
|
|
617
|
+
? '正在测试连接…'
|
|
618
|
+
: '正在申请执行授权…')
|
|
619
|
+
: `缺少凭证:${missing.refs.join(', ')}`;
|
|
620
|
+
const title = toolName === DATASOURCE_TEST_TOOL_NAME ? 'Marivo 连接测试' : 'Marivo 执行授权';
|
|
621
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: rowStyle, "data-marivo-datasource-tool": toolName, "data-marivo-call": callId, children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", children: "\u25CF" }), (0, jsx_runtime_1.jsx)("strong", { children: title }), (0, jsx_runtime_1.jsx)("span", { style: summaryStyle, children: credentialsReady ? `凭证已配置,请重试 ${toolName}` : summary }), missing !== null && !credentialsReady ? ((0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => {
|
|
622
|
+
void openDialog();
|
|
623
|
+
}, children: "\u914D\u7F6E\u51ED\u8BC1" })) : null] }), (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Modal, { open: open, onClose: () => {
|
|
624
|
+
if (!busy)
|
|
625
|
+
setOpen(false);
|
|
626
|
+
}, title: `配置 ${missing?.name ?? ''} 凭证`, description: "\u51ED\u8BC1\u7531 DSH \u51ED\u8BC1\u670D\u52A1\u4FDD\u5B58\uFF1BMarivo \u63D2\u4EF6\u4E0D\u4F1A\u5199\u5165 ~/.marivo/secrets.toml\u3002", closeLabel: "\u53D6\u6D88", footer: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { disabled: busy, onClick: () => setOpen(false), children: "\u53D6\u6D88" }), (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { variant: "primary", disabled: busy, onClick: () => {
|
|
627
|
+
void save();
|
|
628
|
+
}, children: busy ? '保存中…' : '保存' })] }), children: missing?.refs.map((ref) => ((0, jsx_runtime_1.jsxs)("label", { style: fieldStyle, children: [(0, jsx_runtime_1.jsxs)("span", { style: labelStyle, children: [(0, jsx_runtime_1.jsx)("code", { children: ref }), (0, jsx_runtime_1.jsx)("span", { children: configured[ref] ? '已配置' : '未配置' })] }), (0, jsx_runtime_1.jsx)("input", { style: inputStyle, type: "password", autoComplete: "new-password", value: values[ref] ?? '', "aria-label": ref, disabled: busy || configured[ref] === true, onChange: (event) => setValues((current) => ({ ...current, [ref]: event.target.value })) }), errors[ref] === undefined ? null : (0, jsx_runtime_1.jsx)("p", { style: errorStyle, children: errors[ref] })] }, ref))) })] }));
|
|
629
|
+
}
|
|
630
|
+
function MarivoDatasourceTestToolView(props) {
|
|
631
|
+
return MarivoDatasourceCredentialToolView({
|
|
632
|
+
...props,
|
|
633
|
+
toolName: DATASOURCE_TEST_TOOL_NAME,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
function MarivoDatasourceAccessToolView(props) {
|
|
637
|
+
return MarivoDatasourceCredentialToolView({
|
|
638
|
+
...props,
|
|
639
|
+
toolName: DATASOURCE_ACCESS_TOOL_NAME,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
const sourcePanelStyle = {
|
|
643
|
+
marginTop: 10,
|
|
644
|
+
padding: '10px 12px',
|
|
645
|
+
border: '1px solid var(--dsw-alias-border-subtle, #d7d7d7)',
|
|
646
|
+
borderRadius: 8,
|
|
647
|
+
background: 'var(--dsw-alias-surface-secondary, rgba(127, 127, 127, 0.06))',
|
|
648
|
+
color: 'var(--dsw-alias-text-primary, inherit)',
|
|
649
|
+
fontSize: 12,
|
|
650
|
+
};
|
|
651
|
+
const sourcePanelSummaryStyle = {
|
|
652
|
+
display: 'flex',
|
|
653
|
+
flexWrap: 'wrap',
|
|
654
|
+
alignItems: 'baseline',
|
|
655
|
+
gap: 8,
|
|
656
|
+
cursor: 'pointer',
|
|
657
|
+
};
|
|
658
|
+
const sourceGroupListStyle = {
|
|
659
|
+
display: 'grid',
|
|
660
|
+
gap: 10,
|
|
661
|
+
margin: '10px 0 0',
|
|
662
|
+
padding: 0,
|
|
663
|
+
listStyle: 'none',
|
|
664
|
+
};
|
|
665
|
+
const sourceGroupStyle = {
|
|
666
|
+
display: 'grid',
|
|
667
|
+
gap: 6,
|
|
668
|
+
paddingTop: 10,
|
|
669
|
+
borderTop: '1px solid var(--dsw-alias-border-subtle, #e2e2e2)',
|
|
670
|
+
};
|
|
671
|
+
const sourceIdentityStyle = { display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 6 };
|
|
672
|
+
const sourceBadgeStyle = {
|
|
673
|
+
padding: '1px 5px',
|
|
674
|
+
borderRadius: 999,
|
|
675
|
+
background: 'var(--dsw-alias-surface-tertiary, rgba(127, 127, 127, 0.12))',
|
|
676
|
+
};
|
|
677
|
+
const sourceSecondaryStyle = {
|
|
678
|
+
color: 'var(--dsw-alias-text-secondary, #666)',
|
|
679
|
+
overflowWrap: 'anywhere',
|
|
680
|
+
};
|
|
681
|
+
const sourceStatementStyle = { margin: 0, fontSize: 13, lineHeight: 1.55 };
|
|
682
|
+
const sourceAuditStyle = { marginTop: 5 };
|
|
683
|
+
const sourceAuditBodyStyle = { display: 'grid', gap: 8, paddingTop: 8 };
|
|
684
|
+
const sourceFindingStyle = {
|
|
685
|
+
display: 'grid',
|
|
686
|
+
gap: 4,
|
|
687
|
+
paddingTop: 8,
|
|
688
|
+
borderTop: '1px solid var(--dsw-alias-border-subtle, #e2e2e2)',
|
|
689
|
+
};
|
|
690
|
+
function MarivoEvidenceSourcesPanel({ matched: sources, t, }) {
|
|
691
|
+
const groups = groupMarivoEvidenceSources(sources);
|
|
692
|
+
return ((0, jsx_runtime_1.jsxs)("details", { style: sourcePanelStyle, "aria-label": t('source.title'), "data-marivo-sources-panel": true, children: [(0, jsx_runtime_1.jsxs)("summary", { style: sourcePanelSummaryStyle, children: [(0, jsx_runtime_1.jsx)("strong", { children: t('source.title') }), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.summary', {
|
|
693
|
+
artifacts: String(groups.length),
|
|
694
|
+
findings: String(sources.length),
|
|
695
|
+
}) })] }), (0, jsx_runtime_1.jsx)("ul", { style: sourceGroupListStyle, children: groups.map((group, index) => {
|
|
696
|
+
const statuses = [...new Set(group.sources.map((source) => source.status))];
|
|
697
|
+
const committed = [
|
|
698
|
+
...new Set(group.sources
|
|
699
|
+
.map((source) => source.committedAt)
|
|
700
|
+
.filter((value) => value !== null)),
|
|
701
|
+
];
|
|
702
|
+
return ((0, jsx_runtime_1.jsxs)("li", { style: sourceGroupStyle, children: [(0, jsx_runtime_1.jsx)("strong", { children: t('source.artifact', { index: String(index + 1) }) }), (0, jsx_runtime_1.jsxs)("div", { style: sourceIdentityStyle, children: [(0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.findings', { count: String(group.sources.length) }) }), statuses.map((status) => ((0, jsx_runtime_1.jsx)("span", { style: sourceBadgeStyle, children: t('source.status', { value: status }) }, status))), committed.length === 1 ? ((0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.committed', { committedAt: committed[0] }) })) : null] }), (0, jsx_runtime_1.jsxs)("details", { style: sourceAuditStyle, children: [(0, jsx_runtime_1.jsx)("summary", { children: t('source.audit') }), (0, jsx_runtime_1.jsxs)("div", { style: sourceAuditBodyStyle, children: [(0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.artifactRef', { id: group.artifactRef }) }), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.session', { id: group.sessionId }) }), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.environment', { fingerprint: group.environmentFingerprint }) }), group.sources.map((source) => ((0, jsx_runtime_1.jsxs)("div", { style: sourceFindingStyle, children: [(0, jsx_runtime_1.jsx)("strong", { children: source.title }), (0, jsx_runtime_1.jsx)("p", { style: sourceStatementStyle, children: source.excerpt ?? t('source.unavailable') }), (0, jsx_runtime_1.jsxs)("div", { style: sourceIdentityStyle, children: [(0, jsx_runtime_1.jsx)("span", { style: sourceBadgeStyle, children: t('source.status', { value: source.status }) }), (0, jsx_runtime_1.jsx)("span", { style: sourceBadgeStyle, children: t('source.excerptState', {
|
|
703
|
+
value: source.truncated ? t('source.truncated') : t('source.complete'),
|
|
704
|
+
}) }), source.findingType === null ? null : ((0, jsx_runtime_1.jsx)("span", { style: sourceBadgeStyle, children: source.findingType })), source.epistemicKind === null ? null : ((0, jsx_runtime_1.jsx)("span", { style: sourceBadgeStyle, children: source.epistemicKind }))] }), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.locator', { value: source.locator }) }), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.finding', { id: source.findingId }) }), source.canonicalItemKey === null ? null : ((0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.item', { id: source.canonicalItemKey }) })), source.committedAt === null ? null : ((0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.committed', { committedAt: source.committedAt }) })), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.revalidation', {
|
|
705
|
+
value: source.revalidation?.status ?? t('source.unavailable'),
|
|
706
|
+
}) }), (0, jsx_runtime_1.jsx)("span", { style: sourceSecondaryStyle, children: t('source.refs', {
|
|
707
|
+
value: source.sourceRefs.length === 0
|
|
708
|
+
? t('source.unavailable')
|
|
709
|
+
: source.sourceRefs.join(', '),
|
|
710
|
+
}) })] }, evidenceSourceIdentity(source))))] })] })] }, group.key));
|
|
711
|
+
}) }), (0, jsx_runtime_1.jsx)("div", { style: { ...sourceSecondaryStyle, marginTop: 10 }, children: t('source.disclaimer') })] }));
|
|
712
|
+
}
|
|
713
|
+
exports.inject = ['connection', 'slots', 'locale', 'conversationEvents'];
|
|
714
|
+
function apply(ctx) {
|
|
715
|
+
const connection = ctx.get('connection');
|
|
716
|
+
const BoundMarivoDatasourceTestToolView = (props) => ((0, jsx_runtime_1.jsx)(MarivoDatasourceTestToolView, { ...props, connection: connection }));
|
|
717
|
+
const BoundMarivoDatasourceAccessToolView = (props) => ((0, jsx_runtime_1.jsx)(MarivoDatasourceAccessToolView, { ...props, connection: connection }));
|
|
718
|
+
ctx.slots.inject('tool.call.toolview', () => {
|
|
719
|
+
const disposeTest = ctx.slots.register({
|
|
720
|
+
name: 'tool.call.toolview',
|
|
721
|
+
key: DATASOURCE_TEST_TOOL_NAME,
|
|
722
|
+
}, BoundMarivoDatasourceTestToolView);
|
|
723
|
+
const disposeAccess = ctx.slots.register({
|
|
724
|
+
name: 'tool.call.toolview',
|
|
725
|
+
key: DATASOURCE_ACCESS_TOOL_NAME,
|
|
726
|
+
}, BoundMarivoDatasourceAccessToolView);
|
|
727
|
+
return () => {
|
|
728
|
+
disposeAccess();
|
|
729
|
+
disposeTest();
|
|
730
|
+
};
|
|
731
|
+
});
|
|
732
|
+
ctx.conversationEvents.register(exports.marivoEvidenceSourcesDeliveryDefinition);
|
|
733
|
+
ctx.effect(() => ctx.locale.register(EVIDENCE_SOURCES_LOCALE_NAMESPACE, {
|
|
734
|
+
zh: EVIDENCE_SOURCES_ZH,
|
|
735
|
+
en: EVIDENCE_SOURCES_EN,
|
|
736
|
+
}), 'dsh-data-analysis: Evidence source dictionaries');
|
|
737
|
+
ctx.slots.inject('conversation.chat.turnTail', () => ctx.slots.register({
|
|
738
|
+
name: 'conversation.chat.turnTail',
|
|
739
|
+
select: selectMarivoEvidenceSources,
|
|
740
|
+
locale: EVIDENCE_SOURCES_LOCALE_NAMESPACE,
|
|
741
|
+
}, MarivoEvidenceSourcesPanel));
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
return module.exports; } });
|