@yadsh/dsh-qa-surface 0.4.0 → 0.5.0
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/README.md +41 -5
- package/cordis.patch.yml +8 -0
- package/lib/accounts/credentials.js +12 -4
- package/lib/accounts/credentials.js.map +1 -1
- package/lib/accounts/store.js +16 -1
- package/lib/accounts/store.js.map +1 -1
- package/lib/approvals.js +179 -0
- package/lib/approvals.js.map +1 -0
- package/lib/cli.js +10 -0
- package/lib/cli.js.map +1 -1
- package/lib/client/QaSessionController.js +93 -0
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +14 -1
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/approvals.js +104 -0
- package/lib/client/approvals.js.map +1 -0
- package/lib/client/attestation.js +3 -0
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/components/QaApproval.js +23 -0
- package/lib/client/components/QaApproval.js.map +1 -0
- package/lib/client/components/QaChangelog.js +24 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaQuestions.js +96 -0
- package/lib/client/components/QaQuestions.js.map +1 -0
- package/lib/client/index.js +11 -0
- package/lib/client/index.js.map +1 -1
- package/lib/client/project-session-state.js +5 -3
- package/lib/client/project-session-state.js.map +1 -1
- package/lib/client/questions.js +114 -0
- package/lib/client/questions.js.map +1 -0
- package/lib/client/settings/sections/sources.js +2 -0
- package/lib/client/settings/sections/sources.js.map +1 -1
- package/lib/client/styles.js +42 -0
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js +2 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client.js +1018 -56
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/basics.js +4 -2
- package/lib/config-resolvers/basics.js.map +1 -1
- package/lib/config-resolvers/defaults.js +4 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/lockdown.js +11 -0
- package/lib/config-resolvers/lockdown.js.map +1 -1
- package/lib/config-resolvers/session.js +2 -2
- package/lib/config-resolvers/session.js.map +1 -1
- package/lib/config-resolvers/shared.js +9 -0
- package/lib/config-resolvers/shared.js.map +1 -1
- package/lib/config-resolvers/sources.js +2 -0
- package/lib/config-resolvers/sources.js.map +1 -1
- package/lib/config.js +11 -2
- package/lib/config.js.map +1 -1
- package/lib/index.js +76 -6
- package/lib/index.js.map +1 -1
- package/lib/provenance/host-store.js +25 -9
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/provenance/reported.js +37 -12
- package/lib/provenance/reported.js.map +1 -1
- package/lib/questions.js +185 -0
- package/lib/questions.js.map +1 -0
- package/lib/secure-session.js +69 -17
- package/lib/secure-session.js.map +1 -1
- package/lib/session-ownership.js +55 -0
- package/lib/session-ownership.js.map +1 -0
- package/lib/typert.host.js +357 -17
- package/lib/typert.remote-client.d.ts +11 -1
- package/lib/typert.remote-client.js +287 -14
- package/lib/types/accounts/credentials.d.ts +6 -0
- package/lib/types/accounts/store.d.ts +8 -0
- package/lib/types/approvals.d.ts +65 -0
- package/lib/types/client/QaSessionController.d.ts +38 -1
- package/lib/types/client/QaSurface.d.ts +8 -1
- package/lib/types/client/approvals.d.ts +39 -0
- package/lib/types/client/components/QaApproval.d.ts +13 -0
- package/lib/types/client/components/QaQuestions.d.ts +13 -0
- package/lib/types/client/project-session-state.d.ts +8 -1
- package/lib/types/client/questions.d.ts +45 -0
- package/lib/types/client/types.d.ts +48 -1
- package/lib/types/config-resolvers/shared.d.ts +7 -0
- package/lib/types/index.d.ts +29 -3
- package/lib/types/provenance/reported.d.ts +9 -1
- package/lib/types/questions.d.ts +83 -0
- package/lib/types/secure-session.d.ts +21 -2
- package/lib/types/session-ownership.d.ts +30 -0
- package/lib/types/types.d.ts +80 -4
- package/lib/types/user-workspace.d.ts +5 -1
- package/lib/user-workspace.js +21 -6
- package/lib/user-workspace.js.map +1 -1
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -2736,7 +2736,7 @@ window.__ModuleLoader__.load({
|
|
|
2736
2736
|
}
|
|
2737
2737
|
let handoff;
|
|
2738
2738
|
const open = [];
|
|
2739
|
-
const memo$
|
|
2739
|
+
const memo$8 = {
|
|
2740
2740
|
alloc(_inst, payload, empty) {
|
|
2741
2741
|
const bucket = handoff;
|
|
2742
2742
|
if (!bucket) return empty;
|
|
@@ -2827,7 +2827,7 @@ window.__ModuleLoader__.load({
|
|
|
2827
2827
|
};
|
|
2828
2828
|
/** The memoizer that gives containers cycle support. `zod` installs it by default; `zod/mini` opts in with `config({ memoizer: memoizer() })`. */
|
|
2829
2829
|
function memoizer() {
|
|
2830
|
-
return memo$
|
|
2830
|
+
return memo$8;
|
|
2831
2831
|
}
|
|
2832
2832
|
/** Whether this value is a node a back-edge resolved to before it finished. */
|
|
2833
2833
|
function isBackEdge(ctx, value) {
|
|
@@ -5300,6 +5300,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5300
5300
|
}).readonly()
|
|
5301
5301
|
}).readonly()
|
|
5302
5302
|
})]);
|
|
5303
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_0$schema = string();
|
|
5304
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_1$schema = string();
|
|
5305
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_2$schema = string();
|
|
5306
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_3$schema = union([literal("allowed-once"), literal("rejected")]);
|
|
5307
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerApproval_result$schema = boolean();
|
|
5308
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_0$schema = string();
|
|
5309
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_1$schema = string();
|
|
5310
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_2$schema = string();
|
|
5311
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_3$schema = array(object({
|
|
5312
|
+
"id": string().readonly(),
|
|
5313
|
+
"selected": array(string()).readonly(),
|
|
5314
|
+
"custom": string().readonly().optional()
|
|
5315
|
+
}));
|
|
5316
|
+
const _yadsh_dsh_qa_surface_qaSurface_answerQuestion_result$schema = boolean();
|
|
5317
|
+
const _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_parameter_0$schema = string();
|
|
5318
|
+
const _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_parameter_1$schema = string();
|
|
5319
|
+
const _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_parameter_2$schema = string();
|
|
5320
|
+
const _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_result$schema = boolean();
|
|
5303
5321
|
const _yadsh_dsh_qa_surface_qaSurface_createSession_parameter_0$schema = string();
|
|
5304
5322
|
const _yadsh_dsh_qa_surface_qaSurface_createSession_result$schema = string();
|
|
5305
5323
|
const _yadsh_dsh_qa_surface_qaSurface_describe_result$schema = object({
|
|
@@ -5345,8 +5363,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5345
5363
|
"suggestedQuestions": array(string()).readonly(),
|
|
5346
5364
|
"thinkingPhrases": array(string()).readonly(),
|
|
5347
5365
|
"interaction": object({
|
|
5348
|
-
"approvals": literal("blocked").readonly(),
|
|
5349
|
-
"questions": literal("unsupported").readonly()
|
|
5366
|
+
"approvals": union([literal("blocked"), literal("interactive")]).readonly(),
|
|
5367
|
+
"questions": union([literal("interactive"), literal("unsupported")]).readonly()
|
|
5350
5368
|
}).readonly(),
|
|
5351
5369
|
"lockdown": object({
|
|
5352
5370
|
"enabled": boolean().readonly(),
|
|
@@ -5366,7 +5384,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5366
5384
|
"toolPolicy": object({
|
|
5367
5385
|
"mode": literal("allow-list").readonly(),
|
|
5368
5386
|
"allow": array(string()).readonly()
|
|
5369
|
-
}).readonly()
|
|
5387
|
+
}).readonly(),
|
|
5388
|
+
"sharedReadOnlyRoots": array(string()).readonly()
|
|
5370
5389
|
}).readonly(),
|
|
5371
5390
|
"embedding": object({ "frameAncestors": union([literal(null), string()]).readonly() }).readonly(),
|
|
5372
5391
|
"accounts": object({
|
|
@@ -5423,7 +5442,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5423
5442
|
"subagents": object({
|
|
5424
5443
|
"inheritSources": boolean().readonly(),
|
|
5425
5444
|
"enableReportToolFallback": boolean().readonly(),
|
|
5426
|
-
"markIncompleteOpaqueRuns": boolean().readonly()
|
|
5445
|
+
"markIncompleteOpaqueRuns": boolean().readonly(),
|
|
5446
|
+
"validateReportedSources": boolean().readonly()
|
|
5427
5447
|
}).readonly(),
|
|
5428
5448
|
"legacy": object({ "parseAssistantSourcesBlock": boolean().readonly() }).readonly()
|
|
5429
5449
|
}).readonly(),
|
|
@@ -5435,6 +5455,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5435
5455
|
"extensions": array(string()).readonly()
|
|
5436
5456
|
}).readonly()
|
|
5437
5457
|
});
|
|
5458
|
+
const _yadsh_dsh_qa_surface_qaSurface_pendingApprovals_parameter_0$schema = string();
|
|
5459
|
+
const _yadsh_dsh_qa_surface_qaSurface_pendingApprovals_parameter_1$schema = string();
|
|
5460
|
+
const _yadsh_dsh_qa_surface_qaSurface_pendingApprovals_result$schema = array(object({
|
|
5461
|
+
"id": string().readonly(),
|
|
5462
|
+
"sessionId": string().readonly(),
|
|
5463
|
+
"toolName": string().readonly(),
|
|
5464
|
+
"reason": union([literal(null), string()]).readonly(),
|
|
5465
|
+
"createdAt": number().readonly(),
|
|
5466
|
+
"delegated": boolean().readonly()
|
|
5467
|
+
}));
|
|
5468
|
+
const _yadsh_dsh_qa_surface_qaSurface_pendingQuestions_parameter_0$schema = string();
|
|
5469
|
+
const _yadsh_dsh_qa_surface_qaSurface_pendingQuestions_parameter_1$schema = string();
|
|
5470
|
+
const _yadsh_dsh_qa_surface_qaSurface_pendingQuestions_result$schema = array(object({
|
|
5471
|
+
"id": string().readonly(),
|
|
5472
|
+
"sessionId": string().readonly(),
|
|
5473
|
+
"questions": array(object({
|
|
5474
|
+
"id": string().readonly(),
|
|
5475
|
+
"question": string().readonly(),
|
|
5476
|
+
"header": union([literal(null), string()]).readonly(),
|
|
5477
|
+
"detail": union([literal(null), string()]).readonly(),
|
|
5478
|
+
"options": array(object({
|
|
5479
|
+
"label": string().readonly(),
|
|
5480
|
+
"description": union([literal(null), string()]).readonly()
|
|
5481
|
+
})).readonly(),
|
|
5482
|
+
"multiSelect": boolean().readonly()
|
|
5483
|
+
})).readonly(),
|
|
5484
|
+
"createdAt": number().readonly()
|
|
5485
|
+
}));
|
|
5438
5486
|
const _yadsh_dsh_qa_surface_qaSurface_readSourceFile_parameter_0$schema = string();
|
|
5439
5487
|
const _yadsh_dsh_qa_surface_qaSurface_readSourceFile_parameter_1$schema = string();
|
|
5440
5488
|
const _yadsh_dsh_qa_surface_qaSurface_readSourceFile_parameter_2$schema = string();
|
|
@@ -5614,7 +5662,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5614
5662
|
},
|
|
5615
5663
|
sourceLocation: {
|
|
5616
5664
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5617
|
-
"line":
|
|
5665
|
+
"line": 268,
|
|
5618
5666
|
"column": 3
|
|
5619
5667
|
}
|
|
5620
5668
|
},
|
|
@@ -5641,7 +5689,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5641
5689
|
},
|
|
5642
5690
|
sourceLocation: {
|
|
5643
5691
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5644
|
-
"line":
|
|
5692
|
+
"line": 287,
|
|
5645
5693
|
"column": 3
|
|
5646
5694
|
}
|
|
5647
5695
|
},
|
|
@@ -5677,7 +5725,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5677
5725
|
},
|
|
5678
5726
|
sourceLocation: {
|
|
5679
5727
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5680
|
-
"line":
|
|
5728
|
+
"line": 256,
|
|
5681
5729
|
"column": 3
|
|
5682
5730
|
}
|
|
5683
5731
|
},
|
|
@@ -5704,7 +5752,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5704
5752
|
},
|
|
5705
5753
|
sourceLocation: {
|
|
5706
5754
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5707
|
-
"line":
|
|
5755
|
+
"line": 277,
|
|
5708
5756
|
"column": 3
|
|
5709
5757
|
}
|
|
5710
5758
|
},
|
|
@@ -5740,7 +5788,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5740
5788
|
},
|
|
5741
5789
|
sourceLocation: {
|
|
5742
5790
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5743
|
-
"line":
|
|
5791
|
+
"line": 251,
|
|
5744
5792
|
"column": 3
|
|
5745
5793
|
}
|
|
5746
5794
|
},
|
|
@@ -5776,7 +5824,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5776
5824
|
},
|
|
5777
5825
|
sourceLocation: {
|
|
5778
5826
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5779
|
-
"line":
|
|
5827
|
+
"line": 300,
|
|
5780
5828
|
"column": 3
|
|
5781
5829
|
}
|
|
5782
5830
|
},
|
|
@@ -5803,10 +5851,177 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5803
5851
|
},
|
|
5804
5852
|
sourceLocation: {
|
|
5805
5853
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5806
|
-
"line":
|
|
5854
|
+
"line": 262,
|
|
5807
5855
|
"column": 3
|
|
5808
5856
|
}
|
|
5809
5857
|
},
|
|
5858
|
+
{
|
|
5859
|
+
id: "@yadsh/dsh-qa-surface#qaSurface/answerApproval",
|
|
5860
|
+
service: "qaSurface",
|
|
5861
|
+
namespace: "qaSurface",
|
|
5862
|
+
method: "answerApproval",
|
|
5863
|
+
invocation: { kind: "direct" },
|
|
5864
|
+
parameters: [
|
|
5865
|
+
{
|
|
5866
|
+
name: "token",
|
|
5867
|
+
wire: "token",
|
|
5868
|
+
source: "json",
|
|
5869
|
+
codec: {
|
|
5870
|
+
mode: "strict",
|
|
5871
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerApproval:token",
|
|
5872
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_0$schema
|
|
5873
|
+
}
|
|
5874
|
+
},
|
|
5875
|
+
{
|
|
5876
|
+
name: "sessionId",
|
|
5877
|
+
wire: "sessionId",
|
|
5878
|
+
source: "json",
|
|
5879
|
+
codec: {
|
|
5880
|
+
mode: "strict",
|
|
5881
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerApproval:sessionId",
|
|
5882
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_1$schema
|
|
5883
|
+
}
|
|
5884
|
+
},
|
|
5885
|
+
{
|
|
5886
|
+
name: "requestId",
|
|
5887
|
+
wire: "requestId",
|
|
5888
|
+
source: "json",
|
|
5889
|
+
codec: {
|
|
5890
|
+
mode: "strict",
|
|
5891
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerApproval:requestId",
|
|
5892
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_2$schema
|
|
5893
|
+
}
|
|
5894
|
+
},
|
|
5895
|
+
{
|
|
5896
|
+
name: "decision",
|
|
5897
|
+
wire: "decision",
|
|
5898
|
+
source: "json",
|
|
5899
|
+
codec: {
|
|
5900
|
+
mode: "strict",
|
|
5901
|
+
typeSymbol: "@yadsh/dsh-qa-surface/types#QaApprovalDecision",
|
|
5902
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerApproval_parameter_3$schema
|
|
5903
|
+
}
|
|
5904
|
+
}
|
|
5905
|
+
],
|
|
5906
|
+
result: {
|
|
5907
|
+
mode: "strict",
|
|
5908
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerApproval:result",
|
|
5909
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerApproval_result$schema
|
|
5910
|
+
},
|
|
5911
|
+
sourceLocation: {
|
|
5912
|
+
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5913
|
+
"line": 455,
|
|
5914
|
+
"column": 9
|
|
5915
|
+
}
|
|
5916
|
+
},
|
|
5917
|
+
{
|
|
5918
|
+
id: "@yadsh/dsh-qa-surface#qaSurface/answerQuestion",
|
|
5919
|
+
service: "qaSurface",
|
|
5920
|
+
namespace: "qaSurface",
|
|
5921
|
+
method: "answerQuestion",
|
|
5922
|
+
invocation: { kind: "direct" },
|
|
5923
|
+
parameters: [
|
|
5924
|
+
{
|
|
5925
|
+
name: "token",
|
|
5926
|
+
wire: "token",
|
|
5927
|
+
source: "json",
|
|
5928
|
+
codec: {
|
|
5929
|
+
mode: "strict",
|
|
5930
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerQuestion:token",
|
|
5931
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_0$schema
|
|
5932
|
+
}
|
|
5933
|
+
},
|
|
5934
|
+
{
|
|
5935
|
+
name: "sessionId",
|
|
5936
|
+
wire: "sessionId",
|
|
5937
|
+
source: "json",
|
|
5938
|
+
codec: {
|
|
5939
|
+
mode: "strict",
|
|
5940
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerQuestion:sessionId",
|
|
5941
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_1$schema
|
|
5942
|
+
}
|
|
5943
|
+
},
|
|
5944
|
+
{
|
|
5945
|
+
name: "requestId",
|
|
5946
|
+
wire: "requestId",
|
|
5947
|
+
source: "json",
|
|
5948
|
+
codec: {
|
|
5949
|
+
mode: "strict",
|
|
5950
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerQuestion:requestId",
|
|
5951
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_2$schema
|
|
5952
|
+
}
|
|
5953
|
+
},
|
|
5954
|
+
{
|
|
5955
|
+
name: "answers",
|
|
5956
|
+
wire: "answers",
|
|
5957
|
+
source: "json",
|
|
5958
|
+
codec: {
|
|
5959
|
+
mode: "strict",
|
|
5960
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerQuestion:answers",
|
|
5961
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerQuestion_parameter_3$schema
|
|
5962
|
+
}
|
|
5963
|
+
}
|
|
5964
|
+
],
|
|
5965
|
+
result: {
|
|
5966
|
+
mode: "strict",
|
|
5967
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/answerQuestion:result",
|
|
5968
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_answerQuestion_result$schema
|
|
5969
|
+
},
|
|
5970
|
+
sourceLocation: {
|
|
5971
|
+
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5972
|
+
"line": 484,
|
|
5973
|
+
"column": 9
|
|
5974
|
+
}
|
|
5975
|
+
},
|
|
5976
|
+
{
|
|
5977
|
+
id: "@yadsh/dsh-qa-surface#qaSurface/cancelQuestion",
|
|
5978
|
+
service: "qaSurface",
|
|
5979
|
+
namespace: "qaSurface",
|
|
5980
|
+
method: "cancelQuestion",
|
|
5981
|
+
invocation: { kind: "direct" },
|
|
5982
|
+
parameters: [
|
|
5983
|
+
{
|
|
5984
|
+
name: "token",
|
|
5985
|
+
wire: "token",
|
|
5986
|
+
source: "json",
|
|
5987
|
+
codec: {
|
|
5988
|
+
mode: "strict",
|
|
5989
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/cancelQuestion:token",
|
|
5990
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_parameter_0$schema
|
|
5991
|
+
}
|
|
5992
|
+
},
|
|
5993
|
+
{
|
|
5994
|
+
name: "sessionId",
|
|
5995
|
+
wire: "sessionId",
|
|
5996
|
+
source: "json",
|
|
5997
|
+
codec: {
|
|
5998
|
+
mode: "strict",
|
|
5999
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/cancelQuestion:sessionId",
|
|
6000
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_parameter_1$schema
|
|
6001
|
+
}
|
|
6002
|
+
},
|
|
6003
|
+
{
|
|
6004
|
+
name: "requestId",
|
|
6005
|
+
wire: "requestId",
|
|
6006
|
+
source: "json",
|
|
6007
|
+
codec: {
|
|
6008
|
+
mode: "strict",
|
|
6009
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/cancelQuestion:requestId",
|
|
6010
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_parameter_2$schema
|
|
6011
|
+
}
|
|
6012
|
+
}
|
|
6013
|
+
],
|
|
6014
|
+
result: {
|
|
6015
|
+
mode: "strict",
|
|
6016
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/cancelQuestion:result",
|
|
6017
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_cancelQuestion_result$schema
|
|
6018
|
+
},
|
|
6019
|
+
sourceLocation: {
|
|
6020
|
+
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
6021
|
+
"line": 496,
|
|
6022
|
+
"column": 9
|
|
6023
|
+
}
|
|
6024
|
+
},
|
|
5810
6025
|
{
|
|
5811
6026
|
id: "@yadsh/dsh-qa-surface#qaSurface/createSession",
|
|
5812
6027
|
service: "qaSurface",
|
|
@@ -5830,7 +6045,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5830
6045
|
},
|
|
5831
6046
|
sourceLocation: {
|
|
5832
6047
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5833
|
-
"line":
|
|
6048
|
+
"line": 325,
|
|
5834
6049
|
"column": 9
|
|
5835
6050
|
}
|
|
5836
6051
|
},
|
|
@@ -5848,10 +6063,82 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5848
6063
|
},
|
|
5849
6064
|
sourceLocation: {
|
|
5850
6065
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5851
|
-
"line":
|
|
6066
|
+
"line": 315,
|
|
5852
6067
|
"column": 3
|
|
5853
6068
|
}
|
|
5854
6069
|
},
|
|
6070
|
+
{
|
|
6071
|
+
id: "@yadsh/dsh-qa-surface#qaSurface/pendingApprovals",
|
|
6072
|
+
service: "qaSurface",
|
|
6073
|
+
namespace: "qaSurface",
|
|
6074
|
+
method: "pendingApprovals",
|
|
6075
|
+
invocation: { kind: "direct" },
|
|
6076
|
+
parameters: [{
|
|
6077
|
+
name: "token",
|
|
6078
|
+
wire: "token",
|
|
6079
|
+
source: "json",
|
|
6080
|
+
codec: {
|
|
6081
|
+
mode: "strict",
|
|
6082
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/pendingApprovals:token",
|
|
6083
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_pendingApprovals_parameter_0$schema
|
|
6084
|
+
}
|
|
6085
|
+
}, {
|
|
6086
|
+
name: "sessionId",
|
|
6087
|
+
wire: "sessionId",
|
|
6088
|
+
source: "json",
|
|
6089
|
+
codec: {
|
|
6090
|
+
mode: "strict",
|
|
6091
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/pendingApprovals:sessionId",
|
|
6092
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_pendingApprovals_parameter_1$schema
|
|
6093
|
+
}
|
|
6094
|
+
}],
|
|
6095
|
+
result: {
|
|
6096
|
+
mode: "strict",
|
|
6097
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/pendingApprovals:result",
|
|
6098
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_pendingApprovals_result$schema
|
|
6099
|
+
},
|
|
6100
|
+
sourceLocation: {
|
|
6101
|
+
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
6102
|
+
"line": 441,
|
|
6103
|
+
"column": 9
|
|
6104
|
+
}
|
|
6105
|
+
},
|
|
6106
|
+
{
|
|
6107
|
+
id: "@yadsh/dsh-qa-surface#qaSurface/pendingQuestions",
|
|
6108
|
+
service: "qaSurface",
|
|
6109
|
+
namespace: "qaSurface",
|
|
6110
|
+
method: "pendingQuestions",
|
|
6111
|
+
invocation: { kind: "direct" },
|
|
6112
|
+
parameters: [{
|
|
6113
|
+
name: "token",
|
|
6114
|
+
wire: "token",
|
|
6115
|
+
source: "json",
|
|
6116
|
+
codec: {
|
|
6117
|
+
mode: "strict",
|
|
6118
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/pendingQuestions:token",
|
|
6119
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_pendingQuestions_parameter_0$schema
|
|
6120
|
+
}
|
|
6121
|
+
}, {
|
|
6122
|
+
name: "sessionId",
|
|
6123
|
+
wire: "sessionId",
|
|
6124
|
+
source: "json",
|
|
6125
|
+
codec: {
|
|
6126
|
+
mode: "strict",
|
|
6127
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/pendingQuestions:sessionId",
|
|
6128
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_pendingQuestions_parameter_1$schema
|
|
6129
|
+
}
|
|
6130
|
+
}],
|
|
6131
|
+
result: {
|
|
6132
|
+
mode: "strict",
|
|
6133
|
+
typeSymbol: "@yadsh/dsh-qa-surface#qaSurface/pendingQuestions:result",
|
|
6134
|
+
schema: _yadsh_dsh_qa_surface_qaSurface_pendingQuestions_result$schema
|
|
6135
|
+
},
|
|
6136
|
+
sourceLocation: {
|
|
6137
|
+
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
6138
|
+
"line": 470,
|
|
6139
|
+
"column": 9
|
|
6140
|
+
}
|
|
6141
|
+
},
|
|
5855
6142
|
{
|
|
5856
6143
|
id: "@yadsh/dsh-qa-surface#qaSurface/readSourceFile",
|
|
5857
6144
|
service: "qaSurface",
|
|
@@ -5897,7 +6184,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5897
6184
|
},
|
|
5898
6185
|
sourceLocation: {
|
|
5899
6186
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5900
|
-
"line":
|
|
6187
|
+
"line": 507,
|
|
5901
6188
|
"column": 9
|
|
5902
6189
|
}
|
|
5903
6190
|
},
|
|
@@ -5933,8 +6220,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5933
6220
|
},
|
|
5934
6221
|
sourceLocation: {
|
|
5935
6222
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5936
|
-
"line":
|
|
5937
|
-
"column":
|
|
6223
|
+
"line": 399,
|
|
6224
|
+
"column": 9
|
|
5938
6225
|
}
|
|
5939
6226
|
},
|
|
5940
6227
|
{
|
|
@@ -5969,8 +6256,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5969
6256
|
},
|
|
5970
6257
|
sourceLocation: {
|
|
5971
6258
|
"file": "packages/dsh-qa-surface/src/index.ts",
|
|
5972
|
-
"line":
|
|
5973
|
-
"column":
|
|
6259
|
+
"line": 428,
|
|
6260
|
+
"column": 9
|
|
5974
6261
|
}
|
|
5975
6262
|
}
|
|
5976
6263
|
]
|
|
@@ -6459,7 +6746,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6459
6746
|
toolPolicy: Object.freeze({
|
|
6460
6747
|
mode: "allow-list",
|
|
6461
6748
|
allow: Object.freeze([])
|
|
6462
|
-
})
|
|
6749
|
+
}),
|
|
6750
|
+
sharedReadOnlyRoots: Object.freeze([])
|
|
6463
6751
|
}),
|
|
6464
6752
|
embedding: Object.freeze({ frameAncestors: null }),
|
|
6465
6753
|
accounts: Object.freeze({
|
|
@@ -6513,7 +6801,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6513
6801
|
subagents: Object.freeze({
|
|
6514
6802
|
inheritSources: true,
|
|
6515
6803
|
enableReportToolFallback: true,
|
|
6516
|
-
markIncompleteOpaqueRuns: true
|
|
6804
|
+
markIncompleteOpaqueRuns: true,
|
|
6805
|
+
validateReportedSources: true
|
|
6517
6806
|
}),
|
|
6518
6807
|
legacy: Object.freeze({ parseAssistantSourcesBlock: false })
|
|
6519
6808
|
}),
|
|
@@ -6533,6 +6822,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6533
6822
|
return trimmed === "" ? null : trimmed;
|
|
6534
6823
|
}
|
|
6535
6824
|
/**
|
|
6825
|
+
* Whether a configured directory is absolute. The rule reads a drive-letter
|
|
6826
|
+
* path as absolute on every platform, like `session.cwd` does: a deployment
|
|
6827
|
+
* profile is authored on one machine and may be read on another, so a
|
|
6828
|
+
* Windows-style root is not a mistake to reject on a POSIX host.
|
|
6829
|
+
*/
|
|
6830
|
+
function isAbsoluteDirectoryPath(value) {
|
|
6831
|
+
return /^([a-zA-Z]:[/\\]|\/)/u.test(value);
|
|
6832
|
+
}
|
|
6833
|
+
/**
|
|
6536
6834
|
* Shared numeric guard for operator-tuned limits: the value has to be a safe
|
|
6537
6835
|
* integer inside [min, max], and every rejection carries the same message.
|
|
6538
6836
|
*/
|
|
@@ -6643,8 +6941,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6643
6941
|
cookieBootstrap: input.entry?.cookieBootstrap ?? DEFAULT_QA_SURFACE_CONFIG.entry.cookieBootstrap
|
|
6644
6942
|
}),
|
|
6645
6943
|
interaction: Object.freeze({
|
|
6646
|
-
approvals:
|
|
6647
|
-
questions:
|
|
6944
|
+
approvals: input.interaction?.approvals ?? DEFAULT_QA_SURFACE_CONFIG.interaction.approvals,
|
|
6945
|
+
questions: input.interaction?.questions ?? DEFAULT_QA_SURFACE_CONFIG.interaction.questions
|
|
6648
6946
|
})
|
|
6649
6947
|
};
|
|
6650
6948
|
}
|
|
@@ -6656,6 +6954,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6656
6954
|
if (names.some((value) => value.length > 200)) throw new TypeError("dsh-qa-surface: lockdown.toolPolicy.allow names must be at most 200 characters");
|
|
6657
6955
|
return Object.freeze(names);
|
|
6658
6956
|
}
|
|
6957
|
+
function uniqueAbsoluteRoots(values) {
|
|
6958
|
+
const roots = [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
6959
|
+
if (roots.some((value) => !isAbsoluteDirectoryPath(value))) throw new TypeError("dsh-qa-surface: lockdown.sharedReadOnlyRoots must contain only absolute paths");
|
|
6960
|
+
return Object.freeze(roots);
|
|
6961
|
+
}
|
|
6659
6962
|
/**
|
|
6660
6963
|
* Resolve the lockdown domain. The capability flags are clamped shut, and
|
|
6661
6964
|
* showing the reset control needs an explicit authorization here, so the
|
|
@@ -6699,7 +7002,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6699
7002
|
toolPolicy: Object.freeze({
|
|
6700
7003
|
mode: "allow-list",
|
|
6701
7004
|
allow: uniqueToolNames(input.lockdown?.toolPolicy?.allow ?? [])
|
|
6702
|
-
})
|
|
7005
|
+
}),
|
|
7006
|
+
sharedReadOnlyRoots: uniqueAbsoluteRoots(input.lockdown?.sharedReadOnlyRoots ?? [])
|
|
6703
7007
|
});
|
|
6704
7008
|
}
|
|
6705
7009
|
//#endregion
|
|
@@ -6710,7 +7014,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6710
7014
|
const fixedSessionId = optionalText(input.session?.fixedSessionId);
|
|
6711
7015
|
if (policy === "fixed" && fixedSessionId === null) throw new TypeError("dsh-qa-surface: session.fixedSessionId is required for fixed policy");
|
|
6712
7016
|
const cwd = optionalText(input.session?.cwd);
|
|
6713
|
-
if (cwd !== null &&
|
|
7017
|
+
if (cwd !== null && !isAbsoluteDirectoryPath(cwd)) throw new TypeError("dsh-qa-surface: session.cwd must be an absolute directory path");
|
|
6714
7018
|
const workspaceId = optionalText(input.session?.workspaceId);
|
|
6715
7019
|
if (workspaceId !== null && cwd !== null) throw new TypeError("dsh-qa-surface: session.workspaceId and session.cwd are mutually exclusive");
|
|
6716
7020
|
const provider = optionalText(input.session?.provider);
|
|
@@ -6777,7 +7081,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6777
7081
|
subagents: Object.freeze({
|
|
6778
7082
|
inheritSources: input.sources?.subagents?.inheritSources ?? DEFAULT_QA_SURFACE_CONFIG.sources.subagents.inheritSources,
|
|
6779
7083
|
enableReportToolFallback: input.sources?.subagents?.enableReportToolFallback ?? DEFAULT_QA_SURFACE_CONFIG.sources.subagents.enableReportToolFallback,
|
|
6780
|
-
markIncompleteOpaqueRuns: input.sources?.subagents?.markIncompleteOpaqueRuns ?? DEFAULT_QA_SURFACE_CONFIG.sources.subagents.markIncompleteOpaqueRuns
|
|
7084
|
+
markIncompleteOpaqueRuns: input.sources?.subagents?.markIncompleteOpaqueRuns ?? DEFAULT_QA_SURFACE_CONFIG.sources.subagents.markIncompleteOpaqueRuns,
|
|
7085
|
+
validateReportedSources: input.sources?.subagents?.validateReportedSources ?? DEFAULT_QA_SURFACE_CONFIG.sources.subagents.validateReportedSources
|
|
6781
7086
|
}),
|
|
6782
7087
|
legacy: Object.freeze({ parseAssistantSourcesBlock: input.sources?.legacy?.parseAssistantSourcesBlock ?? DEFAULT_QA_SURFACE_CONFIG.sources.legacy.parseAssistantSourcesBlock })
|
|
6783
7088
|
});
|
|
@@ -7493,6 +7798,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7493
7798
|
return reason === void 0 ? null : reason;
|
|
7494
7799
|
}
|
|
7495
7800
|
function attestationHint(reason) {
|
|
7801
|
+
if (reason === "agent-unavailable") return "The Host could not put a live agent behind this chat: resuming the composition its session recorded failed (a preset that no longer mounts does this). The refusal detail is in the Host logs.";
|
|
7496
7802
|
if (reason === "unknown-tools") return "A lockdown.toolPolicy name is not mounted in this session's tool catalog — check the deployment agent preset and the tool's server availability.";
|
|
7497
7803
|
if (reason === "workspace-unavailable") return "The configured session.workspaceId does not match a registered workspace - create the workspace or fix the id (session.cwd is the no-registry alternative).";
|
|
7498
7804
|
if (reason === "composition-mismatch") return "The session's agent preset, workspace or model no longer matches the deployment QA config.";
|
|
@@ -7726,6 +8032,194 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7726
8032
|
}
|
|
7727
8033
|
};
|
|
7728
8034
|
//#endregion
|
|
8035
|
+
//#region src/client/approvals.ts
|
|
8036
|
+
/**
|
|
8037
|
+
* The operator's side of a parked tool call.
|
|
8038
|
+
*
|
|
8039
|
+
* A composed gate's `ask` is answered on the Host, so the waiting request is
|
|
8040
|
+
* Host state: it survives a page reload, and the surface learns about it by
|
|
8041
|
+
* asking rather than by receiving an event. The bridge holds the last list it
|
|
8042
|
+
* saw, refreshes it while a turn runs, and forwards an answer.
|
|
8043
|
+
*/
|
|
8044
|
+
var QaHostApprovalBridge = class {
|
|
8045
|
+
approvalApi;
|
|
8046
|
+
approvals = [];
|
|
8047
|
+
signature = "";
|
|
8048
|
+
refreshing = false;
|
|
8049
|
+
answering = false;
|
|
8050
|
+
/** Bumped on reset so a stale in-flight response never lands. */
|
|
8051
|
+
generation = 0;
|
|
8052
|
+
constructor(approvalApi) {
|
|
8053
|
+
this.approvalApi = approvalApi;
|
|
8054
|
+
}
|
|
8055
|
+
/** Leave the chat: a chat switch drops the previous chat's requests. */
|
|
8056
|
+
reset() {
|
|
8057
|
+
this.generation += 1;
|
|
8058
|
+
this.approvals = [];
|
|
8059
|
+
this.signature = "";
|
|
8060
|
+
this.refreshing = false;
|
|
8061
|
+
this.answering = false;
|
|
8062
|
+
}
|
|
8063
|
+
/** The last list this bridge saw; empty when the deployment blocks them. */
|
|
8064
|
+
list() {
|
|
8065
|
+
return this.approvals;
|
|
8066
|
+
}
|
|
8067
|
+
/** Whether this page can ask the Host about approvals at all. */
|
|
8068
|
+
get available() {
|
|
8069
|
+
return this.approvalApi !== void 0;
|
|
8070
|
+
}
|
|
8071
|
+
/**
|
|
8072
|
+
* Re-read the chat's pending requests; a changed list republishes through the
|
|
8073
|
+
* callback. Overlapping calls coalesce, and a response that outlives its chat
|
|
8074
|
+
* is dropped.
|
|
8075
|
+
*/
|
|
8076
|
+
async refresh(sessionId, token, onChanged) {
|
|
8077
|
+
const api = this.approvalApi;
|
|
8078
|
+
if (api === void 0 || this.refreshing) return;
|
|
8079
|
+
const generation = this.generation;
|
|
8080
|
+
this.refreshing = true;
|
|
8081
|
+
try {
|
|
8082
|
+
const result = await api.pendingApprovals(token, sessionId);
|
|
8083
|
+
if (!result.ok || generation !== this.generation) return;
|
|
8084
|
+
const signature = JSON.stringify(result.value);
|
|
8085
|
+
if (signature === this.signature) return;
|
|
8086
|
+
this.signature = signature;
|
|
8087
|
+
this.approvals = result.value;
|
|
8088
|
+
onChanged();
|
|
8089
|
+
} catch (error) {
|
|
8090
|
+
console.error("dsh-qa-surface: approval poll failed", error);
|
|
8091
|
+
} finally {
|
|
8092
|
+
if (generation === this.generation) this.refreshing = false;
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
/**
|
|
8096
|
+
* Answer one request and re-read the list. A refusal is not an error: the
|
|
8097
|
+
* request was already settled (the turn was stopped, the call went away), so
|
|
8098
|
+
* the refresh — not the answer — is what the surface shows.
|
|
8099
|
+
*/
|
|
8100
|
+
async answer(sessionId, token, requestId, decision) {
|
|
8101
|
+
const api = this.approvalApi;
|
|
8102
|
+
if (api === void 0 || this.answering) return;
|
|
8103
|
+
this.answering = true;
|
|
8104
|
+
const generation = this.generation;
|
|
8105
|
+
try {
|
|
8106
|
+
await api.answerApproval(token, sessionId, requestId, decision);
|
|
8107
|
+
const result = await api.pendingApprovals(token, sessionId);
|
|
8108
|
+
if (generation !== this.generation) return;
|
|
8109
|
+
if (result.ok) {
|
|
8110
|
+
this.signature = JSON.stringify(result.value);
|
|
8111
|
+
this.approvals = result.value;
|
|
8112
|
+
return;
|
|
8113
|
+
}
|
|
8114
|
+
this.signature = "";
|
|
8115
|
+
this.approvals = this.approvals.filter((approval) => approval.id !== requestId);
|
|
8116
|
+
} catch (error) {
|
|
8117
|
+
console.error("dsh-qa-surface: approval answer failed", error);
|
|
8118
|
+
} finally {
|
|
8119
|
+
this.answering = false;
|
|
8120
|
+
}
|
|
8121
|
+
}
|
|
8122
|
+
};
|
|
8123
|
+
//#endregion
|
|
8124
|
+
//#region src/client/questions.ts
|
|
8125
|
+
/**
|
|
8126
|
+
* The operator's side of a parked `ask_user_question` call.
|
|
8127
|
+
*
|
|
8128
|
+
* Like a parked approval, the request lives on the Host: it survives a reload,
|
|
8129
|
+
* and the surface learns about it by asking while a turn runs. Unlike an
|
|
8130
|
+
* approval, an answer is a whole form — every question of the request, with the
|
|
8131
|
+
* operator's selections and free text — so the bridge forwards the form and
|
|
8132
|
+
* re-reads the list afterwards.
|
|
8133
|
+
*/
|
|
8134
|
+
var QaHostQuestionBridge = class {
|
|
8135
|
+
questionApi;
|
|
8136
|
+
questions = [];
|
|
8137
|
+
signature = "";
|
|
8138
|
+
refreshing = false;
|
|
8139
|
+
answering = false;
|
|
8140
|
+
/** Bumped on reset so a stale in-flight response never lands. */
|
|
8141
|
+
generation = 0;
|
|
8142
|
+
constructor(questionApi) {
|
|
8143
|
+
this.questionApi = questionApi;
|
|
8144
|
+
}
|
|
8145
|
+
/** Leave the chat: a chat switch drops the previous chat's requests. */
|
|
8146
|
+
reset() {
|
|
8147
|
+
this.generation += 1;
|
|
8148
|
+
this.questions = [];
|
|
8149
|
+
this.signature = "";
|
|
8150
|
+
this.refreshing = false;
|
|
8151
|
+
this.answering = false;
|
|
8152
|
+
}
|
|
8153
|
+
/** The last list this bridge saw; empty when the deployment refuses them. */
|
|
8154
|
+
list() {
|
|
8155
|
+
return this.questions;
|
|
8156
|
+
}
|
|
8157
|
+
/** Whether this page can ask the Host about questions at all. */
|
|
8158
|
+
get available() {
|
|
8159
|
+
return this.questionApi !== void 0;
|
|
8160
|
+
}
|
|
8161
|
+
/**
|
|
8162
|
+
* Re-read the chat's pending questions; a changed list republishes through
|
|
8163
|
+
* the callback. Overlapping calls coalesce, and a response that outlives its
|
|
8164
|
+
* chat is dropped.
|
|
8165
|
+
*/
|
|
8166
|
+
async refresh(sessionId, token, onChanged) {
|
|
8167
|
+
const api = this.questionApi;
|
|
8168
|
+
if (api === void 0 || this.refreshing) return;
|
|
8169
|
+
const generation = this.generation;
|
|
8170
|
+
this.refreshing = true;
|
|
8171
|
+
try {
|
|
8172
|
+
const result = await api.pendingQuestions(token, sessionId);
|
|
8173
|
+
if (!result.ok || generation !== this.generation) return;
|
|
8174
|
+
const signature = JSON.stringify(result.value);
|
|
8175
|
+
if (signature === this.signature) return;
|
|
8176
|
+
this.signature = signature;
|
|
8177
|
+
this.questions = result.value;
|
|
8178
|
+
onChanged();
|
|
8179
|
+
} catch (error) {
|
|
8180
|
+
console.error("dsh-qa-surface: question poll failed", error);
|
|
8181
|
+
} finally {
|
|
8182
|
+
if (generation === this.generation) this.refreshing = false;
|
|
8183
|
+
}
|
|
8184
|
+
}
|
|
8185
|
+
/** Send the operator's answers to one request and re-read the list. */
|
|
8186
|
+
async answer(sessionId, token, requestId, answers) {
|
|
8187
|
+
await this.settle(sessionId, token, requestId, (api) => api.answerQuestion(token, sessionId, requestId, answers));
|
|
8188
|
+
}
|
|
8189
|
+
/** Close one request without answering it. */
|
|
8190
|
+
async cancel(sessionId, token, requestId) {
|
|
8191
|
+
await this.settle(sessionId, token, requestId, (api) => api.cancelQuestion(token, sessionId, requestId));
|
|
8192
|
+
}
|
|
8193
|
+
/**
|
|
8194
|
+
* Run one write against a request, then re-read the list it belonged to. A
|
|
8195
|
+
* refusal is not an error: the request was already settled (the turn was
|
|
8196
|
+
* stopped, the call went away), so the refresh — not the write — is what the
|
|
8197
|
+
* surface shows.
|
|
8198
|
+
*/
|
|
8199
|
+
async settle(sessionId, token, requestId, write) {
|
|
8200
|
+
const api = this.questionApi;
|
|
8201
|
+
if (api === void 0 || this.answering) return;
|
|
8202
|
+
this.answering = true;
|
|
8203
|
+
const generation = this.generation;
|
|
8204
|
+
try {
|
|
8205
|
+
await write(api);
|
|
8206
|
+
const result = await api.pendingQuestions(token, sessionId);
|
|
8207
|
+
if (generation !== this.generation) return;
|
|
8208
|
+
if (result.ok) {
|
|
8209
|
+
this.signature = JSON.stringify(result.value);
|
|
8210
|
+
this.questions = result.value;
|
|
8211
|
+
return;
|
|
8212
|
+
}
|
|
8213
|
+
this.signature = "";
|
|
8214
|
+
this.questions = this.questions.filter((entry) => entry.id !== requestId);
|
|
8215
|
+
} catch (error) {
|
|
8216
|
+
console.error("dsh-qa-surface: question answer failed", error);
|
|
8217
|
+
} finally {
|
|
8218
|
+
this.answering = false;
|
|
8219
|
+
}
|
|
8220
|
+
}
|
|
8221
|
+
};
|
|
8222
|
+
//#endregion
|
|
7729
8223
|
//#region src/client/stream-publisher.ts
|
|
7730
8224
|
/**
|
|
7731
8225
|
* Spacing for a running turn's stream frames. A running turn's frames arrive
|
|
@@ -7785,7 +8279,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7785
8279
|
sources: Object.freeze([]),
|
|
7786
8280
|
sourcesComplete: true,
|
|
7787
8281
|
incompleteSourceOrigins: void 0,
|
|
7788
|
-
viewingSubagent: null
|
|
8282
|
+
viewingSubagent: null,
|
|
8283
|
+
approvals: Object.freeze([]),
|
|
8284
|
+
questions: Object.freeze([])
|
|
7789
8285
|
});
|
|
7790
8286
|
//#endregion
|
|
7791
8287
|
//#region src/client/wait-for.ts
|
|
@@ -9029,13 +9525,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9029
9525
|
sources: latest === void 0 ? [] : [...latest.sources, ...config.sources.display.showDiscovered ? latest.discovered ?? [] : []],
|
|
9030
9526
|
sourcesComplete: latest?.complete ?? true,
|
|
9031
9527
|
incompleteSourceOrigins: latest?.incompleteOrigins,
|
|
9032
|
-
viewingSubagent: input.viewingSubagent
|
|
9528
|
+
viewingSubagent: input.viewingSubagent,
|
|
9529
|
+
approvals: input.approvals,
|
|
9530
|
+
questions: input.questions
|
|
9033
9531
|
};
|
|
9034
9532
|
}
|
|
9035
9533
|
//#endregion
|
|
9036
9534
|
//#region src/client/QaSessionController.ts
|
|
9037
9535
|
const CONFIGURATION_ERROR = "Настройки помощника недоступны.";
|
|
9038
9536
|
/**
|
|
9537
|
+
* Spacing of the parked-request poll. A request is answered by a person, so a
|
|
9538
|
+
* second of latency is invisible; the poll only runs while a turn runs.
|
|
9539
|
+
*/
|
|
9540
|
+
const PENDING_POLL_MS = 1e3;
|
|
9541
|
+
/**
|
|
9039
9542
|
* The only module that couples QA behavior to DSH Session/client APIs. It owns
|
|
9040
9543
|
* the chat lifecycle state machine; the observable wait, browser-local chat
|
|
9041
9544
|
* bookkeeping and policy-attestation details live in their own modules.
|
|
@@ -9079,6 +9582,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9079
9582
|
chatsRevision = 0;
|
|
9080
9583
|
/** Host-side provenance of the bound chat, merged into the projection. */
|
|
9081
9584
|
hostSources;
|
|
9585
|
+
/** Host-side approvals of the bound chat waiting for the operator. */
|
|
9586
|
+
hostApprovals;
|
|
9587
|
+
/** Host-side question requests of the bound chat waiting for the operator. */
|
|
9588
|
+
hostQuestions;
|
|
9589
|
+
/** Set while a running turn is polled for parked requests. */
|
|
9590
|
+
pendingTimer;
|
|
9082
9591
|
constructor(options) {
|
|
9083
9592
|
this.sessions = options.sessions;
|
|
9084
9593
|
this.createSessionRemote = options.createSession;
|
|
@@ -9100,6 +9609,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9100
9609
|
this.accounts = options.accounts;
|
|
9101
9610
|
this.fileUpload = options.fileUpload ?? (() => void 0);
|
|
9102
9611
|
this.hostSources = new QaHostSourceBridge(this.sourceApi, () => this.accounts?.token() ?? "");
|
|
9612
|
+
this.hostApprovals = new QaHostApprovalBridge(options.approvalApi);
|
|
9613
|
+
this.hostQuestions = new QaHostQuestionBridge(options.questionApi);
|
|
9103
9614
|
this.timeoutMs = options.timeoutMs ?? 15e3;
|
|
9104
9615
|
this.streamPublisher = new StreamPublisher(options.streamIntervalMs ?? 66);
|
|
9105
9616
|
this.connectedOnce = this.connection.getSnapshot() !== void 0;
|
|
@@ -9557,6 +10068,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9557
10068
|
if (this.session !== void 0) this.assets.release(String(this.session.sessionId));
|
|
9558
10069
|
this.session = void 0;
|
|
9559
10070
|
this.hostSources.reset();
|
|
10071
|
+
this.hostApprovals.reset();
|
|
10072
|
+
this.hostQuestions.reset();
|
|
10073
|
+
this.stopPendingPolling();
|
|
9560
10074
|
this.admissionPending = false;
|
|
9561
10075
|
this.policyReady = false;
|
|
9562
10076
|
}
|
|
@@ -9598,12 +10112,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9598
10112
|
const projectedSourceBundles = projectTurnSources(conversationSnapshot, sessionId, this.config.session.cwd ?? void 0);
|
|
9599
10113
|
const sourceBundles = this.hostSources.merge(projectedSourceBundles);
|
|
9600
10114
|
if (!snapshot.running) this.hostSources.refresh(sessionId, () => this.publish());
|
|
10115
|
+
this.syncPendingPolling(snapshot.running === true);
|
|
9601
10116
|
this.state = projectBoundSessionState({
|
|
9602
10117
|
connected,
|
|
9603
10118
|
sessionId,
|
|
9604
10119
|
sessionSnapshot: snapshot,
|
|
9605
10120
|
conversationSnapshot,
|
|
9606
10121
|
sourceBundles,
|
|
10122
|
+
approvals: this.hostApprovals.list(),
|
|
10123
|
+
questions: this.hostQuestions.list(),
|
|
9607
10124
|
author: this.accounts?.messageAuthorOf(sessionId),
|
|
9608
10125
|
operationError: this.operationError,
|
|
9609
10126
|
policyReady: this.policyReady,
|
|
@@ -9674,6 +10191,59 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9674
10191
|
emit() {
|
|
9675
10192
|
for (const listener of this.listeners) listener();
|
|
9676
10193
|
}
|
|
10194
|
+
/**
|
|
10195
|
+
* Answer a request the Host parked for this chat. The Host re-checks the
|
|
10196
|
+
* request against the chat, so an answer that lost its race is a no-op; the
|
|
10197
|
+
* refresh that follows is what the surface renders.
|
|
10198
|
+
*/
|
|
10199
|
+
async answerApproval(requestId, decision) {
|
|
10200
|
+
if (this.session === void 0) return;
|
|
10201
|
+
await this.hostApprovals.answer(String(this.session.sessionId), this.hostToken(), requestId, decision);
|
|
10202
|
+
this.publish();
|
|
10203
|
+
}
|
|
10204
|
+
/** Send the operator's answers to one parked question request. */
|
|
10205
|
+
async answerQuestion(requestId, answers) {
|
|
10206
|
+
if (this.session === void 0) return;
|
|
10207
|
+
await this.hostQuestions.answer(String(this.session.sessionId), this.hostToken(), requestId, answers);
|
|
10208
|
+
this.publish();
|
|
10209
|
+
}
|
|
10210
|
+
/** Close a parked question request without answering it. */
|
|
10211
|
+
async cancelQuestion(requestId) {
|
|
10212
|
+
if (this.session === void 0) return;
|
|
10213
|
+
await this.hostQuestions.cancel(String(this.session.sessionId), this.hostToken(), requestId);
|
|
10214
|
+
this.publish();
|
|
10215
|
+
}
|
|
10216
|
+
/**
|
|
10217
|
+
* Poll the Host for parked requests while a turn runs. A request only exists
|
|
10218
|
+
* inside an open turn, and it is Host state: polling is how the page learns
|
|
10219
|
+
* about it, and how it reappears after a reload. One timer serves both seams,
|
|
10220
|
+
* and each is polled only where the deployment answers it.
|
|
10221
|
+
*/
|
|
10222
|
+
syncPendingPolling(running) {
|
|
10223
|
+
const approvals = this.hostApprovals.available ? this.config.interaction.approvals === "interactive" : false;
|
|
10224
|
+
const questions = this.hostQuestions.available ? this.config.interaction.questions === "interactive" : false;
|
|
10225
|
+
if (!(running && (approvals || questions) && this.viewingSubagent === null && this.session !== void 0)) {
|
|
10226
|
+
this.stopPendingPolling();
|
|
10227
|
+
return;
|
|
10228
|
+
}
|
|
10229
|
+
if (this.pendingTimer !== void 0 || this.session === void 0) return;
|
|
10230
|
+
const sessionId = String(this.session.sessionId);
|
|
10231
|
+
const token = this.hostToken();
|
|
10232
|
+
const tick = () => {
|
|
10233
|
+
if (approvals) this.hostApprovals.refresh(sessionId, token, () => this.publish());
|
|
10234
|
+
if (questions) this.hostQuestions.refresh(sessionId, token, () => this.publish());
|
|
10235
|
+
};
|
|
10236
|
+
this.pendingTimer = setInterval(tick, PENDING_POLL_MS);
|
|
10237
|
+
tick();
|
|
10238
|
+
}
|
|
10239
|
+
stopPendingPolling() {
|
|
10240
|
+
if (this.pendingTimer === void 0) return;
|
|
10241
|
+
clearInterval(this.pendingTimer);
|
|
10242
|
+
this.pendingTimer = void 0;
|
|
10243
|
+
}
|
|
10244
|
+
hostToken() {
|
|
10245
|
+
return this.accounts?.token() ?? "";
|
|
10246
|
+
}
|
|
9677
10247
|
};
|
|
9678
10248
|
//#endregion
|
|
9679
10249
|
//#region src/client/settings/format.ts
|
|
@@ -10121,6 +10691,292 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10121
10691
|
});
|
|
10122
10692
|
}
|
|
10123
10693
|
//#endregion
|
|
10694
|
+
//#region src/client/components/QaApproval.tsx
|
|
10695
|
+
/**
|
|
10696
|
+
* The tool calls a composed gate parked for a person. One row per request, the
|
|
10697
|
+
* gate's own reason on top, and the two answers stock DSH offers: refuse, or
|
|
10698
|
+
* let this one call through. Nothing here decides on its own — an unanswered
|
|
10699
|
+
* request simply keeps the turn waiting.
|
|
10700
|
+
*/
|
|
10701
|
+
const QaApproval = (0, react.memo)(function QaApproval(props) {
|
|
10702
|
+
const [answering, setAnswering] = (0, react.useState)(null);
|
|
10703
|
+
const approvals = props.approvals;
|
|
10704
|
+
if (approvals.length === 0) return null;
|
|
10705
|
+
const answer = (requestId, decision) => {
|
|
10706
|
+
setAnswering(requestId);
|
|
10707
|
+
props.onAnswer(requestId, decision).finally(() => {
|
|
10708
|
+
setAnswering((current) => current === requestId ? null : current);
|
|
10709
|
+
});
|
|
10710
|
+
};
|
|
10711
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10712
|
+
className: "dsh-qa-approvals",
|
|
10713
|
+
"aria-label": "Запросы на одобрение",
|
|
10714
|
+
children: approvals.map((approval) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
10715
|
+
className: "dsh-qa-approval",
|
|
10716
|
+
"aria-live": "polite",
|
|
10717
|
+
children: [
|
|
10718
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
10719
|
+
className: "dsh-qa-approval__strip",
|
|
10720
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10721
|
+
className: "dsh-qa-approval__dot",
|
|
10722
|
+
"aria-hidden": "true"
|
|
10723
|
+
}), "Ожидает одобрения"]
|
|
10724
|
+
}),
|
|
10725
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10726
|
+
className: "dsh-qa-approval__reason",
|
|
10727
|
+
children: approval.reason ?? `Инструмент «${approval.toolName}» запрашивает разрешение.`
|
|
10728
|
+
}),
|
|
10729
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
10730
|
+
className: "dsh-qa-approval__tool",
|
|
10731
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: approval.toolName }), approval.delegated ? " · запросил субагент" : ""]
|
|
10732
|
+
}),
|
|
10733
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10734
|
+
className: "dsh-qa-approval__actions",
|
|
10735
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10736
|
+
type: "button",
|
|
10737
|
+
className: "dsh-qa-approval__button",
|
|
10738
|
+
disabled: answering === approval.id,
|
|
10739
|
+
onClick: () => answer(approval.id, "rejected"),
|
|
10740
|
+
children: "Отклонить"
|
|
10741
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10742
|
+
type: "button",
|
|
10743
|
+
className: "dsh-qa-approval__button dsh-qa-approval__button--primary",
|
|
10744
|
+
disabled: answering === approval.id,
|
|
10745
|
+
onClick: () => answer(approval.id, "allowed-once"),
|
|
10746
|
+
children: "Разрешить один раз"
|
|
10747
|
+
})]
|
|
10748
|
+
})
|
|
10749
|
+
]
|
|
10750
|
+
}, approval.id))
|
|
10751
|
+
});
|
|
10752
|
+
});
|
|
10753
|
+
//#endregion
|
|
10754
|
+
//#region src/client/components/QaQuestions.tsx
|
|
10755
|
+
const NO_DRAFT = {
|
|
10756
|
+
selected: [],
|
|
10757
|
+
custom: "",
|
|
10758
|
+
skipped: false
|
|
10759
|
+
};
|
|
10760
|
+
const isAnswered = (draft) => draft.skipped || draft.selected.length > 0 || draft.custom.trim() !== "";
|
|
10761
|
+
/**
|
|
10762
|
+
* Encode one question's draft the way the harness decodes it (its
|
|
10763
|
+
* user-questions README): a skipped question carries no selection, free text
|
|
10764
|
+
* overrides the choice in a single-select, and accompanies it in a
|
|
10765
|
+
* multi-select.
|
|
10766
|
+
*/
|
|
10767
|
+
function encodeAnswer(question, draft) {
|
|
10768
|
+
if (draft.skipped) return {
|
|
10769
|
+
id: question.id,
|
|
10770
|
+
selected: []
|
|
10771
|
+
};
|
|
10772
|
+
const custom = draft.custom.trim();
|
|
10773
|
+
if (question.multiSelect) return {
|
|
10774
|
+
id: question.id,
|
|
10775
|
+
selected: [...draft.selected],
|
|
10776
|
+
...custom === "" ? {} : { custom }
|
|
10777
|
+
};
|
|
10778
|
+
if (custom !== "") return {
|
|
10779
|
+
id: question.id,
|
|
10780
|
+
selected: [],
|
|
10781
|
+
custom
|
|
10782
|
+
};
|
|
10783
|
+
return {
|
|
10784
|
+
id: question.id,
|
|
10785
|
+
selected: [...draft.selected]
|
|
10786
|
+
};
|
|
10787
|
+
}
|
|
10788
|
+
/**
|
|
10789
|
+
* One parked `ask_user_question` request: the operator's answers, a question at
|
|
10790
|
+
* a time, with a pager when the model asked more than one thing at once.
|
|
10791
|
+
*/
|
|
10792
|
+
function QaQuestionForm({ request, onAnswer, onCancel }) {
|
|
10793
|
+
const [index, setIndex] = (0, react.useState)(0);
|
|
10794
|
+
const [drafts, setDrafts] = (0, react.useState)({});
|
|
10795
|
+
const [busy, setBusy] = (0, react.useState)(null);
|
|
10796
|
+
const [failure, setFailure] = (0, react.useState)(null);
|
|
10797
|
+
const questions = request.questions;
|
|
10798
|
+
const question = questions[Math.min(index, questions.length - 1)];
|
|
10799
|
+
if (question === void 0) return null;
|
|
10800
|
+
const draft = drafts[question.id] ?? NO_DRAFT;
|
|
10801
|
+
const last = index === questions.length - 1;
|
|
10802
|
+
const complete = questions.every((item) => isAnswered(drafts[item.id] ?? NO_DRAFT));
|
|
10803
|
+
const edit = (next) => {
|
|
10804
|
+
setDrafts((current) => ({
|
|
10805
|
+
...current,
|
|
10806
|
+
[question.id]: next
|
|
10807
|
+
}));
|
|
10808
|
+
};
|
|
10809
|
+
const advance = () => {
|
|
10810
|
+
setIndex((current) => Math.min(current + 1, questions.length - 1));
|
|
10811
|
+
};
|
|
10812
|
+
const select = (label) => {
|
|
10813
|
+
if (question.multiSelect) {
|
|
10814
|
+
const selected = draft.selected.includes(label) ? draft.selected.filter((item) => item !== label) : [...draft.selected, label];
|
|
10815
|
+
edit({
|
|
10816
|
+
...draft,
|
|
10817
|
+
selected
|
|
10818
|
+
});
|
|
10819
|
+
return;
|
|
10820
|
+
}
|
|
10821
|
+
edit({
|
|
10822
|
+
...draft,
|
|
10823
|
+
selected: [label]
|
|
10824
|
+
});
|
|
10825
|
+
if (!last) advance();
|
|
10826
|
+
};
|
|
10827
|
+
const skip = () => {
|
|
10828
|
+
edit({
|
|
10829
|
+
...draft,
|
|
10830
|
+
selected: [],
|
|
10831
|
+
custom: "",
|
|
10832
|
+
skipped: true
|
|
10833
|
+
});
|
|
10834
|
+
if (!last) advance();
|
|
10835
|
+
};
|
|
10836
|
+
const submit = () => {
|
|
10837
|
+
setBusy("answer");
|
|
10838
|
+
setFailure(null);
|
|
10839
|
+
onAnswer(request.id, questions.map((item) => encodeAnswer(item, drafts[item.id] ?? NO_DRAFT))).catch(() => setFailure("Не удалось отправить ответ.")).finally(() => setBusy(null));
|
|
10840
|
+
};
|
|
10841
|
+
const cancel = () => {
|
|
10842
|
+
setBusy("cancel");
|
|
10843
|
+
setFailure(null);
|
|
10844
|
+
onCancel(request.id).catch(() => setFailure("Не удалось закрыть вопрос.")).finally(() => setBusy(null));
|
|
10845
|
+
};
|
|
10846
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
10847
|
+
className: "dsh-qa-question",
|
|
10848
|
+
"aria-live": "polite",
|
|
10849
|
+
children: [
|
|
10850
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
10851
|
+
className: "dsh-qa-question__strip",
|
|
10852
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10853
|
+
className: "dsh-qa-question__dot",
|
|
10854
|
+
"aria-hidden": "true"
|
|
10855
|
+
}), questions.length > 1 ? `Требуется ответ · вопрос ${index + 1} из ${questions.length}` : "Требуется ответ"]
|
|
10856
|
+
}),
|
|
10857
|
+
question.header === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10858
|
+
className: "dsh-qa-question__header",
|
|
10859
|
+
children: question.header
|
|
10860
|
+
}),
|
|
10861
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
10862
|
+
className: "dsh-qa-question__fieldset",
|
|
10863
|
+
disabled: busy !== null,
|
|
10864
|
+
children: [
|
|
10865
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("legend", {
|
|
10866
|
+
className: "dsh-qa-question__text",
|
|
10867
|
+
children: question.question
|
|
10868
|
+
}),
|
|
10869
|
+
question.detail === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10870
|
+
className: "dsh-qa-question__detail",
|
|
10871
|
+
children: question.detail
|
|
10872
|
+
}),
|
|
10873
|
+
question.options.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10874
|
+
className: "dsh-qa-question__options",
|
|
10875
|
+
role: question.multiSelect ? "group" : "radiogroup",
|
|
10876
|
+
"aria-label": question.question,
|
|
10877
|
+
children: question.options.map((option) => {
|
|
10878
|
+
const checked = draft.selected.includes(option.label);
|
|
10879
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
10880
|
+
className: "dsh-qa-question__option",
|
|
10881
|
+
"data-checked": checked ? "true" : "false",
|
|
10882
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
10883
|
+
type: question.multiSelect ? "checkbox" : "radio",
|
|
10884
|
+
name: `qa-question-${request.id}-${question.id}`,
|
|
10885
|
+
checked,
|
|
10886
|
+
onChange: () => select(option.label)
|
|
10887
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10888
|
+
className: "dsh-qa-question__option-text",
|
|
10889
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10890
|
+
className: "dsh-qa-question__option-label",
|
|
10891
|
+
children: option.label
|
|
10892
|
+
}), option.description === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10893
|
+
className: "dsh-qa-question__option-description",
|
|
10894
|
+
children: option.description
|
|
10895
|
+
})]
|
|
10896
|
+
})]
|
|
10897
|
+
}, option.label);
|
|
10898
|
+
})
|
|
10899
|
+
}),
|
|
10900
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
10901
|
+
className: "dsh-qa-question__custom",
|
|
10902
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Свой ответ" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
10903
|
+
rows: 2,
|
|
10904
|
+
value: draft.custom,
|
|
10905
|
+
placeholder: "Напечатайте ответ…",
|
|
10906
|
+
onChange: (event) => edit({
|
|
10907
|
+
...draft,
|
|
10908
|
+
custom: event.target.value,
|
|
10909
|
+
skipped: false
|
|
10910
|
+
})
|
|
10911
|
+
})]
|
|
10912
|
+
})
|
|
10913
|
+
]
|
|
10914
|
+
}),
|
|
10915
|
+
failure === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10916
|
+
className: "dsh-qa-question__error",
|
|
10917
|
+
role: "alert",
|
|
10918
|
+
children: failure
|
|
10919
|
+
}),
|
|
10920
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10921
|
+
className: "dsh-qa-question__actions",
|
|
10922
|
+
children: [
|
|
10923
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10924
|
+
type: "button",
|
|
10925
|
+
className: "dsh-qa-question__button",
|
|
10926
|
+
disabled: busy !== null,
|
|
10927
|
+
onClick: cancel,
|
|
10928
|
+
children: "Отмена"
|
|
10929
|
+
}),
|
|
10930
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10931
|
+
type: "button",
|
|
10932
|
+
className: "dsh-qa-question__button",
|
|
10933
|
+
disabled: busy !== null || draft.skipped,
|
|
10934
|
+
onClick: skip,
|
|
10935
|
+
children: "Пропустить"
|
|
10936
|
+
}),
|
|
10937
|
+
index > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10938
|
+
type: "button",
|
|
10939
|
+
className: "dsh-qa-question__button",
|
|
10940
|
+
disabled: busy !== null,
|
|
10941
|
+
onClick: () => setIndex((current) => Math.max(current - 1, 0)),
|
|
10942
|
+
children: "Назад"
|
|
10943
|
+
}) : null,
|
|
10944
|
+
last ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10945
|
+
type: "button",
|
|
10946
|
+
className: "dsh-qa-question__button dsh-qa-question__button--primary",
|
|
10947
|
+
disabled: busy !== null || !complete,
|
|
10948
|
+
onClick: submit,
|
|
10949
|
+
children: "Отправить"
|
|
10950
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10951
|
+
type: "button",
|
|
10952
|
+
className: "dsh-qa-question__button dsh-qa-question__button--primary",
|
|
10953
|
+
disabled: busy !== null || !isAnswered(draft),
|
|
10954
|
+
onClick: advance,
|
|
10955
|
+
children: "Далее"
|
|
10956
|
+
})
|
|
10957
|
+
]
|
|
10958
|
+
})
|
|
10959
|
+
]
|
|
10960
|
+
});
|
|
10961
|
+
}
|
|
10962
|
+
/**
|
|
10963
|
+
* The questions a running turn waits on. Answers are the operator's own: the
|
|
10964
|
+
* form refuses to submit a question left blank, and a question explicitly
|
|
10965
|
+
* skipped is reported as skipped rather than answered by guesswork.
|
|
10966
|
+
*/
|
|
10967
|
+
const QaQuestions = (0, react.memo)(function QaQuestions(props) {
|
|
10968
|
+
if (props.questions.length === 0) return null;
|
|
10969
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10970
|
+
className: "dsh-qa-questions",
|
|
10971
|
+
"aria-label": "Вопросы помощника",
|
|
10972
|
+
children: props.questions.map((request) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaQuestionForm, {
|
|
10973
|
+
request,
|
|
10974
|
+
onAnswer: props.onAnswer,
|
|
10975
|
+
onCancel: props.onCancel
|
|
10976
|
+
}, request.id))
|
|
10977
|
+
});
|
|
10978
|
+
});
|
|
10979
|
+
//#endregion
|
|
10124
10980
|
//#region src/client/components/QaFileAttachment.tsx
|
|
10125
10981
|
/** Uppercase extension badge; a name without one falls back to a paper glyph. */
|
|
10126
10982
|
function badgeText(name) {
|
|
@@ -11842,8 +12698,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11842
12698
|
}
|
|
11843
12699
|
//#endregion
|
|
11844
12700
|
//#region src/client/components/QaChangelog.tsx
|
|
11845
|
-
const QA_VERSION = "0.
|
|
12701
|
+
const QA_VERSION = "0.5.0";
|
|
11846
12702
|
const QA_CHANGELOG = [
|
|
12703
|
+
{
|
|
12704
|
+
version: "0.5.0",
|
|
12705
|
+
date: "2026-09-14",
|
|
12706
|
+
sections: [{
|
|
12707
|
+
title: "Новое",
|
|
12708
|
+
items: [
|
|
12709
|
+
"Одобрения можно давать прямо в QA-интерфейсе: если композитная проверка (классификатор безопасности, правило-хук) помечает вызов инструмента как требующий подтверждения, а настройка interaction.approvals стоит в режиме interactive, вызов встаёт на паузу и появляется карточкой над полем ввода — с причиной проверки, именем инструмента и двумя ответами, «Отклонить» и «Разрешить один раз». Запрос хранится на сервере, поэтому переживает перезагрузку страницы, а неотвеченный закрывается вместе с остановкой хода. По умолчанию (blocked) вызов отклоняется с причиной, и ни один режим не одобряет ничего без человека.",
|
|
12710
|
+
"Вопросы модели отвечаются там же: interaction.questions в режиме interactive показывает ask_user_question формой над полем ввода — вопросы листаются по одному, с вариантами одиночного и множественного выбора, свободным ответом и явными «Пропустить» и «Отменить». Пропущенный вопрос передаётся модели как пропущенный, а не выдуманный; без этой настройки запрос отклоняется с причиной, которую модель может отработать.",
|
|
12711
|
+
"Модели разрешено сообщать источники, которые не сводятся к документу: настройка sources.subagents.validateReportedSources снимает сразу две проверки — отчёт принимается и от самого QA-агента, а не только от делегированного прогона, а запись без адреса сохраняет свой тип, заголовок и сниппет вместо того, чтобы отбрасываться. Ссылка, которую не удалось разобрать, сохраняется как есть, а отсутствующий заголовок заменяется последним сегментом пути. Тумблер живёт в карточке настроек, раздел «Источники», подраздел «Субагенты».",
|
|
12712
|
+
"Пароль аккаунта сбрасывается из командной строки: qa-accounts set-password <почта> --password-stdin. Аккаунт сохраняет свой идентификатор, профиль и все свои чаты, а прежний пароль и выданные под ним токены перестают работать, поэтому сброс закрывает и подозрение на утечку. Пароль читается из стандартного ввода одной строкой и не остаётся в истории команд.",
|
|
12713
|
+
"Общие каталоги только для чтения: lockdown.sharedReadOnlyRoots перечисляет абсолютные пути, доступные читающим инструментам (read, read_image, glob, grep и просмотр в str_replace_editor) поверх личного каталога аккаунта. Записи при этом остаются внутри каталога пользователя, и доступа к инструменту, которого нет в белом списке, это не даёт."
|
|
12714
|
+
]
|
|
12715
|
+
}, {
|
|
12716
|
+
title: "Исправления",
|
|
12717
|
+
items: [
|
|
12718
|
+
"Чат, начатый до перезапуска хоста, снова открывается: поверхность сама будит агента сессии, если хост его ещё не собрал. Раньше такой чат отвечал «Не удалось открыть этот чат.», а восстановление при загрузке бросало его и поднимало новый сеанс.",
|
|
12719
|
+
"Инструменты чтения Git больше не отклоняются сторожем путей по имени: границу репозитория держит отдельно настроенный Git-плагин.",
|
|
12720
|
+
"Заблокированное одобрение больше не выдаётся за отказ пользователя: вызов отклоняется с собственной причиной поверхности, а не с формулировкой «пользователь отклонил»."
|
|
12721
|
+
]
|
|
12722
|
+
}]
|
|
12723
|
+
},
|
|
11847
12724
|
{
|
|
11848
12725
|
version: "0.4.0",
|
|
11849
12726
|
date: "2026-09-13",
|
|
@@ -11963,7 +12840,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11963
12840
|
className: "dsh-qa-changelog__date",
|
|
11964
12841
|
children: entry.date
|
|
11965
12842
|
}),
|
|
11966
|
-
entry.version === "0.
|
|
12843
|
+
entry.version === "0.5.0" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11967
12844
|
className: "dsh-qa-changelog__current",
|
|
11968
12845
|
children: "текущая"
|
|
11969
12846
|
}) : null
|
|
@@ -13644,6 +14521,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13644
14521
|
secureSession: props.secureSession,
|
|
13645
14522
|
createSession: props.createSession,
|
|
13646
14523
|
sourceApi: props.sourceApi,
|
|
14524
|
+
...props.approvalApi === void 0 ? {} : { approvalApi: props.approvalApi },
|
|
14525
|
+
...props.questionApi === void 0 ? {} : { questionApi: props.questionApi },
|
|
13647
14526
|
config,
|
|
13648
14527
|
storage: window.localStorage,
|
|
13649
14528
|
accounts: facade,
|
|
@@ -13661,6 +14540,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13661
14540
|
props.connection,
|
|
13662
14541
|
props.createSession,
|
|
13663
14542
|
props.fileUpload,
|
|
14543
|
+
props.approvalApi,
|
|
14544
|
+
props.questionApi,
|
|
13664
14545
|
props.secureSession,
|
|
13665
14546
|
props.sourceApi,
|
|
13666
14547
|
props.sessions,
|
|
@@ -13711,6 +14592,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13711
14592
|
}, [controller]);
|
|
13712
14593
|
const handleSend = (0, react.useCallback)((text, attachments) => controller?.send(text, attachments) ?? Promise.resolve(false), [controller]);
|
|
13713
14594
|
const handleStop = (0, react.useCallback)(() => controller?.stop() ?? Promise.resolve(), [controller]);
|
|
14595
|
+
const handleAnswerApproval = (0, react.useCallback)((requestId, decision) => controller?.answerApproval(requestId, decision) ?? Promise.resolve(), [controller]);
|
|
14596
|
+
const handleAnswerQuestion = (0, react.useCallback)((requestId, answers) => controller?.answerQuestion(requestId, answers) ?? Promise.resolve(), [controller]);
|
|
14597
|
+
const handleCancelQuestion = (0, react.useCallback)((requestId) => controller?.cancelQuestion(requestId) ?? Promise.resolve(), [controller]);
|
|
13714
14598
|
const handleCloseSubagent = (0, react.useCallback)(() => {
|
|
13715
14599
|
controller?.closeSubagent();
|
|
13716
14600
|
}, [controller]);
|
|
@@ -13972,31 +14856,43 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13972
14856
|
className: "dsh-qa-footer",
|
|
13973
14857
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13974
14858
|
className: "dsh-qa-footer__inner",
|
|
13975
|
-
children: [
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
}
|
|
13999
|
-
|
|
14859
|
+
children: [
|
|
14860
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaApproval, {
|
|
14861
|
+
approvals: state.approvals,
|
|
14862
|
+
onAnswer: handleAnswerApproval
|
|
14863
|
+
}),
|
|
14864
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaQuestions, {
|
|
14865
|
+
questions: state.questions,
|
|
14866
|
+
onAnswer: handleAnswerQuestion,
|
|
14867
|
+
onCancel: handleCancelQuestion
|
|
14868
|
+
}),
|
|
14869
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaComposer, {
|
|
14870
|
+
placeholder: config.branding.placeholder,
|
|
14871
|
+
quickQuestions: empty ? config.suggestedQuestions : NO_QUESTIONS,
|
|
14872
|
+
canSend: state.canSend,
|
|
14873
|
+
canStop: state.canStop,
|
|
14874
|
+
running: state.phase === "running",
|
|
14875
|
+
showStop: config.ui.showStop,
|
|
14876
|
+
status,
|
|
14877
|
+
attachments: pendingAttachments,
|
|
14878
|
+
limits,
|
|
14879
|
+
onAttachmentsChange: setPendingAttachments,
|
|
14880
|
+
onSend: handleSend,
|
|
14881
|
+
onStop: handleStop
|
|
14882
|
+
}, state.sessionId ?? "draft"),
|
|
14883
|
+
config.branding.disclaimer === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
14884
|
+
className: "dsh-qa-footer__disclaimer",
|
|
14885
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
14886
|
+
viewBox: "0 0 16 16",
|
|
14887
|
+
"aria-hidden": "true",
|
|
14888
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
14889
|
+
cx: "8",
|
|
14890
|
+
cy: "8",
|
|
14891
|
+
r: "5.75"
|
|
14892
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8 7.25v3.5m0-5.25v.5" })]
|
|
14893
|
+
}), config.branding.disclaimer]
|
|
14894
|
+
})
|
|
14895
|
+
]
|
|
14000
14896
|
})
|
|
14001
14897
|
}),
|
|
14002
14898
|
!empty ? ["left", "right"].map((side) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaWidthHandle, {
|
|
@@ -14482,6 +15378,48 @@ a.dsh-qa-srcref:hover,button.dsh-qa-srcref:hover{border-color:var(--dsw-alias-la
|
|
|
14482
15378
|
.dsh-qa-work-tool__body pre{max-height:260px;overflow:auto;margin:0;padding:7px 10px 10px;color:var(--dsw-alias-label-secondary);background:transparent;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px;line-height:19px;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
14483
15379
|
.dsh-qa-error{display:flex;align-items:center;justify-content:center;gap:10px;margin:16px auto;padding:10px 12px;border:1px solid var(--dsh-qa-error);border-radius:10px;color:var(--dsw-alias-label-primary);font-size:13px}
|
|
14484
15380
|
.dsh-qa-error button{border:0;background:transparent;color:var(--dsh-qa-accent);font:inherit;font-weight:600;cursor:pointer}
|
|
15381
|
+
.dsh-qa-approvals{display:flex;flex-direction:column;gap:8px;width:100%;margin-bottom:10px}
|
|
15382
|
+
.dsh-qa-approval{padding:12px 14px;border:1px solid var(--dsh-qa-warning30);border-radius:12px;background:var(--dsh-qa-warning10)}
|
|
15383
|
+
.dsh-qa-approval__strip{display:flex;align-items:center;gap:7px;margin:0 0 8px;color:var(--dsh-qa-warning-hover);font-size:12px;font-weight:600;line-height:16px}
|
|
15384
|
+
.dsh-qa-approval__dot{width:7px;height:7px;flex:none;border-radius:999px;background:var(--dsh-qa-warning)}
|
|
15385
|
+
.dsh-qa-approval__reason{margin:0;color:var(--dsw-alias-label-primary);font-size:13px;line-height:19px;overflow-wrap:anywhere}
|
|
15386
|
+
.dsh-qa-approval__tool{margin:6px 0 0;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}
|
|
15387
|
+
.dsh-qa-approval__tool code{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
|
|
15388
|
+
.dsh-qa-approval__actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}
|
|
15389
|
+
.dsh-qa-approval__button{appearance:none;padding:7px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;font-weight:600;line-height:18px;cursor:pointer}
|
|
15390
|
+
.dsh-qa-approval__button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
15391
|
+
.dsh-qa-approval__button:disabled{opacity:.5;cursor:default}
|
|
15392
|
+
.dsh-qa-approval__button:focus-visible{outline:2px solid var(--dsh-qa-accent);outline-offset:1px}
|
|
15393
|
+
.dsh-qa-approval__button--primary{border-color:transparent;background:var(--dsh-qa-accent);color:var(--dsh-qa-accent-contrast)}
|
|
15394
|
+
.dsh-qa-approval__button--primary:hover:not(:disabled){background:var(--dsh-qa-accent-hover)}
|
|
15395
|
+
.dsh-qa-questions{display:flex;flex-direction:column;gap:8px;width:100%;margin-bottom:10px}
|
|
15396
|
+
.dsh-qa-question{padding:12px 14px;border:1px solid var(--dsh-qa-info30);border-radius:12px;background:var(--dsh-qa-info10)}
|
|
15397
|
+
.dsh-qa-question__strip{display:flex;align-items:center;gap:7px;margin:0 0 8px;color:var(--dsh-qa-info);font-size:12px;font-weight:600;line-height:16px}
|
|
15398
|
+
.dsh-qa-question__dot{width:7px;height:7px;flex:none;border-radius:999px;background:var(--dsh-qa-info)}
|
|
15399
|
+
.dsh-qa-question__header{margin:0 0 4px;color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:600;line-height:16px;text-transform:uppercase;letter-spacing:.04em}
|
|
15400
|
+
.dsh-qa-question__fieldset{display:flex;flex-direction:column;gap:8px;min-width:0;margin:0;padding:0;border:0}
|
|
15401
|
+
.dsh-qa-question__text{margin:0;padding:0;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:19px;overflow-wrap:anywhere}
|
|
15402
|
+
.dsh-qa-question__detail{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;white-space:pre-wrap;overflow-wrap:anywhere;max-height:220px;overflow:auto}
|
|
15403
|
+
.dsh-qa-question__options{display:flex;flex-direction:column;gap:6px}
|
|
15404
|
+
.dsh-qa-question__option{display:flex;align-items:flex-start;gap:8px;padding:7px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);cursor:pointer}
|
|
15405
|
+
.dsh-qa-question__option[data-checked="true"]{border-color:var(--dsh-qa-info);background:color-mix(in srgb,var(--dsh-qa-info) 8%,var(--dsw-alias-bg-layer-2))}
|
|
15406
|
+
.dsh-qa-question__option input{margin:2px 0 0;accent-color:var(--dsh-qa-info)}
|
|
15407
|
+
.dsh-qa-question__option-text{display:flex;flex-direction:column;gap:2px;min-width:0}
|
|
15408
|
+
.dsh-qa-question__option-label{color:var(--dsw-alias-label-primary);font-size:13px;line-height:18px;overflow-wrap:anywhere}
|
|
15409
|
+
.dsh-qa-question__option-description{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px;overflow-wrap:anywhere}
|
|
15410
|
+
.dsh-qa-question__custom{display:flex;flex-direction:column;gap:4px}
|
|
15411
|
+
.dsh-qa-question__custom span{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}
|
|
15412
|
+
.dsh-qa-question__custom textarea{width:100%;resize:vertical;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:19px}
|
|
15413
|
+
.dsh-qa-question__custom textarea:focus-visible{outline:2px solid var(--dsh-qa-info);outline-offset:1px}
|
|
15414
|
+
.dsh-qa-question__fieldset:disabled{opacity:.6}
|
|
15415
|
+
.dsh-qa-question__error{margin:0;color:var(--dsh-qa-error);font-size:12px;line-height:17px}
|
|
15416
|
+
.dsh-qa-question__actions{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}
|
|
15417
|
+
.dsh-qa-question__button{appearance:none;padding:7px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;font-weight:600;line-height:18px;cursor:pointer}
|
|
15418
|
+
.dsh-qa-question__button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
15419
|
+
.dsh-qa-question__button:disabled{opacity:.5;cursor:default}
|
|
15420
|
+
.dsh-qa-question__button:focus-visible{outline:2px solid var(--dsh-qa-info);outline-offset:1px}
|
|
15421
|
+
.dsh-qa-question__button--primary{border-color:transparent;background:var(--dsh-qa-accent);color:var(--dsh-qa-accent-contrast)}
|
|
15422
|
+
.dsh-qa-question__button--primary:hover:not(:disabled){background:var(--dsh-qa-accent-hover)}
|
|
14485
15423
|
.dsh-qa-footer{position:relative;flex:none;padding:28px 16px max(12px,env(safe-area-inset-bottom));background:linear-gradient(180deg,color-mix(in srgb,var(--dsw-alias-bg-base) 0%,transparent) 0,var(--dsw-alias-bg-base) 28px)}
|
|
14486
15424
|
.dsh-qa-footer__inner{width:100%;max-width:var(--dsh-qa-content-width);margin:0 auto}
|
|
14487
15425
|
.dsh-qa-composer-wrap{display:flex;flex-direction:column;gap:10px;width:100%}
|
|
@@ -16159,6 +17097,19 @@ a.dsh-qa-srcref:hover,button.dsh-qa-srcref:hover{border-color:var(--dsw-alias-la
|
|
|
16159
17097
|
"markIncompleteOpaqueRuns"
|
|
16160
17098
|
], value);
|
|
16161
17099
|
}
|
|
17100
|
+
}),
|
|
17101
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
17102
|
+
checked: sources?.subagents?.validateReportedSources ?? true,
|
|
17103
|
+
disabled: blocked,
|
|
17104
|
+
label: "Проверять источники из отчёта",
|
|
17105
|
+
hint: "С проверкой принимается только источник с путём или адресом из делегированного прогона. Без неё записывается и «факт» без адреса, и отчёт самого помощника.",
|
|
17106
|
+
onChange: (value) => {
|
|
17107
|
+
props.write([
|
|
17108
|
+
"sources",
|
|
17109
|
+
"subagents",
|
|
17110
|
+
"validateReportedSources"
|
|
17111
|
+
], value);
|
|
17112
|
+
}
|
|
16162
17113
|
})
|
|
16163
17114
|
]
|
|
16164
17115
|
})]
|
|
@@ -16548,6 +17499,15 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
16548
17499
|
sources: (token, sessionId) => policyRemote.sources(token, sessionId),
|
|
16549
17500
|
readSourceFile: (token, sessionId, sourcePath) => policyRemote.readSourceFile(token, sessionId, sourcePath)
|
|
16550
17501
|
};
|
|
17502
|
+
const questionApi = {
|
|
17503
|
+
pendingQuestions: (token, sessionId) => policyRemote.pendingQuestions(token, sessionId),
|
|
17504
|
+
answerQuestion: (token, sessionId, requestId, answers) => policyRemote.answerQuestion(token, sessionId, requestId, answers),
|
|
17505
|
+
cancelQuestion: (token, sessionId, requestId) => policyRemote.cancelQuestion(token, sessionId, requestId)
|
|
17506
|
+
};
|
|
17507
|
+
const approvalApi = {
|
|
17508
|
+
pendingApprovals: (token, sessionId) => policyRemote.pendingApprovals(token, sessionId),
|
|
17509
|
+
answerApproval: (token, sessionId, requestId, decision) => policyRemote.answerApproval(token, sessionId, requestId, decision)
|
|
17510
|
+
};
|
|
16551
17511
|
const accounts = new QaAccountsController({
|
|
16552
17512
|
remote: policyRemote,
|
|
16553
17513
|
storage: window.localStorage,
|
|
@@ -16660,6 +17620,8 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
16660
17620
|
secureSession,
|
|
16661
17621
|
createSession: (token) => policyRemote.createSession(token),
|
|
16662
17622
|
sourceApi,
|
|
17623
|
+
approvalApi,
|
|
17624
|
+
questionApi,
|
|
16663
17625
|
accounts,
|
|
16664
17626
|
fileUpload: () => ctx.get("fileUpload")
|
|
16665
17627
|
})
|