forkit-connect 0.1.10 → 0.1.12
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/dist/cli.js +31 -18
- package/dist/launcher.js +459 -149
- package/dist/v1/service.d.ts +1 -0
- package/dist/v1/service.js +16 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -942,7 +942,7 @@ function buildInteractiveOverviewSections(service, sessionState, accountLimits)
|
|
|
942
942
|
sections.push({
|
|
943
943
|
title: 'Inbox',
|
|
944
944
|
lines: [
|
|
945
|
-
shellLine('
|
|
945
|
+
shellLine('Private review', overview.draft_first_count),
|
|
946
946
|
shellLine('Ready to connect', otherReadyCount),
|
|
947
947
|
shellLine('Needs confirmation', overview.needs_confirmation_count),
|
|
948
948
|
shellLine('Connected', overview.connected_count),
|
|
@@ -972,7 +972,7 @@ function buildInteractiveOverviewSections(service, sessionState, accountLimits)
|
|
|
972
972
|
lines: [
|
|
973
973
|
shellLine('Workspace', formatScopeReferenceLabel(preparedWorkspace || null, 'workspace')),
|
|
974
974
|
shellLine('Project', formatScopeReferenceLabel(preparedProject || null, 'project')),
|
|
975
|
-
shellLine('
|
|
975
|
+
shellLine('Private review', overview.draft_first_count),
|
|
976
976
|
shellLine('Ready to connect', otherReadyCount),
|
|
977
977
|
shellLine('Needs confirmation', overview.needs_confirmation_count),
|
|
978
978
|
],
|
|
@@ -1433,7 +1433,7 @@ function formatSmartInboxActionLabel(item) {
|
|
|
1433
1433
|
if (item.item_type === 'model'
|
|
1434
1434
|
&& item.recommended_action === 'create_passport_draft'
|
|
1435
1435
|
&& String(item.details_received_automatically.registration_flow_state || '').trim() === 'private_draft_required') {
|
|
1436
|
-
return '
|
|
1436
|
+
return 'Continue Registration';
|
|
1437
1437
|
}
|
|
1438
1438
|
return formatSmartInboxActionValue(item.recommended_action, item.item_type, String(item.details_received_automatically.connectable_model_name || '').trim());
|
|
1439
1439
|
}
|
|
@@ -1488,7 +1488,7 @@ function printPublicStatusOverview(status) {
|
|
|
1488
1488
|
console.log(`- scope=${status.workspace_id && status.project_id ? `${status.workspace_id} / ${status.project_id}` : 'not selected'}`);
|
|
1489
1489
|
console.log(`- daemon=${status.daemon_status}`);
|
|
1490
1490
|
console.log(`- local inventory=models ${status.models_discovered} · agents ${status.agents_discovered} · runtimes ${status.runtimes_discovered}`);
|
|
1491
|
-
console.log(`- review queue=
|
|
1491
|
+
console.log(`- review queue=private review ${status.draft_first_count} · ready ${otherReadyCount} · needs review ${status.needs_confirmation_count}`);
|
|
1492
1492
|
console.log(`- connected records=${status.connected_count}`);
|
|
1493
1493
|
console.log(`- pending runtime sync=${status.c2_sync_pending}`);
|
|
1494
1494
|
console.log(`- privacy=${status.privacy_mode}`);
|
|
@@ -2131,7 +2131,7 @@ async function run() {
|
|
|
2131
2131
|
{
|
|
2132
2132
|
title: 'Queue',
|
|
2133
2133
|
lines: [
|
|
2134
|
-
shellLine('
|
|
2134
|
+
shellLine('Private review', payload.draft_first_count),
|
|
2135
2135
|
shellLine('Ready to connect', otherReadyCount),
|
|
2136
2136
|
shellLine('Needs confirmation', payload.needs_confirmation_count),
|
|
2137
2137
|
shellLine('Connected', payload.connected_count),
|
|
@@ -3892,11 +3892,11 @@ async function run() {
|
|
|
3892
3892
|
if (raw === 'MODEL_SELECTION_AMBIGUOUS')
|
|
3893
3893
|
return 'Model selection is ambiguous. Use a full discoveryHash.';
|
|
3894
3894
|
if (raw === 'DRAFT_ALREADY_EXISTS')
|
|
3895
|
-
return '
|
|
3895
|
+
return 'Registration is already started privately for this model. No duplicate registration was created.';
|
|
3896
3896
|
if (raw === 'SIMILAR_PASSPORT_EXISTS')
|
|
3897
|
-
return 'A similar or existing passport already exists in your Forkit.dev account. Review existing records before creating
|
|
3897
|
+
return 'A similar or existing passport already exists in your Forkit.dev account. Review existing records before creating another registration.';
|
|
3898
3898
|
if (raw === 'INVALID_DRAFT_VISIBILITY')
|
|
3899
|
-
return '
|
|
3899
|
+
return 'Forkit needs one private review step before this passport can finish publishing. Continue the registration from inbox/start first.';
|
|
3900
3900
|
if (raw === 'WORKSPACE_PROJECT_BINDING_REQUIRED')
|
|
3901
3901
|
return 'No governed workspace/project scope is linked yet. Select or create scope first.';
|
|
3902
3902
|
if (raw === 'DRAFT_CREATION_NOT_ALLOWED_BY_BINDING')
|
|
@@ -3907,13 +3907,13 @@ async function run() {
|
|
|
3907
3907
|
if (action === 'already_bound')
|
|
3908
3908
|
return 'Model is already connected to an existing passport.';
|
|
3909
3909
|
if (action === 'already_pending')
|
|
3910
|
-
return '
|
|
3910
|
+
return 'Registration already started privately. No duplicate registration was created.';
|
|
3911
3911
|
if (action === 'passport_registered')
|
|
3912
|
-
return 'Passport
|
|
3912
|
+
return 'Passport registered successfully.';
|
|
3913
3913
|
if (action === 'draft_created')
|
|
3914
|
-
return '
|
|
3914
|
+
return 'Private review started. Continue registration from inbox/start.';
|
|
3915
3915
|
if (action === 'draft_queued')
|
|
3916
|
-
return '
|
|
3916
|
+
return 'Registration saved locally and will sync when backend access is available.';
|
|
3917
3917
|
return action;
|
|
3918
3918
|
};
|
|
3919
3919
|
const accountLimits = await loadCliAccountLimits().catch(() => null);
|
|
@@ -3937,7 +3937,9 @@ async function run() {
|
|
|
3937
3937
|
});
|
|
3938
3938
|
const runRegisterOne = async (targetModelSelector, displayNameHint) => {
|
|
3939
3939
|
try {
|
|
3940
|
-
const result = await service.connectDetectedModel(targetModelSelector)
|
|
3940
|
+
const result = await service.connectDetectedModel(targetModelSelector, hasFlag('--draft-only')
|
|
3941
|
+
? { destination: 'draft', visibility: 'private' }
|
|
3942
|
+
: { destination: 'passport', visibility: 'public' });
|
|
3941
3943
|
return {
|
|
3942
3944
|
ok: true,
|
|
3943
3945
|
model: result.model.model,
|
|
@@ -4501,7 +4503,10 @@ async function run() {
|
|
|
4501
4503
|
return;
|
|
4502
4504
|
}
|
|
4503
4505
|
try {
|
|
4504
|
-
const result = await service.connectDetectedModel(selector
|
|
4506
|
+
const result = await service.connectDetectedModel(selector, {
|
|
4507
|
+
destination: 'passport',
|
|
4508
|
+
visibility: 'public',
|
|
4509
|
+
});
|
|
4505
4510
|
if (result.action === 'already_bound') {
|
|
4506
4511
|
console.log('Model is already bound to a Passport.');
|
|
4507
4512
|
if (result.gaid) {
|
|
@@ -4510,14 +4515,22 @@ async function run() {
|
|
|
4510
4515
|
return;
|
|
4511
4516
|
}
|
|
4512
4517
|
if (result.action === 'already_pending') {
|
|
4513
|
-
console.log('
|
|
4518
|
+
console.log('Registration already started privately for this model.');
|
|
4514
4519
|
if (result.draftId) {
|
|
4515
4520
|
console.log(`Draft ID: ${result.draftId}`);
|
|
4516
4521
|
}
|
|
4517
4522
|
return;
|
|
4518
4523
|
}
|
|
4524
|
+
if (result.action === 'passport_registered') {
|
|
4525
|
+
console.log('Passport registered successfully.');
|
|
4526
|
+
console.log(`Model: ${result.model.model}`);
|
|
4527
|
+
if (result.gaid) {
|
|
4528
|
+
console.log(`Passport GAID: ${result.gaid}`);
|
|
4529
|
+
}
|
|
4530
|
+
return;
|
|
4531
|
+
}
|
|
4519
4532
|
if (result.action === 'draft_created') {
|
|
4520
|
-
console.log('
|
|
4533
|
+
console.log('Registration started privately for review.');
|
|
4521
4534
|
console.log(`Model: ${result.model.model}`);
|
|
4522
4535
|
if (result.draftId) {
|
|
4523
4536
|
console.log(`Draft ID: ${result.draftId}`);
|
|
@@ -4527,9 +4540,9 @@ async function run() {
|
|
|
4527
4540
|
}
|
|
4528
4541
|
return;
|
|
4529
4542
|
}
|
|
4530
|
-
console.log('
|
|
4543
|
+
console.log('Registration saved locally and will sync when Forkit Connect can reach Forkit.dev.');
|
|
4531
4544
|
console.log(`Model: ${result.model.model}`);
|
|
4532
|
-
console.log('Complete login later and run scan or queue processing to
|
|
4545
|
+
console.log('Complete login later and run scan or queue processing to continue it.');
|
|
4533
4546
|
return;
|
|
4534
4547
|
}
|
|
4535
4548
|
catch (error) {
|
package/dist/launcher.js
CHANGED
|
@@ -434,7 +434,7 @@ function formatBindingStatusLabel(status) {
|
|
|
434
434
|
return { label: 'Published', meta: 'Live on Forkit.dev', tone: 'ok' };
|
|
435
435
|
}
|
|
436
436
|
if (normalized === 'pending') {
|
|
437
|
-
return { label: '
|
|
437
|
+
return { label: 'Private review', meta: 'In progress', tone: 'warn' };
|
|
438
438
|
}
|
|
439
439
|
if (normalized === 'ignored') {
|
|
440
440
|
return { label: 'Archived', meta: 'Not active locally', tone: 'muted' };
|
|
@@ -449,7 +449,7 @@ function formatPassportHistoryLabel(type) {
|
|
|
449
449
|
return { label: 'Passport linked', tone: 'ok' };
|
|
450
450
|
case 'model_draft_created':
|
|
451
451
|
case 'model_draft_synced':
|
|
452
|
-
return { label: '
|
|
452
|
+
return { label: 'Private review started', tone: 'warn' };
|
|
453
453
|
case 'passport_draft_requested':
|
|
454
454
|
case 'model_draft_queued':
|
|
455
455
|
return { label: 'Registration queued', tone: 'warn' };
|
|
@@ -538,10 +538,10 @@ function normalizeDiscoveryRegistrationFailure(message) {
|
|
|
538
538
|
if (normalized === 'INVALID_DRAFT_VISIBILITY') {
|
|
539
539
|
return {
|
|
540
540
|
code: normalized,
|
|
541
|
-
message: '
|
|
541
|
+
message: 'Forkit needs one private review step before this passport can finish publishing.',
|
|
542
542
|
nextActions: [
|
|
543
|
-
'
|
|
544
|
-
'
|
|
543
|
+
'Continue registration privately first.',
|
|
544
|
+
'Publish only after Forkit has finished the private review step.',
|
|
545
545
|
],
|
|
546
546
|
};
|
|
547
547
|
}
|
|
@@ -694,17 +694,17 @@ function buildDiscovery(service) {
|
|
|
694
694
|
actionTone = 'muted';
|
|
695
695
|
}
|
|
696
696
|
else if (draftPending) {
|
|
697
|
-
statusLabel = '
|
|
698
|
-
statusMeta = '
|
|
697
|
+
statusLabel = 'Registration in progress';
|
|
698
|
+
statusMeta = 'Forkit already started this privately. Continue it in Passports instead of starting over.';
|
|
699
699
|
statusTone = 'warn';
|
|
700
|
-
actionLabel = '
|
|
700
|
+
actionLabel = 'Continue';
|
|
701
701
|
actionTone = 'accent';
|
|
702
702
|
}
|
|
703
703
|
else if (registrationState === 'private_draft_required') {
|
|
704
|
-
statusLabel = '
|
|
705
|
-
statusMeta = registrationGuidance ?? '
|
|
704
|
+
statusLabel = 'Finish privately first';
|
|
705
|
+
statusMeta = registrationGuidance ?? 'Forkit needs one private review step before this passport can finish publishing.';
|
|
706
706
|
statusTone = 'warn';
|
|
707
|
-
actionLabel = '
|
|
707
|
+
actionLabel = 'Continue';
|
|
708
708
|
actionTone = 'accent';
|
|
709
709
|
}
|
|
710
710
|
else if (group === 'connected') {
|
|
@@ -741,6 +741,7 @@ function buildDiscovery(service) {
|
|
|
741
741
|
recommendedAction: entry.recommended_action,
|
|
742
742
|
workspaceId: entry.workspaceId,
|
|
743
743
|
projectId: entry.projectId,
|
|
744
|
+
draftId: binding?.draftId ?? null,
|
|
744
745
|
passportGaid: entry.passport_gaid,
|
|
745
746
|
matchedPassportGaid: entry.matched_passport_gaid,
|
|
746
747
|
detailSummary: verificationSummary ?? scopeSuggestion ?? matchReason,
|
|
@@ -791,10 +792,10 @@ function buildDiscovery(service) {
|
|
|
791
792
|
actionTone = 'accent';
|
|
792
793
|
}
|
|
793
794
|
else if (draftId || trackingStatus === 'draft_created') {
|
|
794
|
-
statusLabel = '
|
|
795
|
-
statusMeta = '
|
|
795
|
+
statusLabel = 'Registration in progress';
|
|
796
|
+
statusMeta = 'Forkit already started this privately. Continue it in Passports.';
|
|
796
797
|
statusTone = 'warn';
|
|
797
|
-
actionLabel = '
|
|
798
|
+
actionLabel = 'Continue';
|
|
798
799
|
actionTone = 'accent';
|
|
799
800
|
}
|
|
800
801
|
else if (group === 'connected' || linkedPassportGaid) {
|
|
@@ -835,6 +836,7 @@ function buildDiscovery(service) {
|
|
|
835
836
|
recommendedAction: entry.recommended_action,
|
|
836
837
|
workspaceId: entry.workspaceId,
|
|
837
838
|
projectId: entry.projectId,
|
|
839
|
+
draftId,
|
|
838
840
|
passportGaid: linkedPassportGaid,
|
|
839
841
|
matchedPassportGaid: entry.matched_passport_gaid,
|
|
840
842
|
detailSummary: statusMeta,
|
|
@@ -929,7 +931,7 @@ function buildDiscovery(service) {
|
|
|
929
931
|
localDetection: state.detected_runtimes.length > 0 || state.detected_models.length > 0 ? 'active' : 'attention',
|
|
930
932
|
metadataExtraction: state.detected_models.length > 0 ? 'active' : 'attention',
|
|
931
933
|
duplicateMatching: inbox.existing_passport_match_candidates.length > 0 || state.model_bindings.length > 0 ? 'active' : 'attention',
|
|
932
|
-
passportReadiness: `${draftFirstCount}
|
|
934
|
+
passportReadiness: `${draftFirstCount} private review · ${otherReadyCount} ready · ${inbox.summary.needs_confirmation_count} review · ${inbox.summary.connected_count} linked`,
|
|
933
935
|
},
|
|
934
936
|
groups: {
|
|
935
937
|
ready_to_connect: inbox.groups.ready_to_connect.length,
|
|
@@ -1799,7 +1801,9 @@ function renderLauncherHtml(launcherToken) {
|
|
|
1799
1801
|
.quick-review-chip:focus-visible,
|
|
1800
1802
|
.quick-review-primary:focus-visible,
|
|
1801
1803
|
.quick-review-options-button:focus-visible,
|
|
1804
|
+
.review-mode-button:focus-visible,
|
|
1802
1805
|
.quick-review-field select:focus-visible,
|
|
1806
|
+
.discovery-review-field select:focus-visible,
|
|
1803
1807
|
.quick-review-options-menu button:focus-visible {
|
|
1804
1808
|
outline: 2px solid rgba(157, 238, 245, 0.72);
|
|
1805
1809
|
outline-offset: 2px;
|
|
@@ -1991,12 +1995,66 @@ function renderLauncherHtml(launcherToken) {
|
|
|
1991
1995
|
gap: 10px;
|
|
1992
1996
|
}
|
|
1993
1997
|
|
|
1998
|
+
.review-mode-group {
|
|
1999
|
+
display: grid;
|
|
2000
|
+
gap: 8px;
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
.review-mode-label {
|
|
2004
|
+
font-size: 0.74rem;
|
|
2005
|
+
text-transform: uppercase;
|
|
2006
|
+
letter-spacing: 0.12em;
|
|
2007
|
+
font-weight: 700;
|
|
2008
|
+
color: rgba(241, 235, 223, 0.62);
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
.review-mode-toggle {
|
|
2012
|
+
display: inline-grid;
|
|
2013
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
2014
|
+
gap: 8px;
|
|
2015
|
+
padding: 6px;
|
|
2016
|
+
border-radius: 18px;
|
|
2017
|
+
border: 1px solid rgba(241, 235, 223, 0.08);
|
|
2018
|
+
background: rgba(255,255,255,0.04);
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
.review-mode-button {
|
|
2022
|
+
min-height: 42px;
|
|
2023
|
+
border: 1px solid rgba(241, 235, 223, 0.08);
|
|
2024
|
+
border-radius: 14px;
|
|
2025
|
+
background: transparent;
|
|
2026
|
+
color: rgba(241, 235, 223, 0.72);
|
|
2027
|
+
font: inherit;
|
|
2028
|
+
font-size: 0.88rem;
|
|
2029
|
+
font-weight: 600;
|
|
2030
|
+
cursor: pointer;
|
|
2031
|
+
transition: border-color 160ms ease, background 160ms ease, color 160ms ease, transform 160ms ease;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
.review-mode-button:hover {
|
|
2035
|
+
border-color: rgba(157, 238, 245, 0.26);
|
|
2036
|
+
color: #fff8ef;
|
|
2037
|
+
transform: translateY(-1px);
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
.review-mode-button.active {
|
|
2041
|
+
border-color: rgba(157, 238, 245, 0.34);
|
|
2042
|
+
background: linear-gradient(135deg, rgba(55, 68, 86, 0.62), rgba(31, 36, 56, 0.92));
|
|
2043
|
+
color: #fff8ef;
|
|
2044
|
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
|
|
2045
|
+
}
|
|
2046
|
+
|
|
1994
2047
|
.quick-review-scope-grid {
|
|
1995
2048
|
display: grid;
|
|
1996
2049
|
grid-template-columns: 1fr 1fr;
|
|
1997
2050
|
gap: 10px;
|
|
1998
2051
|
}
|
|
1999
2052
|
|
|
2053
|
+
.quick-review-scope-grid[hidden],
|
|
2054
|
+
.discovery-review-scope-grid[hidden] {
|
|
2055
|
+
display: none;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2000
2058
|
.quick-review-field {
|
|
2001
2059
|
display: grid;
|
|
2002
2060
|
gap: 6px;
|
|
@@ -6454,7 +6512,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
6454
6512
|
<div class="quick-review-summary-grid">
|
|
6455
6513
|
<div class="quick-review-summary-pill">
|
|
6456
6514
|
<span class="quick-review-summary-label">Action</span>
|
|
6457
|
-
<span class="quick-review-summary-value" id="quick-review-action-summary">
|
|
6515
|
+
<span class="quick-review-summary-value" id="quick-review-action-summary">Register on this account now</span>
|
|
6458
6516
|
</div>
|
|
6459
6517
|
<div class="quick-review-summary-pill">
|
|
6460
6518
|
<span class="quick-review-summary-label">Scope</span>
|
|
@@ -6463,7 +6521,14 @@ function renderLauncherHtml(launcherToken) {
|
|
|
6463
6521
|
</div>
|
|
6464
6522
|
<div class="quick-review-status" id="quick-review-status">Waiting for review.</div>
|
|
6465
6523
|
<div class="quick-review-scope" id="quick-review-scope" hidden>
|
|
6466
|
-
<div class="quick-review-
|
|
6524
|
+
<div class="review-mode-group" id="quick-review-mode">
|
|
6525
|
+
<span class="review-mode-label">Register as</span>
|
|
6526
|
+
<div class="review-mode-toggle" role="group" aria-label="Quick review registration path">
|
|
6527
|
+
<button class="review-mode-button active" id="quick-review-mode-solo" type="button" aria-pressed="true">Solo</button>
|
|
6528
|
+
<button class="review-mode-button" id="quick-review-mode-workspace" type="button" aria-pressed="false">Governed workspace</button>
|
|
6529
|
+
</div>
|
|
6530
|
+
</div>
|
|
6531
|
+
<div class="quick-review-scope-grid" id="quick-review-scope-grid" hidden>
|
|
6467
6532
|
<div class="quick-review-field">
|
|
6468
6533
|
<label for="quick-review-workspace">Workspace</label>
|
|
6469
6534
|
<select id="quick-review-workspace"></select>
|
|
@@ -6867,7 +6932,14 @@ function renderLauncherHtml(launcherToken) {
|
|
|
6867
6932
|
<p class="discovery-review-detail" id="discovery-review-detail">Registering creates or updates a Forkit Passport. Nothing is published automatically.</p>
|
|
6868
6933
|
<div class="discovery-review-status" id="discovery-review-status">Select an item to continue.</div>
|
|
6869
6934
|
<div class="discovery-review-scope" id="discovery-review-scope" hidden>
|
|
6870
|
-
<div class="discovery-review-
|
|
6935
|
+
<div class="review-mode-group" id="discovery-review-mode">
|
|
6936
|
+
<span class="review-mode-label">Register as</span>
|
|
6937
|
+
<div class="review-mode-toggle" role="group" aria-label="Discovery review registration path">
|
|
6938
|
+
<button class="review-mode-button active" id="discovery-review-mode-solo" type="button" aria-pressed="true">Solo</button>
|
|
6939
|
+
<button class="review-mode-button" id="discovery-review-mode-workspace" type="button" aria-pressed="false">Governed workspace</button>
|
|
6940
|
+
</div>
|
|
6941
|
+
</div>
|
|
6942
|
+
<div class="discovery-review-scope-grid" id="discovery-review-scope-grid" hidden>
|
|
6871
6943
|
<div class="discovery-review-field">
|
|
6872
6944
|
<label for="discovery-review-workspace">Workspace</label>
|
|
6873
6945
|
<select id="discovery-review-workspace"></select>
|
|
@@ -7252,7 +7324,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7252
7324
|
<div class="scope-modal-backdrop" id="scope-modal" hidden>
|
|
7253
7325
|
<div class="scope-modal" role="dialog" aria-modal="true" aria-labelledby="scope-modal-title">
|
|
7254
7326
|
<h3 id="scope-modal-title">Choose registration scope</h3>
|
|
7255
|
-
<p id="scope-modal-copy">
|
|
7327
|
+
<p id="scope-modal-copy">Register on your account now, or choose a governed workspace/project when you need governed ownership.</p>
|
|
7256
7328
|
<div class="scope-field-grid">
|
|
7257
7329
|
<div class="scope-field">
|
|
7258
7330
|
<label for="scope-workspace-select">Workspace</label>
|
|
@@ -7400,9 +7472,53 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7400
7472
|
return true;
|
|
7401
7473
|
}
|
|
7402
7474
|
|
|
7475
|
+
function focusPassportByDraftId(draftId, options) {
|
|
7476
|
+
const normalizedDraftId = String(draftId || '').trim();
|
|
7477
|
+
if (!normalizedDraftId) return false;
|
|
7478
|
+
const passports = latestPassports && Array.isArray(latestPassports.items) ? latestPassports.items : [];
|
|
7479
|
+
const match = passports.find((entry) => String(entry.draftId || '').trim() === normalizedDraftId);
|
|
7480
|
+
if (!match) return false;
|
|
7481
|
+
selectedPassportId = match.id;
|
|
7482
|
+
passportHistoryVisible = Boolean(options && options.showHistory);
|
|
7483
|
+
selectedWorkspaceScope = ALL_SCOPE_VALUE;
|
|
7484
|
+
selectedProjectScope = ALL_SCOPE_VALUE;
|
|
7485
|
+
renderGlobalLaunchHeaderAndCards();
|
|
7486
|
+
setView('passports', { skipRouteUpdate: true });
|
|
7487
|
+
renderPassportsRows();
|
|
7488
|
+
updateRoute('passports', { passport: match.gaid || match.id, ...(passportHistoryVisible ? { focus: 'history' } : {}) });
|
|
7489
|
+
return true;
|
|
7490
|
+
}
|
|
7491
|
+
|
|
7492
|
+
function getReviewScopeMode(workspaceId, projectId) {
|
|
7493
|
+
return String(workspaceId || '').trim() && String(projectId || '').trim() ? 'workspace' : 'solo';
|
|
7494
|
+
}
|
|
7495
|
+
|
|
7496
|
+
function isContinuationReviewItem(item) {
|
|
7497
|
+
return Boolean(item && (
|
|
7498
|
+
item.actionLabel === 'Continue'
|
|
7499
|
+
|| item.statusLabel === 'Registration in progress'
|
|
7500
|
+
|| item.statusLabel === 'Finish privately first'
|
|
7501
|
+
));
|
|
7502
|
+
}
|
|
7503
|
+
|
|
7504
|
+
function shouldOpenReviewContext(item) {
|
|
7505
|
+
return Boolean(
|
|
7506
|
+
item
|
|
7507
|
+
&& (
|
|
7508
|
+
item.kind === 'runtime'
|
|
7509
|
+
|| item.passportGaid
|
|
7510
|
+
|| item.matchedPassportGaid
|
|
7511
|
+
|| item.actionLabel === 'Open'
|
|
7512
|
+
|| item.actionLabel === 'Review'
|
|
7513
|
+
|| isContinuationReviewItem(item)
|
|
7514
|
+
)
|
|
7515
|
+
);
|
|
7516
|
+
}
|
|
7517
|
+
|
|
7403
7518
|
async function openDiscoveryContext(item) {
|
|
7404
7519
|
if (!item) return false;
|
|
7405
7520
|
const preferredPassportGaid = String(item.passportGaid || item.matchedPassportGaid || '').trim();
|
|
7521
|
+
const preferredDraftId = String(item.draftId || '').trim();
|
|
7406
7522
|
if (preferredPassportGaid) {
|
|
7407
7523
|
if (!latestPassports) {
|
|
7408
7524
|
await refreshPassports();
|
|
@@ -7411,6 +7527,14 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7411
7527
|
return true;
|
|
7412
7528
|
}
|
|
7413
7529
|
}
|
|
7530
|
+
if (preferredDraftId) {
|
|
7531
|
+
if (!latestPassports) {
|
|
7532
|
+
await refreshPassports();
|
|
7533
|
+
}
|
|
7534
|
+
if (focusPassportByDraftId(preferredDraftId, { showHistory: true })) {
|
|
7535
|
+
return true;
|
|
7536
|
+
}
|
|
7537
|
+
}
|
|
7414
7538
|
if (item.kind === 'model' || item.kind === 'agent') {
|
|
7415
7539
|
await openRegistrationScopeDialog(item);
|
|
7416
7540
|
return true;
|
|
@@ -7500,6 +7624,53 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7500
7624
|
status.className = 'quick-review-status' + (tone ? ' ' + tone : '');
|
|
7501
7625
|
}
|
|
7502
7626
|
|
|
7627
|
+
function canChooseReviewScope(item) {
|
|
7628
|
+
return Boolean(canReviewRegister(item) && !shouldOpenReviewContext(item));
|
|
7629
|
+
}
|
|
7630
|
+
|
|
7631
|
+
function getReviewRegistrationMode(prefix) {
|
|
7632
|
+
const scope = document.getElementById(prefix + '-scope');
|
|
7633
|
+
if (!scope) return 'solo';
|
|
7634
|
+
return String(scope.dataset.mode || '').trim() === 'workspace' ? 'workspace' : 'solo';
|
|
7635
|
+
}
|
|
7636
|
+
|
|
7637
|
+
function setReviewRegistrationMode(prefix, mode) {
|
|
7638
|
+
const normalized = mode === 'workspace' ? 'workspace' : 'solo';
|
|
7639
|
+
const scope = document.getElementById(prefix + '-scope');
|
|
7640
|
+
const scopeGrid = document.getElementById(prefix + '-scope-grid');
|
|
7641
|
+
if (scope) {
|
|
7642
|
+
scope.dataset.mode = normalized;
|
|
7643
|
+
}
|
|
7644
|
+
if (scopeGrid) {
|
|
7645
|
+
scopeGrid.hidden = normalized !== 'workspace';
|
|
7646
|
+
}
|
|
7647
|
+
['solo', 'workspace'].forEach((candidate) => {
|
|
7648
|
+
const button = document.getElementById(prefix + '-mode-' + candidate);
|
|
7649
|
+
if (!button) return;
|
|
7650
|
+
const active = candidate === normalized;
|
|
7651
|
+
button.classList.toggle('active', active);
|
|
7652
|
+
button.setAttribute('aria-pressed', active ? 'true' : 'false');
|
|
7653
|
+
});
|
|
7654
|
+
return normalized;
|
|
7655
|
+
}
|
|
7656
|
+
|
|
7657
|
+
function getPassiveReviewScopeSummary(item) {
|
|
7658
|
+
if (!item) return 'Review';
|
|
7659
|
+
if (item.kind === 'runtime') {
|
|
7660
|
+
return item.statusTone === 'error' ? 'Runtime fix' : 'Runtime review';
|
|
7661
|
+
}
|
|
7662
|
+
if (isContinuationReviewItem(item)) {
|
|
7663
|
+
return 'Private review';
|
|
7664
|
+
}
|
|
7665
|
+
if (item.passportGaid) {
|
|
7666
|
+
return 'Linked passport';
|
|
7667
|
+
}
|
|
7668
|
+
if (item.matchedPassportGaid) {
|
|
7669
|
+
return 'Existing passport';
|
|
7670
|
+
}
|
|
7671
|
+
return 'Full review';
|
|
7672
|
+
}
|
|
7673
|
+
|
|
7503
7674
|
function resetReviewResolutionActions(prefix) {
|
|
7504
7675
|
setReviewResolutionActions(prefix, []);
|
|
7505
7676
|
}
|
|
@@ -7514,13 +7685,14 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7514
7685
|
].map((value) => String(value || '').trim()).find(Boolean) || '';
|
|
7515
7686
|
}
|
|
7516
7687
|
|
|
7517
|
-
function getReviewPrimaryLabel(item) {
|
|
7688
|
+
function getReviewPrimaryLabel(item, scopeMode) {
|
|
7689
|
+
const effectiveScopeMode = scopeMode === 'workspace' ? 'workspace' : 'solo';
|
|
7518
7690
|
if (!item) return 'Review';
|
|
7519
7691
|
if (item.kind === 'runtime') {
|
|
7520
7692
|
return item.statusTone === 'error' ? 'Open runtime fix' : 'Open runtime review';
|
|
7521
7693
|
}
|
|
7522
|
-
if (item
|
|
7523
|
-
return '
|
|
7694
|
+
if (isContinuationReviewItem(item)) {
|
|
7695
|
+
return 'Continue registration';
|
|
7524
7696
|
}
|
|
7525
7697
|
if (item.passportGaid) {
|
|
7526
7698
|
return 'Open passport';
|
|
@@ -7534,16 +7706,17 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7534
7706
|
if (item.actionLabel === 'Open' || item.actionLabel === 'Review') {
|
|
7535
7707
|
return 'Review in context';
|
|
7536
7708
|
}
|
|
7537
|
-
return '
|
|
7709
|
+
return effectiveScopeMode === 'workspace' ? 'Register in workspace' : 'Register solo';
|
|
7538
7710
|
}
|
|
7539
7711
|
|
|
7540
|
-
function getReviewActionSummary(item) {
|
|
7712
|
+
function getReviewActionSummary(item, scopeMode) {
|
|
7713
|
+
const effectiveScopeMode = scopeMode === 'workspace' ? 'workspace' : 'solo';
|
|
7541
7714
|
if (!item) return 'Review';
|
|
7542
7715
|
if (item.kind === 'runtime') {
|
|
7543
7716
|
return item.statusTone === 'error' ? 'Resolve runtime attention' : 'Open runtime lane';
|
|
7544
7717
|
}
|
|
7545
|
-
if (item
|
|
7546
|
-
return 'Continue the
|
|
7718
|
+
if (isContinuationReviewItem(item)) {
|
|
7719
|
+
return 'Continue the private review step before this passport finishes publishing';
|
|
7547
7720
|
}
|
|
7548
7721
|
if (item.passportGaid) {
|
|
7549
7722
|
return 'Open the linked passport';
|
|
@@ -7557,7 +7730,9 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7557
7730
|
if (item.actionLabel === 'Open' || item.actionLabel === 'Review') {
|
|
7558
7731
|
return 'Open full review';
|
|
7559
7732
|
}
|
|
7560
|
-
return
|
|
7733
|
+
return effectiveScopeMode === 'workspace'
|
|
7734
|
+
? 'Register this item in the selected workspace'
|
|
7735
|
+
: 'Register this item on your account now';
|
|
7561
7736
|
}
|
|
7562
7737
|
|
|
7563
7738
|
function getReviewDetailText(item) {
|
|
@@ -7567,8 +7742,11 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7567
7742
|
? 'Runtime attention is required before linked models can keep registering cleanly.'
|
|
7568
7743
|
: 'Open runtime review to confirm health, scope, and connected models.';
|
|
7569
7744
|
}
|
|
7570
|
-
if (item.statusLabel === '
|
|
7571
|
-
return '
|
|
7745
|
+
if (item.statusLabel === 'Registration in progress') {
|
|
7746
|
+
return 'Forkit already started this registration privately. Continue it in Passports instead of creating a second record.';
|
|
7747
|
+
}
|
|
7748
|
+
if (item.statusLabel === 'Finish privately first') {
|
|
7749
|
+
return 'Forkit needs one private review step before it can publish this passport. Continue registration and finish the private step first.';
|
|
7572
7750
|
}
|
|
7573
7751
|
if (item.matchedPassportGaid && !item.passportGaid) {
|
|
7574
7752
|
return 'Forkit Connect found a matching passport. Reuse it before creating anything new.';
|
|
@@ -7608,7 +7786,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7608
7786
|
: result && result.code === 'SIMILAR_PASSPORT_EXISTS'
|
|
7609
7787
|
? 'Matching passport exists · reuse it instead of creating another'
|
|
7610
7788
|
: result && result.code === 'INVALID_DRAFT_VISIBILITY'
|
|
7611
|
-
? '
|
|
7789
|
+
? 'Private review first · continue registration privately before publishing'
|
|
7612
7790
|
: result && (result.code === 'WORKSPACE_PROJECT_BINDING_REQUIRED' || result.code === 'DRAFT_CREATION_NOT_ALLOWED_BY_BINDING')
|
|
7613
7791
|
? 'Scope required · choose workspace and project'
|
|
7614
7792
|
: null,
|
|
@@ -7728,15 +7906,19 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7728
7906
|
}
|
|
7729
7907
|
}
|
|
7730
7908
|
|
|
7731
|
-
function updateQuickReviewScopeSummary(
|
|
7909
|
+
function updateQuickReviewScopeSummary(scopeMode) {
|
|
7732
7910
|
const workspaceSelect = document.getElementById('quick-review-workspace');
|
|
7733
7911
|
const projectSelect = document.getElementById('quick-review-project');
|
|
7734
7912
|
const workspaceId = workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
|
|
7735
7913
|
const projectId = projectSelect ? String(projectSelect.value || '').trim() : '';
|
|
7736
7914
|
const workspaceLabel = readSelectedOptionLabel(workspaceSelect);
|
|
7737
7915
|
const projectLabel = readSelectedOptionLabel(projectSelect);
|
|
7916
|
+
if (scopeMode !== 'workspace') {
|
|
7917
|
+
setText('quick-review-scope-summary', 'Account scope');
|
|
7918
|
+
return;
|
|
7919
|
+
}
|
|
7738
7920
|
if (!workspaceId) {
|
|
7739
|
-
setText('quick-review-scope-summary',
|
|
7921
|
+
setText('quick-review-scope-summary', 'Choose governed workspace');
|
|
7740
7922
|
return;
|
|
7741
7923
|
}
|
|
7742
7924
|
if (!projectId) {
|
|
@@ -7746,14 +7928,41 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7746
7928
|
setText('quick-review-scope-summary', [workspaceLabel, projectLabel].filter(Boolean).join(' · ') || 'Governed project');
|
|
7747
7929
|
}
|
|
7748
7930
|
|
|
7749
|
-
|
|
7931
|
+
function syncQuickReviewRegistrationMode(item, mode) {
|
|
7932
|
+
const reviewScopeMode = setReviewRegistrationMode('quick-review', mode);
|
|
7933
|
+
const workspaceSelect = document.getElementById('quick-review-workspace');
|
|
7934
|
+
const projectSelect = document.getElementById('quick-review-project');
|
|
7935
|
+
const primaryButton = document.getElementById('quick-review-primary');
|
|
7936
|
+
const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect
|
|
7937
|
+
? String(workspaceSelect.value || '').trim()
|
|
7938
|
+
: '';
|
|
7939
|
+
const projectId = reviewScopeMode === 'workspace' && projectSelect
|
|
7940
|
+
? String(projectSelect.value || '').trim()
|
|
7941
|
+
: '';
|
|
7942
|
+
if (primaryButton && item) {
|
|
7943
|
+
primaryButton.textContent = getReviewPrimaryLabel(item, reviewScopeMode);
|
|
7944
|
+
primaryButton.disabled = item.inboxGroup === 'ignored' || (reviewScopeMode === 'workspace' && (!workspaceId || !projectId));
|
|
7945
|
+
}
|
|
7946
|
+
if (item) {
|
|
7947
|
+
setText('quick-review-action-summary', getReviewActionSummary(item, reviewScopeMode));
|
|
7948
|
+
}
|
|
7949
|
+
updateQuickReviewScopeSummary(reviewScopeMode);
|
|
7950
|
+
return reviewScopeMode;
|
|
7951
|
+
}
|
|
7952
|
+
|
|
7953
|
+
async function loadQuickReviewProjects(workspaceId, selectedProjectId, scopeMode) {
|
|
7750
7954
|
const projectSelect = document.getElementById('quick-review-project');
|
|
7751
7955
|
const primaryButton = document.getElementById('quick-review-primary');
|
|
7752
7956
|
if (!projectSelect) return;
|
|
7753
7957
|
if (!workspaceId) {
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7958
|
+
if (scopeMode === 'workspace') {
|
|
7959
|
+
setScopeOptions(projectSelect, [{ id: '', label: 'Choose a workspace first' }], '');
|
|
7960
|
+
if (primaryButton) primaryButton.disabled = true;
|
|
7961
|
+
} else {
|
|
7962
|
+
setScopeOptions(projectSelect, [{ id: '', label: 'Solo registration / no project' }], '');
|
|
7963
|
+
if (primaryButton) primaryButton.disabled = false;
|
|
7964
|
+
}
|
|
7965
|
+
updateQuickReviewScopeSummary(scopeMode);
|
|
7757
7966
|
return;
|
|
7758
7967
|
}
|
|
7759
7968
|
setScopeOptions(projectSelect, [{ id: '', label: 'Loading projects...' }], '');
|
|
@@ -7773,14 +7982,14 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7773
7982
|
if (primaryButton) {
|
|
7774
7983
|
primaryButton.disabled = !projects.length;
|
|
7775
7984
|
}
|
|
7776
|
-
updateQuickReviewScopeSummary(
|
|
7985
|
+
updateQuickReviewScopeSummary(scopeMode);
|
|
7777
7986
|
} catch {
|
|
7778
7987
|
setScopeOptions(projectSelect, [{ id: '', label: 'Project list unavailable' }], '');
|
|
7779
7988
|
setQuickReviewStatus('Project list is unavailable right now.', 'warn');
|
|
7780
7989
|
if (primaryButton) {
|
|
7781
7990
|
primaryButton.disabled = true;
|
|
7782
7991
|
}
|
|
7783
|
-
updateQuickReviewScopeSummary(
|
|
7992
|
+
updateQuickReviewScopeSummary(scopeMode);
|
|
7784
7993
|
}
|
|
7785
7994
|
}
|
|
7786
7995
|
|
|
@@ -7818,10 +8027,10 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7818
8027
|
setQuickReviewStatus(item.statusLabel + (item.statusMeta ? ' · ' + item.statusMeta : ''), item.statusTone === 'muted' ? '' : item.statusTone);
|
|
7819
8028
|
resetReviewResolutionActions('quick-review');
|
|
7820
8029
|
|
|
7821
|
-
const primaryLabel = getReviewPrimaryLabel(item);
|
|
8030
|
+
const primaryLabel = getReviewPrimaryLabel(item, 'solo');
|
|
7822
8031
|
setText(
|
|
7823
8032
|
'quick-review-action-summary',
|
|
7824
|
-
getReviewActionSummary(item),
|
|
8033
|
+
getReviewActionSummary(item, 'solo'),
|
|
7825
8034
|
);
|
|
7826
8035
|
if (primaryButton) {
|
|
7827
8036
|
primaryButton.textContent = primaryLabel;
|
|
@@ -7840,17 +8049,22 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7840
8049
|
ignoreButton.hidden = !canReviewIgnore(item);
|
|
7841
8050
|
}
|
|
7842
8051
|
|
|
7843
|
-
const
|
|
7844
|
-
if (!
|
|
8052
|
+
const showScopeChoice = canChooseReviewScope(item);
|
|
8053
|
+
if (!showScopeChoice) {
|
|
7845
8054
|
if (scopeWrap) scopeWrap.hidden = true;
|
|
8055
|
+
setReviewRegistrationMode('quick-review', 'solo');
|
|
7846
8056
|
quickReviewScopeCacheKey = null;
|
|
7847
|
-
setText('quick-review-scope-summary', item
|
|
8057
|
+
setText('quick-review-scope-summary', getPassiveReviewScopeSummary(item));
|
|
7848
8058
|
return;
|
|
7849
8059
|
}
|
|
7850
8060
|
|
|
7851
8061
|
if (scopeWrap) scopeWrap.hidden = false;
|
|
7852
8062
|
if (!workspaceSelect || !projectSelect) return;
|
|
7853
8063
|
const cacheKey = item.id + ':' + String(item.workspaceId || '') + ':' + String(item.projectId || '');
|
|
8064
|
+
syncQuickReviewRegistrationMode(
|
|
8065
|
+
item,
|
|
8066
|
+
quickReviewScopeCacheKey === cacheKey ? getReviewRegistrationMode('quick-review') : 'solo',
|
|
8067
|
+
);
|
|
7854
8068
|
if (quickReviewScopeCacheKey === cacheKey) {
|
|
7855
8069
|
return;
|
|
7856
8070
|
}
|
|
@@ -7863,35 +8077,43 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7863
8077
|
const response = await apiFetch('/api/scope/access');
|
|
7864
8078
|
const payload = await response.json();
|
|
7865
8079
|
scopeAccessSnapshot = payload;
|
|
7866
|
-
const governedMode = payload && payload.operatingMode === 'governed';
|
|
7867
8080
|
const workspaces = payload.ok && Array.isArray(payload.workspaces) ? payload.workspaces : [];
|
|
7868
8081
|
const options = [
|
|
7869
|
-
|
|
8082
|
+
{ id: '', label: 'Register solo / account scope' },
|
|
7870
8083
|
...workspaces.map((workspace) => ({ id: workspace.id, label: workspace.name || workspace.id })),
|
|
7871
8084
|
];
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
}
|
|
7875
|
-
const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || (options[0] && options[0].id) || '';
|
|
8085
|
+
const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || '';
|
|
8086
|
+
const selectedProject = item.projectId || payload.currentProjectId || '';
|
|
7876
8087
|
setScopeOptions(workspaceSelect, options, selectedWorkspace);
|
|
7877
|
-
await loadQuickReviewProjects(selectedWorkspace,
|
|
8088
|
+
await loadQuickReviewProjects(selectedWorkspace, selectedProject, getReviewRegistrationMode('quick-review'));
|
|
8089
|
+
const reviewScopeMode = syncQuickReviewRegistrationMode(item, getReviewRegistrationMode('quick-review'));
|
|
7878
8090
|
setQuickReviewStatus(
|
|
7879
8091
|
payload.ok
|
|
7880
|
-
? (
|
|
7881
|
-
?
|
|
7882
|
-
|
|
7883
|
-
|
|
8092
|
+
? (reviewScopeMode === 'workspace'
|
|
8093
|
+
? (selectedWorkspace
|
|
8094
|
+
? 'Choose the governed workspace and project for this registration.'
|
|
8095
|
+
: workspaces.length
|
|
8096
|
+
? 'Choose a workspace and project for governed registration.'
|
|
8097
|
+
: 'No governed workspaces are available yet. Switch back to solo or create one first.')
|
|
8098
|
+
: 'Solo registration is ready. Choose governed workspace only when needed.')
|
|
8099
|
+
: (reviewScopeMode === 'workspace'
|
|
8100
|
+
? (payload.message || 'Workspace access is unavailable right now. Switch to solo registration or retry later.')
|
|
8101
|
+
: 'Solo registration is still available. Governed workspace access is unavailable right now.'),
|
|
7884
8102
|
payload.ok ? '' : 'warn',
|
|
7885
8103
|
);
|
|
7886
|
-
updateQuickReviewScopeSummary(governedMode);
|
|
7887
8104
|
} catch {
|
|
7888
8105
|
setScopeOptions(workspaceSelect, [{ id: '', label: 'Workspace list unavailable' }], '');
|
|
7889
8106
|
setScopeOptions(projectSelect, [{ id: '', label: 'Project list unavailable' }], '');
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
8107
|
+
const reviewScopeMode = syncQuickReviewRegistrationMode(item, getReviewRegistrationMode('quick-review'));
|
|
8108
|
+
setQuickReviewStatus(
|
|
8109
|
+
reviewScopeMode === 'workspace'
|
|
8110
|
+
? 'Workspace access is unavailable right now. Switch to solo registration or retry later.'
|
|
8111
|
+
: 'Solo registration is still available. Governed workspace access is unavailable right now.',
|
|
8112
|
+
'warn',
|
|
8113
|
+
);
|
|
8114
|
+
if (reviewScopeMode === 'workspace') {
|
|
8115
|
+
setText('quick-review-scope-summary', 'Scope unavailable');
|
|
7893
8116
|
}
|
|
7894
|
-
setText('quick-review-scope-summary', 'Scope unavailable');
|
|
7895
8117
|
}
|
|
7896
8118
|
}
|
|
7897
8119
|
|
|
@@ -7899,7 +8121,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7899
8121
|
const item = getQuickReviewItem();
|
|
7900
8122
|
if (!item) return;
|
|
7901
8123
|
selectedDiscoveryId = item.id;
|
|
7902
|
-
if (item
|
|
8124
|
+
if (shouldOpenReviewContext(item)) {
|
|
7903
8125
|
await openDiscoveryContext(item);
|
|
7904
8126
|
setQuickReviewPanelOpen(false);
|
|
7905
8127
|
return;
|
|
@@ -7911,17 +8133,13 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7911
8133
|
const workspaceSelect = document.getElementById('quick-review-workspace');
|
|
7912
8134
|
const projectSelect = document.getElementById('quick-review-project');
|
|
7913
8135
|
const primaryButton = document.getElementById('quick-review-primary');
|
|
7914
|
-
const
|
|
7915
|
-
const
|
|
7916
|
-
const
|
|
7917
|
-
if (
|
|
8136
|
+
const reviewScopeMode = getReviewRegistrationMode('quick-review');
|
|
8137
|
+
const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
|
|
8138
|
+
const projectId = reviewScopeMode === 'workspace' && projectSelect ? String(projectSelect.value || '').trim() : '';
|
|
8139
|
+
if (reviewScopeMode === 'workspace' && (!workspaceId || !projectId)) {
|
|
7918
8140
|
setQuickReviewStatus('Select a project for the chosen workspace, or switch back to account scope.', 'warn');
|
|
7919
8141
|
return;
|
|
7920
8142
|
}
|
|
7921
|
-
if (!workspaceId && governedMode) {
|
|
7922
|
-
setQuickReviewStatus('Choose the governed workspace and project before registering here.', 'warn');
|
|
7923
|
-
return;
|
|
7924
|
-
}
|
|
7925
8143
|
if (primaryButton) primaryButton.disabled = true;
|
|
7926
8144
|
const endpoint = item.kind === 'agent' ? '/api/discovery/connect-agent' : '/api/discovery/connect-model';
|
|
7927
8145
|
const result = await postAction(endpoint, 'Registering with Forkit Connect...', {
|
|
@@ -7995,13 +8213,39 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7995
8213
|
}
|
|
7996
8214
|
}
|
|
7997
8215
|
|
|
7998
|
-
|
|
8216
|
+
function syncDiscoveryReviewRegistrationMode(item, mode) {
|
|
8217
|
+
const reviewScopeMode = setReviewRegistrationMode('discovery-review', mode);
|
|
8218
|
+
const workspaceSelect = document.getElementById('discovery-review-workspace');
|
|
8219
|
+
const projectSelect = document.getElementById('discovery-review-project');
|
|
8220
|
+
const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect
|
|
8221
|
+
? String(workspaceSelect.value || '').trim()
|
|
8222
|
+
: '';
|
|
8223
|
+
const projectId = reviewScopeMode === 'workspace' && projectSelect
|
|
8224
|
+
? String(projectSelect.value || '').trim()
|
|
8225
|
+
: '';
|
|
8226
|
+
if (item) {
|
|
8227
|
+
setDiscoveryReviewButtons({
|
|
8228
|
+
primaryLabel: getReviewPrimaryLabel(item, reviewScopeMode),
|
|
8229
|
+
primaryEnabled: item.inboxGroup !== 'ignored' && !(reviewScopeMode === 'workspace' && (!workspaceId || !projectId)),
|
|
8230
|
+
deferEnabled: canReviewDefer(item),
|
|
8231
|
+
ignoreEnabled: canReviewIgnore(item),
|
|
8232
|
+
});
|
|
8233
|
+
}
|
|
8234
|
+
return reviewScopeMode;
|
|
8235
|
+
}
|
|
8236
|
+
|
|
8237
|
+
async function loadDiscoveryReviewProjects(workspaceId, selectedProjectId, scopeMode) {
|
|
7999
8238
|
const projectSelect = document.getElementById('discovery-review-project');
|
|
8000
8239
|
const primaryButton = document.getElementById('discovery-review-primary');
|
|
8001
8240
|
if (!projectSelect) return;
|
|
8002
8241
|
if (!workspaceId) {
|
|
8003
|
-
|
|
8004
|
-
|
|
8242
|
+
if (scopeMode === 'workspace') {
|
|
8243
|
+
setScopeOptions(projectSelect, [{ id: '', label: 'Choose a workspace first' }], '');
|
|
8244
|
+
if (primaryButton) primaryButton.disabled = true;
|
|
8245
|
+
} else {
|
|
8246
|
+
setScopeOptions(projectSelect, [{ id: '', label: 'Solo registration / no project' }], '');
|
|
8247
|
+
if (primaryButton) primaryButton.disabled = false;
|
|
8248
|
+
}
|
|
8005
8249
|
return;
|
|
8006
8250
|
}
|
|
8007
8251
|
setScopeOptions(projectSelect, [{ id: '', label: 'Loading projects...' }], '');
|
|
@@ -8042,6 +8286,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
8042
8286
|
setText('discovery-review-meta', 'Choose a model, agent, or runtime to review it here.');
|
|
8043
8287
|
setText('discovery-review-detail', 'Registering creates or updates a Forkit Passport. Nothing is published automatically.');
|
|
8044
8288
|
if (scopeWrap) scopeWrap.hidden = true;
|
|
8289
|
+
setReviewRegistrationMode('discovery-review', 'solo');
|
|
8045
8290
|
setDiscoveryReviewStatus('Select an item to continue.', '');
|
|
8046
8291
|
resetReviewResolutionActions('discovery-review');
|
|
8047
8292
|
setDiscoveryReviewButtons({ primaryLabel: 'Review', primaryEnabled: false, deferEnabled: false, ignoreEnabled: false });
|
|
@@ -8049,8 +8294,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
8049
8294
|
}
|
|
8050
8295
|
|
|
8051
8296
|
const typeLabel = item.typeLabel || item.kind;
|
|
8052
|
-
const
|
|
8053
|
-
const primaryLabel = getReviewPrimaryLabel(item);
|
|
8297
|
+
const showScopeChoice = canChooseReviewScope(item);
|
|
8054
8298
|
|
|
8055
8299
|
setText('discovery-review-kicker', typeLabel);
|
|
8056
8300
|
setText('discovery-review-title', item.name);
|
|
@@ -8059,14 +8303,15 @@ function renderLauncherHtml(launcherToken) {
|
|
|
8059
8303
|
setDiscoveryReviewStatus(item.statusLabel + (item.statusMeta ? ' · ' + item.statusMeta : ''), item.statusTone === 'muted' ? '' : item.statusTone);
|
|
8060
8304
|
resetReviewResolutionActions('discovery-review');
|
|
8061
8305
|
setDiscoveryReviewButtons({
|
|
8062
|
-
primaryLabel: getReviewPrimaryLabel(item),
|
|
8306
|
+
primaryLabel: getReviewPrimaryLabel(item, 'solo'),
|
|
8063
8307
|
primaryEnabled: item.inboxGroup !== 'ignored',
|
|
8064
8308
|
deferEnabled: canReviewDefer(item),
|
|
8065
8309
|
ignoreEnabled: canReviewIgnore(item),
|
|
8066
8310
|
});
|
|
8067
8311
|
|
|
8068
|
-
if (!
|
|
8312
|
+
if (!showScopeChoice) {
|
|
8069
8313
|
if (scopeWrap) scopeWrap.hidden = true;
|
|
8314
|
+
setReviewRegistrationMode('discovery-review', 'solo');
|
|
8070
8315
|
reviewScopeCacheKey = null;
|
|
8071
8316
|
return;
|
|
8072
8317
|
}
|
|
@@ -8075,6 +8320,10 @@ function renderLauncherHtml(launcherToken) {
|
|
|
8075
8320
|
if (!workspaceSelect || !projectSelect) return;
|
|
8076
8321
|
|
|
8077
8322
|
const cacheKey = item.id + ':' + String(item.workspaceId || '') + ':' + String(item.projectId || '');
|
|
8323
|
+
syncDiscoveryReviewRegistrationMode(
|
|
8324
|
+
item,
|
|
8325
|
+
reviewScopeCacheKey === cacheKey ? getReviewRegistrationMode('discovery-review') : 'solo',
|
|
8326
|
+
);
|
|
8078
8327
|
if (reviewScopeCacheKey === cacheKey) {
|
|
8079
8328
|
return;
|
|
8080
8329
|
}
|
|
@@ -8088,43 +8337,47 @@ function renderLauncherHtml(launcherToken) {
|
|
|
8088
8337
|
const response = await apiFetch('/api/scope/access');
|
|
8089
8338
|
const payload = await response.json();
|
|
8090
8339
|
scopeAccessSnapshot = payload;
|
|
8091
|
-
const governedMode = payload && payload.operatingMode === 'governed';
|
|
8092
8340
|
const workspaces = payload.ok && Array.isArray(payload.workspaces) ? payload.workspaces : [];
|
|
8093
8341
|
const options = [
|
|
8094
|
-
|
|
8342
|
+
{ id: '', label: 'Register solo / account scope' },
|
|
8095
8343
|
...workspaces.map((workspace) => ({ id: workspace.id, label: workspace.name || workspace.id })),
|
|
8096
8344
|
];
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
}
|
|
8100
|
-
const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || (options[0] && options[0].id) || '';
|
|
8345
|
+
const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || '';
|
|
8346
|
+
const selectedProject = item.projectId || payload.currentProjectId || '';
|
|
8101
8347
|
setScopeOptions(workspaceSelect, options, selectedWorkspace);
|
|
8102
|
-
await loadDiscoveryReviewProjects(selectedWorkspace,
|
|
8348
|
+
await loadDiscoveryReviewProjects(selectedWorkspace, selectedProject, getReviewRegistrationMode('discovery-review'));
|
|
8349
|
+
const reviewScopeMode = syncDiscoveryReviewRegistrationMode(item, getReviewRegistrationMode('discovery-review'));
|
|
8103
8350
|
setDiscoveryReviewStatus(
|
|
8104
8351
|
payload.ok
|
|
8105
|
-
? (
|
|
8106
|
-
?
|
|
8107
|
-
|
|
8108
|
-
|
|
8352
|
+
? (reviewScopeMode === 'workspace'
|
|
8353
|
+
? (selectedWorkspace
|
|
8354
|
+
? 'Choose the governed workspace and project for this registration.'
|
|
8355
|
+
: workspaces.length
|
|
8356
|
+
? 'Choose a workspace and project for governed registration.'
|
|
8357
|
+
: 'No governed workspaces are available yet. Switch back to solo or create one first.')
|
|
8358
|
+
: 'Solo registration is ready. Choose governed workspace only when needed.')
|
|
8359
|
+
: (reviewScopeMode === 'workspace'
|
|
8360
|
+
? (payload.message || 'Workspace access is unavailable right now. Switch to solo registration or retry later.')
|
|
8361
|
+
: 'Solo registration is still available. Governed workspace access is unavailable right now.'),
|
|
8109
8362
|
payload.ok ? '' : 'warn',
|
|
8110
8363
|
);
|
|
8111
8364
|
} catch {
|
|
8112
8365
|
setScopeOptions(workspaceSelect, [{ id: '', label: 'Workspace list unavailable' }], '');
|
|
8113
8366
|
setScopeOptions(projectSelect, [{ id: '', label: 'Project list unavailable' }], '');
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8367
|
+
const reviewScopeMode = syncDiscoveryReviewRegistrationMode(item, getReviewRegistrationMode('discovery-review'));
|
|
8368
|
+
setDiscoveryReviewStatus(
|
|
8369
|
+
reviewScopeMode === 'workspace'
|
|
8370
|
+
? 'Workspace access is unavailable right now. Switch to solo registration or retry later.'
|
|
8371
|
+
: 'Solo registration is still available. Governed workspace access is unavailable right now.',
|
|
8372
|
+
'warn',
|
|
8373
|
+
);
|
|
8121
8374
|
}
|
|
8122
8375
|
}
|
|
8123
8376
|
|
|
8124
8377
|
async function submitDiscoveryReviewPrimary() {
|
|
8125
8378
|
const item = getSelectedDiscoveryItem();
|
|
8126
8379
|
if (!item) return;
|
|
8127
|
-
if (item
|
|
8380
|
+
if (shouldOpenReviewContext(item)) {
|
|
8128
8381
|
await openDiscoveryContext(item);
|
|
8129
8382
|
return;
|
|
8130
8383
|
}
|
|
@@ -8135,9 +8388,10 @@ function renderLauncherHtml(launcherToken) {
|
|
|
8135
8388
|
const workspaceSelect = document.getElementById('discovery-review-workspace');
|
|
8136
8389
|
const projectSelect = document.getElementById('discovery-review-project');
|
|
8137
8390
|
const primaryButton = document.getElementById('discovery-review-primary');
|
|
8138
|
-
const
|
|
8139
|
-
const
|
|
8140
|
-
|
|
8391
|
+
const reviewScopeMode = getReviewRegistrationMode('discovery-review');
|
|
8392
|
+
const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
|
|
8393
|
+
const projectId = reviewScopeMode === 'workspace' && projectSelect ? String(projectSelect.value || '').trim() : '';
|
|
8394
|
+
if (reviewScopeMode === 'workspace' && (!workspaceId || !projectId)) {
|
|
8141
8395
|
setDiscoveryReviewStatus('Select a project for the chosen workspace, or switch back to account scope.', 'warn');
|
|
8142
8396
|
return;
|
|
8143
8397
|
}
|
|
@@ -9091,7 +9345,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
9091
9345
|
registerButton.disabled = true;
|
|
9092
9346
|
setText('scope-modal-title', 'Register ' + item.name);
|
|
9093
9347
|
let governedMode = latestSummary && latestSummary.operatingMode === 'governed';
|
|
9094
|
-
setText('scope-modal-copy', 'Checking account scope and
|
|
9348
|
+
setText('scope-modal-copy', 'Checking account scope and any governed workspace options...');
|
|
9095
9349
|
if (createWorkspaceButton) createWorkspaceButton.hidden = true;
|
|
9096
9350
|
if (createProjectButton) createProjectButton.hidden = true;
|
|
9097
9351
|
setScopeCreateButtonsEnabled(false);
|
|
@@ -9106,40 +9360,38 @@ function renderLauncherHtml(launcherToken) {
|
|
|
9106
9360
|
setText(
|
|
9107
9361
|
'scope-modal-copy',
|
|
9108
9362
|
governedMode
|
|
9109
|
-
? '
|
|
9110
|
-
: '
|
|
9363
|
+
? 'Register on your account now, or choose a governed workspace/project when you want governed ownership. You can create missing scope here.'
|
|
9364
|
+
: 'Solo registration is available now. Choose a governed workspace/project only when you want governed operations.',
|
|
9111
9365
|
);
|
|
9112
9366
|
if (createWorkspaceButton) createWorkspaceButton.hidden = !governedMode;
|
|
9113
9367
|
if (createProjectButton) createProjectButton.hidden = !governedMode;
|
|
9114
9368
|
setScopeCreateButtonsEnabled(governedMode);
|
|
9115
9369
|
const workspaces = payload.ok && Array.isArray(payload.workspaces) ? payload.workspaces : [];
|
|
9116
9370
|
const options = [
|
|
9117
|
-
|
|
9371
|
+
{ id: '', label: 'Register solo / account scope' },
|
|
9118
9372
|
...workspaces.map((workspace) => ({ id: workspace.id, label: workspace.name || workspace.id })),
|
|
9119
9373
|
];
|
|
9120
|
-
if (governedMode &&
|
|
9121
|
-
options.push({ id: '', label: 'No governed workspaces yet' });
|
|
9122
|
-
registerButton.disabled = true;
|
|
9374
|
+
if (governedMode && workspaces.length === 0) {
|
|
9123
9375
|
openScopeCreateWorkspaceFlow('No governed workspace exists yet. Create one here to continue.', 'warn');
|
|
9124
9376
|
}
|
|
9125
|
-
const selectedWorkspace =
|
|
9377
|
+
const selectedWorkspace = item.workspaceId || '';
|
|
9126
9378
|
setScopeOptions(workspaceSelect, options, selectedWorkspace);
|
|
9127
9379
|
const hasProjects = await loadScopeProjects(workspaceSelect.value, payload.currentProjectId || '');
|
|
9128
|
-
registerButton.disabled = !payload.ok || (
|
|
9129
|
-
if (payload.ok && (!
|
|
9130
|
-
setScopeStatus(
|
|
9380
|
+
registerButton.disabled = !payload.ok || (Boolean(String(workspaceSelect.value || '').trim()) && !hasProjects);
|
|
9381
|
+
if (payload.ok && (!String(workspaceSelect.value || '').trim() || hasProjects)) {
|
|
9382
|
+
setScopeStatus(String(workspaceSelect.value || '').trim() ? 'Ready to register in governed scope.' : 'Ready to register solo.', '');
|
|
9131
9383
|
} else if (!payload.ok) {
|
|
9132
9384
|
setScopeStatus(
|
|
9133
|
-
payload.message ||
|
|
9385
|
+
payload.message || 'Workspace list unavailable. Solo registration is still available.',
|
|
9134
9386
|
'warn',
|
|
9135
9387
|
);
|
|
9136
9388
|
}
|
|
9137
9389
|
} catch {
|
|
9138
|
-
setScopeOptions(workspaceSelect,
|
|
9139
|
-
await loadScopeProjects(
|
|
9140
|
-
registerButton.disabled =
|
|
9390
|
+
setScopeOptions(workspaceSelect, [{ id: '', label: 'Register solo / account scope' }], '');
|
|
9391
|
+
await loadScopeProjects('', '');
|
|
9392
|
+
registerButton.disabled = false;
|
|
9141
9393
|
setScopeCreateButtonsEnabled(false);
|
|
9142
|
-
setScopeStatus(
|
|
9394
|
+
setScopeStatus('Workspace list unavailable. Solo registration is still available.', 'warn');
|
|
9143
9395
|
}
|
|
9144
9396
|
}
|
|
9145
9397
|
|
|
@@ -9165,7 +9417,7 @@ function renderLauncherHtml(launcherToken) {
|
|
|
9165
9417
|
}
|
|
9166
9418
|
if (registerButton) registerButton.disabled = true;
|
|
9167
9419
|
const endpoint = item.kind === 'agent' ? '/api/discovery/connect-agent' : '/api/discovery/connect-model';
|
|
9168
|
-
const pendingMessage = item.kind === 'agent' ? 'Registering agent...' : '
|
|
9420
|
+
const pendingMessage = item.kind === 'agent' ? 'Registering agent...' : 'Registering model...';
|
|
9169
9421
|
setScopeStatus('Registering with Forkit Connect...', 'warn');
|
|
9170
9422
|
const result = await postAction(endpoint, pendingMessage, {
|
|
9171
9423
|
method: 'POST',
|
|
@@ -10073,34 +10325,62 @@ function renderLauncherHtml(launcherToken) {
|
|
|
10073
10325
|
void submitQuickReviewIgnore();
|
|
10074
10326
|
});
|
|
10075
10327
|
}
|
|
10328
|
+
const quickReviewModeSolo = document.getElementById('quick-review-mode-solo');
|
|
10329
|
+
if (quickReviewModeSolo) {
|
|
10330
|
+
quickReviewModeSolo.addEventListener('click', () => {
|
|
10331
|
+
const item = getQuickReviewItem();
|
|
10332
|
+
if (!item || !canChooseReviewScope(item)) return;
|
|
10333
|
+
syncQuickReviewRegistrationMode(item, 'solo');
|
|
10334
|
+
setQuickReviewStatus('Solo registration is ready. Choose governed workspace only when needed.', '');
|
|
10335
|
+
});
|
|
10336
|
+
}
|
|
10337
|
+
const quickReviewModeWorkspace = document.getElementById('quick-review-mode-workspace');
|
|
10338
|
+
if (quickReviewModeWorkspace) {
|
|
10339
|
+
quickReviewModeWorkspace.addEventListener('click', () => {
|
|
10340
|
+
const item = getQuickReviewItem();
|
|
10341
|
+
if (!item || !canChooseReviewScope(item)) return;
|
|
10342
|
+
syncQuickReviewRegistrationMode(item, 'workspace');
|
|
10343
|
+
const selectedWorkspaceId = quickReviewWorkspaceSelect
|
|
10344
|
+
? String(quickReviewWorkspaceSelect.value || '').trim()
|
|
10345
|
+
: '';
|
|
10346
|
+
const selectedProjectId = quickReviewProjectSelect
|
|
10347
|
+
? String(quickReviewProjectSelect.value || '').trim()
|
|
10348
|
+
: '';
|
|
10349
|
+
void loadQuickReviewProjects(selectedWorkspaceId, selectedProjectId, 'workspace');
|
|
10350
|
+
setQuickReviewStatus(
|
|
10351
|
+
selectedWorkspaceId
|
|
10352
|
+
? 'Choose the governed project for this registration.'
|
|
10353
|
+
: 'Choose a workspace and project for governed registration.',
|
|
10354
|
+
'',
|
|
10355
|
+
);
|
|
10356
|
+
});
|
|
10357
|
+
}
|
|
10076
10358
|
const quickReviewWorkspaceSelect = document.getElementById('quick-review-workspace');
|
|
10077
10359
|
if (quickReviewWorkspaceSelect) {
|
|
10078
10360
|
quickReviewWorkspaceSelect.addEventListener('change', () => {
|
|
10361
|
+
const item = getQuickReviewItem();
|
|
10079
10362
|
const selectedWorkspaceId = String(quickReviewWorkspaceSelect.value || '').trim();
|
|
10080
|
-
const
|
|
10081
|
-
|
|
10082
|
-
void loadQuickReviewProjects(selectedWorkspaceId, '', governedMode);
|
|
10083
|
-
updateQuickReviewScopeSummary(governedMode);
|
|
10363
|
+
const reviewScopeMode = getReviewRegistrationMode('quick-review');
|
|
10364
|
+
void loadQuickReviewProjects(selectedWorkspaceId, '', reviewScopeMode);
|
|
10084
10365
|
setQuickReviewStatus(
|
|
10085
|
-
|
|
10086
|
-
?
|
|
10087
|
-
|
|
10366
|
+
reviewScopeMode === 'workspace'
|
|
10367
|
+
? (selectedWorkspaceId
|
|
10368
|
+
? 'Choose the governed project for this registration.'
|
|
10369
|
+
: 'Choose a workspace and project for governed registration.')
|
|
10370
|
+
: 'Solo registration stays available. Choose governed scope only when needed.',
|
|
10088
10371
|
'',
|
|
10089
10372
|
);
|
|
10373
|
+
if (item) {
|
|
10374
|
+
syncQuickReviewRegistrationMode(item, reviewScopeMode);
|
|
10375
|
+
}
|
|
10090
10376
|
});
|
|
10091
10377
|
}
|
|
10092
10378
|
const quickReviewProjectSelect = document.getElementById('quick-review-project');
|
|
10093
10379
|
if (quickReviewProjectSelect) {
|
|
10094
10380
|
quickReviewProjectSelect.addEventListener('change', () => {
|
|
10095
|
-
const
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
: '';
|
|
10099
|
-
const selectedProjectId = String(quickReviewProjectSelect.value || '').trim();
|
|
10100
|
-
const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
|
|
10101
|
-
updateQuickReviewScopeSummary(governedMode);
|
|
10102
|
-
if (primaryButton) {
|
|
10103
|
-
primaryButton.disabled = Boolean(selectedWorkspaceId && !selectedProjectId && governedMode);
|
|
10381
|
+
const item = getQuickReviewItem();
|
|
10382
|
+
if (item) {
|
|
10383
|
+
syncQuickReviewRegistrationMode(item, getReviewRegistrationMode('quick-review'));
|
|
10104
10384
|
}
|
|
10105
10385
|
});
|
|
10106
10386
|
}
|
|
@@ -10134,20 +10414,53 @@ function renderLauncherHtml(launcherToken) {
|
|
|
10134
10414
|
void submitDiscoveryReviewIgnore();
|
|
10135
10415
|
});
|
|
10136
10416
|
}
|
|
10417
|
+
const discoveryReviewModeSolo = document.getElementById('discovery-review-mode-solo');
|
|
10418
|
+
if (discoveryReviewModeSolo) {
|
|
10419
|
+
discoveryReviewModeSolo.addEventListener('click', () => {
|
|
10420
|
+
const selectedItem = getSelectedDiscoveryItem();
|
|
10421
|
+
if (!selectedItem || !canChooseReviewScope(selectedItem)) return;
|
|
10422
|
+
syncDiscoveryReviewRegistrationMode(selectedItem, 'solo');
|
|
10423
|
+
setDiscoveryReviewStatus('Solo registration is ready. Choose governed workspace only when needed.', '');
|
|
10424
|
+
});
|
|
10425
|
+
}
|
|
10426
|
+
const discoveryReviewModeWorkspace = document.getElementById('discovery-review-mode-workspace');
|
|
10427
|
+
if (discoveryReviewModeWorkspace) {
|
|
10428
|
+
discoveryReviewModeWorkspace.addEventListener('click', () => {
|
|
10429
|
+
const selectedItem = getSelectedDiscoveryItem();
|
|
10430
|
+
if (!selectedItem || !canChooseReviewScope(selectedItem)) return;
|
|
10431
|
+
syncDiscoveryReviewRegistrationMode(selectedItem, 'workspace');
|
|
10432
|
+
const selectedWorkspaceId = discoveryReviewWorkspaceSelect
|
|
10433
|
+
? String(discoveryReviewWorkspaceSelect.value || '').trim()
|
|
10434
|
+
: '';
|
|
10435
|
+
const selectedProjectId = discoveryReviewProjectSelect
|
|
10436
|
+
? String(discoveryReviewProjectSelect.value || '').trim()
|
|
10437
|
+
: '';
|
|
10438
|
+
void loadDiscoveryReviewProjects(selectedWorkspaceId, selectedProjectId, 'workspace');
|
|
10439
|
+
setDiscoveryReviewStatus(
|
|
10440
|
+
selectedWorkspaceId
|
|
10441
|
+
? 'Choose the governed project for this registration.'
|
|
10442
|
+
: 'Choose a workspace and project for governed registration.',
|
|
10443
|
+
'',
|
|
10444
|
+
);
|
|
10445
|
+
});
|
|
10446
|
+
}
|
|
10137
10447
|
const discoveryReviewWorkspaceSelect = document.getElementById('discovery-review-workspace');
|
|
10138
10448
|
if (discoveryReviewWorkspaceSelect) {
|
|
10139
10449
|
discoveryReviewWorkspaceSelect.addEventListener('change', () => {
|
|
10140
10450
|
const selectedItem = getSelectedDiscoveryItem();
|
|
10141
10451
|
const selectedWorkspaceId = String(discoveryReviewWorkspaceSelect.value || '').trim();
|
|
10142
|
-
const
|
|
10143
|
-
void loadDiscoveryReviewProjects(selectedWorkspaceId, '',
|
|
10452
|
+
const reviewScopeMode = getReviewRegistrationMode('discovery-review');
|
|
10453
|
+
void loadDiscoveryReviewProjects(selectedWorkspaceId, '', reviewScopeMode);
|
|
10144
10454
|
if (selectedItem && canReviewRegister(selectedItem)) {
|
|
10145
10455
|
setDiscoveryReviewStatus(
|
|
10146
|
-
|
|
10147
|
-
?
|
|
10148
|
-
|
|
10456
|
+
reviewScopeMode === 'workspace'
|
|
10457
|
+
? (selectedWorkspaceId
|
|
10458
|
+
? 'Choose the governed project for this registration.'
|
|
10459
|
+
: 'Choose a workspace and project for governed registration.')
|
|
10460
|
+
: 'Solo registration stays available. Choose governed scope only when needed.',
|
|
10149
10461
|
'',
|
|
10150
10462
|
);
|
|
10463
|
+
syncDiscoveryReviewRegistrationMode(selectedItem, reviewScopeMode);
|
|
10151
10464
|
}
|
|
10152
10465
|
});
|
|
10153
10466
|
}
|
|
@@ -10155,14 +10468,8 @@ function renderLauncherHtml(launcherToken) {
|
|
|
10155
10468
|
if (discoveryReviewProjectSelect) {
|
|
10156
10469
|
discoveryReviewProjectSelect.addEventListener('change', () => {
|
|
10157
10470
|
const selectedItem = getSelectedDiscoveryItem();
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
? String(discoveryReviewWorkspaceSelect.value || '').trim()
|
|
10161
|
-
: '';
|
|
10162
|
-
const selectedProjectId = String(discoveryReviewProjectSelect.value || '').trim();
|
|
10163
|
-
const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
|
|
10164
|
-
if (primaryButton && selectedItem && canReviewRegister(selectedItem)) {
|
|
10165
|
-
primaryButton.disabled = Boolean(selectedWorkspaceId && !selectedProjectId && governedMode);
|
|
10471
|
+
if (selectedItem && canReviewRegister(selectedItem)) {
|
|
10472
|
+
syncDiscoveryReviewRegistrationMode(selectedItem, getReviewRegistrationMode('discovery-review'));
|
|
10166
10473
|
}
|
|
10167
10474
|
});
|
|
10168
10475
|
}
|
|
@@ -10806,16 +11113,19 @@ function createLauncherApp(options) {
|
|
|
10806
11113
|
else {
|
|
10807
11114
|
await options.service.bindWorkspaceProject(null, null);
|
|
10808
11115
|
}
|
|
10809
|
-
const result = await options.service.connectDetectedModel(selector
|
|
11116
|
+
const result = await options.service.connectDetectedModel(selector, {
|
|
11117
|
+
destination: 'passport',
|
|
11118
|
+
visibility: 'public',
|
|
11119
|
+
});
|
|
10810
11120
|
const message = result.action === 'already_bound'
|
|
10811
11121
|
? 'Model is already connected to a Passport.'
|
|
10812
11122
|
: result.action === 'already_pending'
|
|
10813
|
-
? '
|
|
11123
|
+
? 'Registration is already in progress for this model.'
|
|
10814
11124
|
: result.action === 'passport_registered'
|
|
10815
|
-
? 'Passport registered
|
|
11125
|
+
? 'Passport registered successfully.'
|
|
10816
11126
|
: result.action === 'draft_created'
|
|
10817
|
-
? '
|
|
10818
|
-
: '
|
|
11127
|
+
? 'Registration started privately for review before publishing.'
|
|
11128
|
+
: 'Registration was saved locally and will continue when Forkit Connect can sync again.';
|
|
10819
11129
|
response.json({
|
|
10820
11130
|
ok: true,
|
|
10821
11131
|
message,
|
|
@@ -10885,7 +11195,7 @@ function createLauncherApp(options) {
|
|
|
10885
11195
|
: passportGaid
|
|
10886
11196
|
? 'Agent is already registered.'
|
|
10887
11197
|
: draftId
|
|
10888
|
-
? 'Agent registration
|
|
11198
|
+
? 'Agent registration started privately for review.'
|
|
10889
11199
|
: 'Agent connected locally. Registration is still available.';
|
|
10890
11200
|
response.json({
|
|
10891
11201
|
ok: true,
|
package/dist/v1/service.d.ts
CHANGED
|
@@ -742,6 +742,7 @@ export declare class ConnectV1Service {
|
|
|
742
742
|
connectDetectedModel(selector: string, options?: {
|
|
743
743
|
visibility?: 'private' | 'public';
|
|
744
744
|
destination?: 'draft' | 'passport';
|
|
745
|
+
allowPrivateFallback?: boolean;
|
|
745
746
|
}): Promise<ConnectSelectionResult>;
|
|
746
747
|
private resolveRuntimePassportSelection;
|
|
747
748
|
connectRuntimeSuggestion(selector: string): Promise<ConnectSelectionResult>;
|
package/dist/v1/service.js
CHANGED
|
@@ -7834,10 +7834,13 @@ class ConnectV1Service {
|
|
|
7834
7834
|
const soloDraftAllowed = draftBindingStatus.allowed && draftBindingStatus.reasonCode === 'solo_passport_draft_allowed';
|
|
7835
7835
|
const localScopedDraftAllowed = draftBindingStatus.allowed && draftBindingStatus.reasonCode === 'local_workspace_project_draft_allowed';
|
|
7836
7836
|
const model = this.resolveModelSelection(selector, state);
|
|
7837
|
-
const requestedDestination = options?.destination === '
|
|
7838
|
-
const requestedVisibility = options?.visibility === '
|
|
7839
|
-
? '
|
|
7840
|
-
: '
|
|
7837
|
+
const requestedDestination = options?.destination === 'draft' ? 'draft' : 'passport';
|
|
7838
|
+
const requestedVisibility = options?.visibility === 'private'
|
|
7839
|
+
? 'private'
|
|
7840
|
+
: requestedDestination === 'passport'
|
|
7841
|
+
? 'public'
|
|
7842
|
+
: 'private';
|
|
7843
|
+
const allowPrivateFallback = options?.allowPrivateFallback !== false;
|
|
7841
7844
|
this.clearModelReviewDeferral(model);
|
|
7842
7845
|
this.updateDetectedModelRegistrationHint(model, {
|
|
7843
7846
|
trackingStatus: null,
|
|
@@ -7992,10 +7995,17 @@ class ConnectV1Service {
|
|
|
7992
7995
|
this.updateDetectedModelRegistrationHint(model, {
|
|
7993
7996
|
trackingStatus: 'private_draft_required',
|
|
7994
7997
|
errorCode: backendCode,
|
|
7995
|
-
errorMessage: '
|
|
7998
|
+
errorMessage: 'Forkit needs one private review step before this passport can finish publishing.',
|
|
7996
7999
|
errorStatus: result.status,
|
|
7997
|
-
guidance: '
|
|
8000
|
+
guidance: 'Forkit is continuing this registration privately first. Finish the review step there before publishing.',
|
|
7998
8001
|
});
|
|
8002
|
+
if (allowPrivateFallback && requestedDestination === 'passport' && requestedVisibility === 'public') {
|
|
8003
|
+
return this.connectDetectedModel(selector, {
|
|
8004
|
+
destination: 'draft',
|
|
8005
|
+
visibility: 'private',
|
|
8006
|
+
allowPrivateFallback: false,
|
|
8007
|
+
});
|
|
8008
|
+
}
|
|
7999
8009
|
}
|
|
8000
8010
|
this.observeBackendCommunicationState({
|
|
8001
8011
|
passportGaid: bindingWithRuntime?.gaid ?? null,
|