forkit-connect 0.1.6 → 0.1.8
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 +17 -0
- package/dist/launcher.js +23 -1
- package/dist/v1/service.d.ts +1 -0
- package/dist/v1/service.js +58 -3
- package/dist/v1/state.js +22 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1427,6 +1427,11 @@ function formatSmartInboxActionValue(action, itemType, connectableModelName) {
|
|
|
1427
1427
|
}
|
|
1428
1428
|
}
|
|
1429
1429
|
function formatSmartInboxActionLabel(item) {
|
|
1430
|
+
if (item.item_type === 'model'
|
|
1431
|
+
&& item.recommended_action === 'create_passport_draft'
|
|
1432
|
+
&& String(item.details_received_automatically.registration_flow_state || '').trim() === 'private_draft_required') {
|
|
1433
|
+
return 'Open Draft Path';
|
|
1434
|
+
}
|
|
1430
1435
|
return formatSmartInboxActionValue(item.recommended_action, item.item_type, String(item.details_received_automatically.connectable_model_name || '').trim());
|
|
1431
1436
|
}
|
|
1432
1437
|
function printInboxGroup(label, items) {
|
|
@@ -2709,6 +2714,9 @@ async function run() {
|
|
|
2709
2714
|
else if (message === 'SIMILAR_PASSPORT_EXISTS') {
|
|
2710
2715
|
console.error('A similar or existing passport already exists in your Forkit.dev account. Open inbox and review the connected/passport match before creating a new draft.');
|
|
2711
2716
|
}
|
|
2717
|
+
else if (message === 'INVALID_DRAFT_VISIBILITY') {
|
|
2718
|
+
console.error('This registration must start as a private draft. Review it in inbox/start first, or choose publish only when Forkit is ready to finish the passport.');
|
|
2719
|
+
}
|
|
2712
2720
|
else if (message.startsWith('DRAFT_CREATE_FAILED:')) {
|
|
2713
2721
|
console.error(`[forkit-connect] Draft creation failed (${message.split(':')[1]}).`);
|
|
2714
2722
|
}
|
|
@@ -2847,6 +2855,8 @@ async function run() {
|
|
|
2847
2855
|
const detailKeys = [
|
|
2848
2856
|
'verification_summary',
|
|
2849
2857
|
'limitations_summary',
|
|
2858
|
+
'registration_guidance',
|
|
2859
|
+
'registration_error_message',
|
|
2850
2860
|
'scope_suggestion',
|
|
2851
2861
|
'scope_mismatch_reason',
|
|
2852
2862
|
'connectable_model_name',
|
|
@@ -3871,6 +3881,8 @@ async function run() {
|
|
|
3871
3881
|
return 'A backend draft already exists for this model. No duplicate draft created.';
|
|
3872
3882
|
if (raw === 'SIMILAR_PASSPORT_EXISTS')
|
|
3873
3883
|
return 'A similar or existing passport already exists in your Forkit.dev account. Review existing records before creating a new draft.';
|
|
3884
|
+
if (raw === 'INVALID_DRAFT_VISIBILITY')
|
|
3885
|
+
return 'This registration must start as a private draft. Review it in inbox/start first, or choose publish only when Forkit is ready to finish the passport.';
|
|
3874
3886
|
if (raw === 'WORKSPACE_PROJECT_BINDING_REQUIRED')
|
|
3875
3887
|
return 'No governed workspace/project scope is linked yet. Select or create scope first.';
|
|
3876
3888
|
if (raw === 'DRAFT_CREATION_NOT_ALLOWED_BY_BINDING')
|
|
@@ -4538,6 +4550,11 @@ async function run() {
|
|
|
4538
4550
|
process.exitCode = 2;
|
|
4539
4551
|
return;
|
|
4540
4552
|
}
|
|
4553
|
+
if (message === 'INVALID_DRAFT_VISIBILITY') {
|
|
4554
|
+
console.error('This registration must start as a private draft. Review it in inbox/start first, or choose publish only when Forkit is ready to finish the passport.');
|
|
4555
|
+
process.exitCode = 2;
|
|
4556
|
+
return;
|
|
4557
|
+
}
|
|
4541
4558
|
if (message.startsWith('DRAFT_CREATE_FAILED:')) {
|
|
4542
4559
|
console.error(`[forkit-connect] Draft creation failed (${message.split(':')[1]}).`);
|
|
4543
4560
|
process.exitCode = 2;
|
package/dist/launcher.js
CHANGED
|
@@ -535,6 +535,16 @@ function normalizeDiscoveryRegistrationFailure(message) {
|
|
|
535
535
|
message: 'A similar passport already exists in Forkit. Review existing records before creating a new one.',
|
|
536
536
|
};
|
|
537
537
|
}
|
|
538
|
+
if (normalized === 'INVALID_DRAFT_VISIBILITY') {
|
|
539
|
+
return {
|
|
540
|
+
code: normalized,
|
|
541
|
+
message: 'This registration needs to start as a private draft before it can be published.',
|
|
542
|
+
nextActions: [
|
|
543
|
+
'Keep the item in review or open the draft path first.',
|
|
544
|
+
'Choose publish only when Forkit is ready to finish the passport.',
|
|
545
|
+
],
|
|
546
|
+
};
|
|
547
|
+
}
|
|
538
548
|
if (normalized === 'WORKSPACE_PROJECT_BINDING_REQUIRED') {
|
|
539
549
|
return {
|
|
540
550
|
code: normalized,
|
|
@@ -666,6 +676,9 @@ function buildDiscovery(service) {
|
|
|
666
676
|
const registeredPassportName = getInboxDetailText(entry, 'registered_passport_name');
|
|
667
677
|
const scopeSuggestion = getInboxDetailText(entry, 'scope_suggestion');
|
|
668
678
|
const verificationSummary = getInboxDetailText(entry, 'verification_summary');
|
|
679
|
+
const registrationState = getInboxDetailText(entry, 'registration_flow_state');
|
|
680
|
+
const registrationGuidance = getInboxDetailText(entry, 'registration_guidance')
|
|
681
|
+
?? getInboxDetailText(entry, 'registration_error_message');
|
|
669
682
|
const matchReason = entry.match_reason;
|
|
670
683
|
const draftPending = binding?.status === 'pending';
|
|
671
684
|
let statusLabel = 'Ready to register';
|
|
@@ -687,6 +700,13 @@ function buildDiscovery(service) {
|
|
|
687
700
|
actionLabel = 'Review';
|
|
688
701
|
actionTone = 'accent';
|
|
689
702
|
}
|
|
703
|
+
else if (registrationState === 'private_draft_required') {
|
|
704
|
+
statusLabel = 'Draft first';
|
|
705
|
+
statusMeta = registrationGuidance ?? 'This model needs to go through the private draft path before publishing.';
|
|
706
|
+
statusTone = 'warn';
|
|
707
|
+
actionLabel = 'Review';
|
|
708
|
+
actionTone = 'accent';
|
|
709
|
+
}
|
|
690
710
|
else if (group === 'connected') {
|
|
691
711
|
statusLabel = 'Registered';
|
|
692
712
|
statusMeta = registeredPassportName
|
|
@@ -7581,9 +7601,11 @@ function renderLauncherHtml(launcherToken) {
|
|
|
7581
7601
|
actionSummary: result && result.code === 'GOVERNED_PASSPORT_CAPACITY_REACHED'
|
|
7582
7602
|
? 'Capacity full · use an existing passport or free space'
|
|
7583
7603
|
: result && result.code === 'DRAFT_LIMIT_REACHED'
|
|
7584
|
-
|
|
7604
|
+
? 'Draft capacity full · use an existing passport, clear a draft, or upgrade'
|
|
7585
7605
|
: result && result.code === 'SIMILAR_PASSPORT_EXISTS'
|
|
7586
7606
|
? 'Matching passport exists · reuse it instead of creating another'
|
|
7607
|
+
: result && result.code === 'INVALID_DRAFT_VISIBILITY'
|
|
7608
|
+
? 'Draft first · keep this registration private until it is ready to publish'
|
|
7587
7609
|
: result && (result.code === 'WORKSPACE_PROJECT_BINDING_REQUIRED' || result.code === 'DRAFT_CREATION_NOT_ALLOWED_BY_BINDING')
|
|
7588
7610
|
? 'Scope required · choose workspace and project'
|
|
7589
7611
|
: null,
|
package/dist/v1/service.d.ts
CHANGED
|
@@ -408,6 +408,7 @@ export declare class ConnectV1Service {
|
|
|
408
408
|
private hasExactBoundPassportForModel;
|
|
409
409
|
private runtimeHasExactBoundModelDuplicate;
|
|
410
410
|
private clearModelReviewDeferral;
|
|
411
|
+
private updateDetectedModelRegistrationHint;
|
|
411
412
|
private buildPassportMatchSuggestionForModel;
|
|
412
413
|
private normalizeRemotePassportList;
|
|
413
414
|
private loadRemoteWorkspaceNameMaps;
|
package/dist/v1/service.js
CHANGED
|
@@ -2287,6 +2287,33 @@ class ConnectV1Service {
|
|
|
2287
2287
|
: item);
|
|
2288
2288
|
this.stateStore.replaceDetectedModels(nextModels);
|
|
2289
2289
|
}
|
|
2290
|
+
updateDetectedModelRegistrationHint(model, input) {
|
|
2291
|
+
const nextModels = this.stateStore.readState().detected_models.map((item) => {
|
|
2292
|
+
if (item.discoveryHash !== model.discoveryHash) {
|
|
2293
|
+
return item;
|
|
2294
|
+
}
|
|
2295
|
+
const nextMetadata = {
|
|
2296
|
+
...(item.metadata && typeof item.metadata === 'object' ? item.metadata : {}),
|
|
2297
|
+
};
|
|
2298
|
+
const assignOrDelete = (key, value) => {
|
|
2299
|
+
if (value === null || value === undefined || value === '') {
|
|
2300
|
+
delete nextMetadata[key];
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
nextMetadata[key] = value;
|
|
2304
|
+
};
|
|
2305
|
+
assignOrDelete('tracking_status', input.trackingStatus ?? null);
|
|
2306
|
+
assignOrDelete('registration_error_code', input.errorCode ?? null);
|
|
2307
|
+
assignOrDelete('registration_error_message', input.errorMessage ?? null);
|
|
2308
|
+
assignOrDelete('registration_error_status', typeof input.errorStatus === 'number' ? input.errorStatus : null);
|
|
2309
|
+
assignOrDelete('registration_guidance', input.guidance ?? null);
|
|
2310
|
+
return {
|
|
2311
|
+
...item,
|
|
2312
|
+
metadata: nextMetadata,
|
|
2313
|
+
};
|
|
2314
|
+
});
|
|
2315
|
+
this.stateStore.replaceDetectedModels(nextModels);
|
|
2316
|
+
}
|
|
2290
2317
|
buildPassportMatchSuggestionForModel(state, model, runtimePassport) {
|
|
2291
2318
|
const registrationKey = (0, discovery_1.buildModelRegistrationKey)(model, state.runtime_identity.runtimeId);
|
|
2292
2319
|
const candidates = state.model_bindings
|
|
@@ -4305,6 +4332,10 @@ class ConnectV1Service {
|
|
|
4305
4332
|
const observedProjectId = normalizeDisplayText(modelMetadata.projectId ?? modelMetadata.project_id);
|
|
4306
4333
|
const scopeSuggestion = this.resolveScopeSuggestion(refreshedState, observedWorkspaceId, observedProjectId);
|
|
4307
4334
|
const itemId = this.buildInboxItemId('model', model.discoveryHash);
|
|
4335
|
+
const registrationTrackingStatus = normalizeDisplayText(modelMetadata.tracking_status);
|
|
4336
|
+
const registrationErrorMessage = normalizeDisplayText(modelMetadata.registration_error_message);
|
|
4337
|
+
const registrationErrorCode = normalizeDisplayText(modelMetadata.registration_error_code);
|
|
4338
|
+
const registrationGuidance = normalizeDisplayText(modelMetadata.registration_guidance);
|
|
4308
4339
|
const recommendedAction = binding?.status === 'bound'
|
|
4309
4340
|
? 'open_on_forkit'
|
|
4310
4341
|
: suggestion.match_confidence === 'medium'
|
|
@@ -4371,6 +4402,10 @@ class ConnectV1Service {
|
|
|
4371
4402
|
registered_workspace_name: binding?.workspaceName ?? null,
|
|
4372
4403
|
registered_project_name: binding?.projectName ?? null,
|
|
4373
4404
|
remote_match_source: binding?.remoteMatchSource ?? null,
|
|
4405
|
+
registration_flow_state: registrationTrackingStatus,
|
|
4406
|
+
registration_error_message: registrationErrorMessage,
|
|
4407
|
+
registration_error_code: registrationErrorCode,
|
|
4408
|
+
registration_guidance: registrationGuidance,
|
|
4374
4409
|
verification_summary: verification.verification,
|
|
4375
4410
|
limitations_summary: verification.limitations,
|
|
4376
4411
|
review_disposition: reviewDisposition,
|
|
@@ -7793,8 +7828,18 @@ class ConnectV1Service {
|
|
|
7793
7828
|
const soloDraftAllowed = draftBindingStatus.allowed && draftBindingStatus.reasonCode === 'solo_passport_draft_allowed';
|
|
7794
7829
|
const localScopedDraftAllowed = draftBindingStatus.allowed && draftBindingStatus.reasonCode === 'local_workspace_project_draft_allowed';
|
|
7795
7830
|
const model = this.resolveModelSelection(selector, state);
|
|
7796
|
-
const
|
|
7831
|
+
const requestedDestination = options?.destination === 'passport' ? 'passport' : 'draft';
|
|
7832
|
+
const requestedVisibility = options?.visibility === 'public' && requestedDestination === 'passport'
|
|
7833
|
+
? 'public'
|
|
7834
|
+
: 'private';
|
|
7797
7835
|
this.clearModelReviewDeferral(model);
|
|
7836
|
+
this.updateDetectedModelRegistrationHint(model, {
|
|
7837
|
+
trackingStatus: null,
|
|
7838
|
+
errorCode: null,
|
|
7839
|
+
errorMessage: null,
|
|
7840
|
+
errorStatus: null,
|
|
7841
|
+
guidance: null,
|
|
7842
|
+
});
|
|
7798
7843
|
const { payload, registrationKey } = this.buildConnectDraftPayload(model, state, draftScope, {
|
|
7799
7844
|
visibility: requestedVisibility,
|
|
7800
7845
|
});
|
|
@@ -7802,7 +7847,7 @@ class ConnectV1Service {
|
|
|
7802
7847
|
const binding = this.findBindingForModel(this.stateStore.readState(), model, registrationKey);
|
|
7803
7848
|
const pendingQueue = this.findPendingQueueItem(state, model, registrationKey);
|
|
7804
7849
|
const shouldPublishImmediately = requestedVisibility === 'public'
|
|
7805
|
-
&& (
|
|
7850
|
+
&& (requestedDestination === 'passport' || (soloDraftAllowed && requestedDestination !== 'draft'));
|
|
7806
7851
|
const bindingWithRuntime = binding ? {
|
|
7807
7852
|
...binding,
|
|
7808
7853
|
runtimeGaid: binding.runtimeGaid ?? runtimePassport?.runtime_gaid ?? null,
|
|
@@ -7936,6 +7981,16 @@ class ConnectV1Service {
|
|
|
7936
7981
|
const api = this.getApiClient(state);
|
|
7937
7982
|
const result = await api.createPassportDraft(payload);
|
|
7938
7983
|
if (!result.ok) {
|
|
7984
|
+
const backendCode = extractApiErrorCode(result.body) || `DRAFT_CREATE_FAILED:${result.status}`;
|
|
7985
|
+
if (backendCode === 'INVALID_DRAFT_VISIBILITY') {
|
|
7986
|
+
this.updateDetectedModelRegistrationHint(model, {
|
|
7987
|
+
trackingStatus: 'private_draft_required',
|
|
7988
|
+
errorCode: backendCode,
|
|
7989
|
+
errorMessage: 'This registration must start as a private draft before it can be published.',
|
|
7990
|
+
errorStatus: result.status,
|
|
7991
|
+
guidance: 'Open the review flow and continue through the private draft path first.',
|
|
7992
|
+
});
|
|
7993
|
+
}
|
|
7939
7994
|
this.observeBackendCommunicationState({
|
|
7940
7995
|
passportGaid: bindingWithRuntime?.gaid ?? null,
|
|
7941
7996
|
runtimeGaid: runtimePassport?.runtime_gaid ?? null,
|
|
@@ -7944,7 +7999,7 @@ class ConnectV1Service {
|
|
|
7944
7999
|
body: result.body,
|
|
7945
8000
|
source: 'draft_sync',
|
|
7946
8001
|
});
|
|
7947
|
-
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' :
|
|
8002
|
+
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' : backendCode);
|
|
7948
8003
|
}
|
|
7949
8004
|
const parsed = this.parseDraftResponse(result);
|
|
7950
8005
|
let finalGaid = parsed.gaid;
|
package/dist/v1/state.js
CHANGED
|
@@ -938,8 +938,30 @@ class LocalStateStore {
|
|
|
938
938
|
const seen = new Map();
|
|
939
939
|
for (const model of models) {
|
|
940
940
|
const existing = state.detected_models.find((item) => item.discoveryHash === model.discoveryHash);
|
|
941
|
+
const nextMetadata = model.metadata && typeof model.metadata === 'object'
|
|
942
|
+
? { ...model.metadata }
|
|
943
|
+
: {};
|
|
944
|
+
const existingMetadata = existing?.metadata && typeof existing.metadata === 'object'
|
|
945
|
+
? existing.metadata
|
|
946
|
+
: null;
|
|
947
|
+
if (existingMetadata) {
|
|
948
|
+
for (const key of [
|
|
949
|
+
'draft_id',
|
|
950
|
+
'passport_gaid',
|
|
951
|
+
'tracking_status',
|
|
952
|
+
'registration_error_code',
|
|
953
|
+
'registration_error_message',
|
|
954
|
+
'registration_error_status',
|
|
955
|
+
'registration_guidance',
|
|
956
|
+
]) {
|
|
957
|
+
if (!Object.prototype.hasOwnProperty.call(nextMetadata, key) && Object.prototype.hasOwnProperty.call(existingMetadata, key)) {
|
|
958
|
+
nextMetadata[key] = existingMetadata[key];
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
941
962
|
seen.set(model.discoveryHash, {
|
|
942
963
|
...model,
|
|
964
|
+
metadata: nextMetadata,
|
|
943
965
|
status: model.status === 'ignored' || model.status === 'bound'
|
|
944
966
|
? model.status
|
|
945
967
|
: existing?.status === 'ignored' || existing?.status === 'bound'
|