forkit-connect 0.1.7 → 0.1.9
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 +15 -1
- package/dist/launcher.js +14 -1
- package/dist/v1/service.d.ts +2 -0
- package/dist/v1/service.js +59 -1
- 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) {
|
|
@@ -1463,6 +1468,7 @@ function printConnectStatusOverview(status) {
|
|
|
1463
1468
|
paused_session_count: status.paused_session_count,
|
|
1464
1469
|
revoked_session_count: status.revoked_session_count,
|
|
1465
1470
|
credential_reconnect_needed: status.credential_reconnect_needed,
|
|
1471
|
+
draft_first_count: status.draft_first_count,
|
|
1466
1472
|
ready_to_connect_count: status.ready_to_connect_count,
|
|
1467
1473
|
needs_confirmation_count: status.needs_confirmation_count,
|
|
1468
1474
|
connected_count: status.connected_count,
|
|
@@ -1473,12 +1479,13 @@ function printConnectStatusOverview(status) {
|
|
|
1473
1479
|
}, null, 2));
|
|
1474
1480
|
}
|
|
1475
1481
|
function printPublicStatusOverview(status) {
|
|
1482
|
+
const otherReadyCount = Math.max(0, status.ready_to_connect_count - status.draft_first_count);
|
|
1476
1483
|
console.log('[forkit-connect] Status');
|
|
1477
1484
|
console.log(`- device=${status.device_paired ? 'paired' : 'approval pending'}`);
|
|
1478
1485
|
console.log(`- scope=${status.workspace_id && status.project_id ? `${status.workspace_id} / ${status.project_id}` : 'not selected'}`);
|
|
1479
1486
|
console.log(`- daemon=${status.daemon_status}`);
|
|
1480
1487
|
console.log(`- local inventory=models ${status.models_discovered} · agents ${status.agents_discovered} · runtimes ${status.runtimes_discovered}`);
|
|
1481
|
-
console.log(`- review queue=
|
|
1488
|
+
console.log(`- review queue=draft first ${status.draft_first_count} · ready ${otherReadyCount} · needs review ${status.needs_confirmation_count}`);
|
|
1482
1489
|
console.log(`- connected records=${status.connected_count}`);
|
|
1483
1490
|
console.log(`- pending runtime sync=${status.c2_sync_pending}`);
|
|
1484
1491
|
console.log(`- privacy=${status.privacy_mode}`);
|
|
@@ -1747,8 +1754,11 @@ async function run() {
|
|
|
1747
1754
|
preferSnapshot: true,
|
|
1748
1755
|
refreshInBackground: false,
|
|
1749
1756
|
});
|
|
1757
|
+
const draftFirstCount = inbox.groups.ready_to_connect.filter((item) => (item.item_type === 'model'
|
|
1758
|
+
&& String(item.details_received_automatically.registration_flow_state || '').trim() === 'private_draft_required')).length;
|
|
1750
1759
|
return {
|
|
1751
1760
|
...overview,
|
|
1761
|
+
draft_first_count: draftFirstCount,
|
|
1752
1762
|
ready_to_connect_count: inbox.summary.ready_to_connect_count,
|
|
1753
1763
|
needs_confirmation_count: inbox.summary.needs_confirmation_count,
|
|
1754
1764
|
connected_count: inbox.summary.connected_count,
|
|
@@ -2070,6 +2080,7 @@ async function run() {
|
|
|
2070
2080
|
? 'Local workspace/project scope is cached on this device, but account login is required before governed actions can continue.'
|
|
2071
2081
|
: 'Account login is required before governed workspace/project actions can continue.',
|
|
2072
2082
|
daemon_status: overview.daemon_status,
|
|
2083
|
+
draft_first_count: overview.draft_first_count,
|
|
2073
2084
|
ready_to_connect_count: overview.ready_to_connect_count,
|
|
2074
2085
|
needs_confirmation_count: overview.needs_confirmation_count,
|
|
2075
2086
|
connected_count: overview.connected_count,
|
|
@@ -2113,6 +2124,7 @@ async function run() {
|
|
|
2113
2124
|
{
|
|
2114
2125
|
title: 'Queue',
|
|
2115
2126
|
lines: [
|
|
2127
|
+
shellLine('Draft-first review', payload.draft_first_count),
|
|
2116
2128
|
shellLine('Ready to connect', payload.ready_to_connect_count),
|
|
2117
2129
|
shellLine('Needs confirmation', payload.needs_confirmation_count),
|
|
2118
2130
|
shellLine('Connected', payload.connected_count),
|
|
@@ -2850,6 +2862,8 @@ async function run() {
|
|
|
2850
2862
|
const detailKeys = [
|
|
2851
2863
|
'verification_summary',
|
|
2852
2864
|
'limitations_summary',
|
|
2865
|
+
'registration_guidance',
|
|
2866
|
+
'registration_error_message',
|
|
2853
2867
|
'scope_suggestion',
|
|
2854
2868
|
'scope_mismatch_reason',
|
|
2855
2869
|
'connectable_model_name',
|
package/dist/launcher.js
CHANGED
|
@@ -676,6 +676,9 @@ function buildDiscovery(service) {
|
|
|
676
676
|
const registeredPassportName = getInboxDetailText(entry, 'registered_passport_name');
|
|
677
677
|
const scopeSuggestion = getInboxDetailText(entry, 'scope_suggestion');
|
|
678
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');
|
|
679
682
|
const matchReason = entry.match_reason;
|
|
680
683
|
const draftPending = binding?.status === 'pending';
|
|
681
684
|
let statusLabel = 'Ready to register';
|
|
@@ -697,6 +700,13 @@ function buildDiscovery(service) {
|
|
|
697
700
|
actionLabel = 'Review';
|
|
698
701
|
actionTone = 'accent';
|
|
699
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
|
+
}
|
|
700
710
|
else if (group === 'connected') {
|
|
701
711
|
statusLabel = 'Registered';
|
|
702
712
|
statusMeta = registeredPassportName
|
|
@@ -902,6 +912,9 @@ function buildDiscovery(service) {
|
|
|
902
912
|
const modelItems = items.filter((item) => item.kind === 'model');
|
|
903
913
|
const agentItems = items.filter((item) => item.kind === 'agent');
|
|
904
914
|
const runtimeItems = items.filter((item) => item.kind === 'runtime');
|
|
915
|
+
const draftFirstCount = inbox.groups.ready_to_connect.filter((item) => (item.item_type === 'model'
|
|
916
|
+
&& String(item.details_received_automatically.registration_flow_state || '').trim() === 'private_draft_required')).length;
|
|
917
|
+
const otherReadyCount = Math.max(0, inbox.summary.ready_to_connect_count - draftFirstCount);
|
|
905
918
|
return {
|
|
906
919
|
ok: true,
|
|
907
920
|
generatedAt: new Date().toISOString(),
|
|
@@ -916,7 +929,7 @@ function buildDiscovery(service) {
|
|
|
916
929
|
localDetection: state.detected_runtimes.length > 0 || state.detected_models.length > 0 ? 'active' : 'attention',
|
|
917
930
|
metadataExtraction: state.detected_models.length > 0 ? 'active' : 'attention',
|
|
918
931
|
duplicateMatching: inbox.existing_passport_match_candidates.length > 0 || state.model_bindings.length > 0 ? 'active' : 'attention',
|
|
919
|
-
passportReadiness: `${
|
|
932
|
+
passportReadiness: `${draftFirstCount} draft-first · ${otherReadyCount} ready · ${inbox.summary.needs_confirmation_count} review · ${inbox.summary.connected_count} linked`,
|
|
920
933
|
},
|
|
921
934
|
groups: {
|
|
922
935
|
ready_to_connect: inbox.groups.ready_to_connect.length,
|
package/dist/v1/service.d.ts
CHANGED
|
@@ -253,6 +253,7 @@ export interface ConnectStatusOverview {
|
|
|
253
253
|
paused_session_count: number;
|
|
254
254
|
revoked_session_count: number;
|
|
255
255
|
credential_reconnect_needed: boolean;
|
|
256
|
+
draft_first_count: number;
|
|
256
257
|
ready_to_connect_count: number;
|
|
257
258
|
needs_confirmation_count: number;
|
|
258
259
|
connected_count: number;
|
|
@@ -408,6 +409,7 @@ export declare class ConnectV1Service {
|
|
|
408
409
|
private hasExactBoundPassportForModel;
|
|
409
410
|
private runtimeHasExactBoundModelDuplicate;
|
|
410
411
|
private clearModelReviewDeferral;
|
|
412
|
+
private updateDetectedModelRegistrationHint;
|
|
411
413
|
private buildPassportMatchSuggestionForModel;
|
|
412
414
|
private normalizeRemotePassportList;
|
|
413
415
|
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,
|
|
@@ -4690,6 +4725,11 @@ class ConnectV1Service {
|
|
|
4690
4725
|
const state = this.stateStore.readState();
|
|
4691
4726
|
const includeInbox = options?.includeInbox !== false;
|
|
4692
4727
|
const inbox = includeInbox ? this.buildSmartRegistrationInbox() : null;
|
|
4728
|
+
const draftFirstCount = inbox
|
|
4729
|
+
? inbox.groups.ready_to_connect.filter((item) => (item.item_type === 'model'
|
|
4730
|
+
&& String(item.details_received_automatically.registration_flow_state || '').trim() === 'private_draft_required')).length
|
|
4731
|
+
: state.detected_models.filter((item) => (item.status !== 'ignored'
|
|
4732
|
+
&& String((item.metadata && typeof item.metadata === 'object' ? item.metadata : {}).tracking_status || '').trim() === 'private_draft_required')).length;
|
|
4693
4733
|
const sessionSummary = this.getC2SessionSummary();
|
|
4694
4734
|
const binding = this.getEffectiveBindingState(state);
|
|
4695
4735
|
const bindingReconnectRequired = this.bindingRequiresReconnect(state);
|
|
@@ -4709,6 +4749,7 @@ class ConnectV1Service {
|
|
|
4709
4749
|
paused_session_count: sessionSummary.paused_session_count,
|
|
4710
4750
|
revoked_session_count: sessionSummary.revoked_session_count,
|
|
4711
4751
|
credential_reconnect_needed: bindingReconnectRequired || sessionSummary.credential_reconnect_needed,
|
|
4752
|
+
draft_first_count: draftFirstCount,
|
|
4712
4753
|
ready_to_connect_count: inbox?.summary.ready_to_connect_count ?? discoveredModels,
|
|
4713
4754
|
needs_confirmation_count: inbox?.summary.needs_confirmation_count ?? 0,
|
|
4714
4755
|
connected_count: inbox?.summary.connected_count ?? connectedCount,
|
|
@@ -7798,6 +7839,13 @@ class ConnectV1Service {
|
|
|
7798
7839
|
? 'public'
|
|
7799
7840
|
: 'private';
|
|
7800
7841
|
this.clearModelReviewDeferral(model);
|
|
7842
|
+
this.updateDetectedModelRegistrationHint(model, {
|
|
7843
|
+
trackingStatus: null,
|
|
7844
|
+
errorCode: null,
|
|
7845
|
+
errorMessage: null,
|
|
7846
|
+
errorStatus: null,
|
|
7847
|
+
guidance: null,
|
|
7848
|
+
});
|
|
7801
7849
|
const { payload, registrationKey } = this.buildConnectDraftPayload(model, state, draftScope, {
|
|
7802
7850
|
visibility: requestedVisibility,
|
|
7803
7851
|
});
|
|
@@ -7939,6 +7987,16 @@ class ConnectV1Service {
|
|
|
7939
7987
|
const api = this.getApiClient(state);
|
|
7940
7988
|
const result = await api.createPassportDraft(payload);
|
|
7941
7989
|
if (!result.ok) {
|
|
7990
|
+
const backendCode = extractApiErrorCode(result.body) || `DRAFT_CREATE_FAILED:${result.status}`;
|
|
7991
|
+
if (backendCode === 'INVALID_DRAFT_VISIBILITY') {
|
|
7992
|
+
this.updateDetectedModelRegistrationHint(model, {
|
|
7993
|
+
trackingStatus: 'private_draft_required',
|
|
7994
|
+
errorCode: backendCode,
|
|
7995
|
+
errorMessage: 'This registration must start as a private draft before it can be published.',
|
|
7996
|
+
errorStatus: result.status,
|
|
7997
|
+
guidance: 'Open the review flow and continue through the private draft path first.',
|
|
7998
|
+
});
|
|
7999
|
+
}
|
|
7942
8000
|
this.observeBackendCommunicationState({
|
|
7943
8001
|
passportGaid: bindingWithRuntime?.gaid ?? null,
|
|
7944
8002
|
runtimeGaid: runtimePassport?.runtime_gaid ?? null,
|
|
@@ -7947,7 +8005,7 @@ class ConnectV1Service {
|
|
|
7947
8005
|
body: result.body,
|
|
7948
8006
|
source: 'draft_sync',
|
|
7949
8007
|
});
|
|
7950
|
-
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' :
|
|
8008
|
+
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' : backendCode);
|
|
7951
8009
|
}
|
|
7952
8010
|
const parsed = this.parseDraftResponse(result);
|
|
7953
8011
|
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'
|