forkit-connect 0.1.31 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/v1/heartbeat.js +17 -1
- package/dist/v1/service.js +55 -8
- package/package.json +1 -3
package/README.md
CHANGED
|
@@ -123,7 +123,7 @@ Then install the generated tarball into a clean directory:
|
|
|
123
123
|
mkdir -p /tmp/forkit-connect-smoke
|
|
124
124
|
cd /tmp/forkit-connect-smoke
|
|
125
125
|
npm init -y
|
|
126
|
-
npm install /absolute/path/to/forkit-connect
|
|
126
|
+
npm install /absolute/path/to/forkit-connect-<version>.tgz
|
|
127
127
|
npx forkit-connect --help
|
|
128
128
|
npx forkit-connect status
|
|
129
129
|
npx forkit-connect inbox
|
package/dist/v1/heartbeat.js
CHANGED
|
@@ -137,9 +137,25 @@ function listBoundBindings(state) {
|
|
|
137
137
|
if (!Array.isArray(state.model_bindings)) {
|
|
138
138
|
return [];
|
|
139
139
|
}
|
|
140
|
+
const detectedModelKeys = new Set(state.detected_models.map((item) => `${item.model}#${item.digest}`));
|
|
141
|
+
const scoreBinding = (binding) => {
|
|
142
|
+
let score = 0;
|
|
143
|
+
if (detectedModelKeys.has(binding.modelKey))
|
|
144
|
+
score += 4;
|
|
145
|
+
if (binding.runtimeGaid)
|
|
146
|
+
score += 2;
|
|
147
|
+
if (binding.runtimeSignalKeyPresent)
|
|
148
|
+
score += 1;
|
|
149
|
+
return score;
|
|
150
|
+
};
|
|
140
151
|
return state.model_bindings
|
|
141
152
|
.filter((item) => item.status === 'bound' && typeof item.gaid === 'string' && item.gaid.trim())
|
|
142
|
-
.sort((left, right) =>
|
|
153
|
+
.sort((left, right) => {
|
|
154
|
+
const scoreDelta = scoreBinding(right) - scoreBinding(left);
|
|
155
|
+
if (scoreDelta !== 0)
|
|
156
|
+
return scoreDelta;
|
|
157
|
+
return String(right.updatedAt || '').localeCompare(String(left.updatedAt || ''));
|
|
158
|
+
})
|
|
143
159
|
.map((binding) => ({
|
|
144
160
|
binding,
|
|
145
161
|
detectedModel: state.detected_models.find((item) => `${item.model}#${item.digest}` === binding.modelKey),
|
package/dist/v1/service.js
CHANGED
|
@@ -309,7 +309,8 @@ function canonicalJson(value) {
|
|
|
309
309
|
return JSON.stringify(canonicalize(value));
|
|
310
310
|
}
|
|
311
311
|
function modelNameFromKey(modelKeyValue) {
|
|
312
|
-
|
|
312
|
+
const rawName = String(modelKeyValue || '').split('#')[0]?.trim() || 'unknown';
|
|
313
|
+
return rawName.startsWith('model:') ? rawName.slice('model:'.length) : rawName;
|
|
313
314
|
}
|
|
314
315
|
function modelDigestFromKey(modelKeyValue) {
|
|
315
316
|
const digest = String(modelKeyValue || '').split('#')[1]?.trim() || '';
|
|
@@ -2832,7 +2833,26 @@ class ConnectV1Service {
|
|
|
2832
2833
|
};
|
|
2833
2834
|
}
|
|
2834
2835
|
getPrimaryBoundBinding(state) {
|
|
2835
|
-
|
|
2836
|
+
const detectedModelKeys = new Set(state.detected_models.map((item) => `${item.model}#${item.digest}`));
|
|
2837
|
+
const scoreBinding = (binding) => {
|
|
2838
|
+
let score = 0;
|
|
2839
|
+
if (detectedModelKeys.has(binding.modelKey))
|
|
2840
|
+
score += 4;
|
|
2841
|
+
if (binding.runtimeGaid)
|
|
2842
|
+
score += 2;
|
|
2843
|
+
if (binding.runtimeSignalKeyPresent)
|
|
2844
|
+
score += 1;
|
|
2845
|
+
return score;
|
|
2846
|
+
};
|
|
2847
|
+
return state.model_bindings
|
|
2848
|
+
.filter((binding) => binding.status === 'bound' && typeof binding.gaid === 'string' && binding.gaid.trim())
|
|
2849
|
+
.sort((left, right) => {
|
|
2850
|
+
const scoreDelta = scoreBinding(right) - scoreBinding(left);
|
|
2851
|
+
if (scoreDelta !== 0)
|
|
2852
|
+
return scoreDelta;
|
|
2853
|
+
return String(right.updatedAt || '').localeCompare(String(left.updatedAt || ''));
|
|
2854
|
+
})
|
|
2855
|
+
.at(0);
|
|
2836
2856
|
}
|
|
2837
2857
|
setRuntimeSignalApiKeyForGaid(gaid, apiKey) {
|
|
2838
2858
|
if (!gaid || !apiKey)
|
|
@@ -3240,7 +3260,8 @@ class ConnectV1Service {
|
|
|
3240
3260
|
const { workspaceId, projectId } = this.resolveRuntimeRunScope(state, gaid);
|
|
3241
3261
|
const runtimeMetadata = isRecord(input.metadata) ? input.metadata : {};
|
|
3242
3262
|
const steps = Array.isArray(input.steps) ? input.steps.filter((step) => isRecord(step)) : [];
|
|
3243
|
-
|
|
3263
|
+
const client = this.getApiClientWithSessionToken(apiKey);
|
|
3264
|
+
return client.pushRuntimeRunLog({
|
|
3244
3265
|
gaid,
|
|
3245
3266
|
apiKey,
|
|
3246
3267
|
schemaVersion: 'runtime.run.v1',
|
|
@@ -7080,6 +7101,7 @@ class ConnectV1Service {
|
|
|
7080
7101
|
// Don't consume a retry_count increment here — this is a throttle, not a real failure.
|
|
7081
7102
|
return;
|
|
7082
7103
|
}
|
|
7104
|
+
attempted += 1;
|
|
7083
7105
|
if (!event.passport_gaid) {
|
|
7084
7106
|
if (event.event_type === 'connect_runtime_unavailable') {
|
|
7085
7107
|
this.stateStore.discardC2Event(event.event_id, 'c2_local_only_runtime_unavailable');
|
|
@@ -7169,14 +7191,39 @@ class ConnectV1Service {
|
|
|
7169
7191
|
}
|
|
7170
7192
|
}
|
|
7171
7193
|
const queuedEvents = dedupedEvents.slice(0, C2_SYNC_BATCH_SIZE);
|
|
7172
|
-
|
|
7173
|
-
for (
|
|
7174
|
-
|
|
7194
|
+
const eventsByPassport = new Map();
|
|
7195
|
+
for (const event of queuedEvents) {
|
|
7196
|
+
const groupKey = event.passport_gaid
|
|
7197
|
+
? `passport:${event.passport_gaid}`
|
|
7198
|
+
: `event:${event.event_id}`;
|
|
7199
|
+
const group = eventsByPassport.get(groupKey) ?? [];
|
|
7200
|
+
group.push(event);
|
|
7201
|
+
eventsByPassport.set(groupKey, group);
|
|
7202
|
+
}
|
|
7203
|
+
// Keep throughput across independent passports, but process each passport
|
|
7204
|
+
// sequentially so a credential/governor halt leaves later events untouched.
|
|
7205
|
+
while (eventsByPassport.size > 0) {
|
|
7175
7206
|
if (rateLimitedUntilMs !== null && Date.now() < rateLimitedUntilMs) {
|
|
7176
7207
|
break;
|
|
7177
7208
|
}
|
|
7178
|
-
const
|
|
7179
|
-
|
|
7209
|
+
const round = [];
|
|
7210
|
+
for (const key of [...eventsByPassport.keys()]) {
|
|
7211
|
+
const group = eventsByPassport.get(key);
|
|
7212
|
+
const event = group?.shift();
|
|
7213
|
+
if (event) {
|
|
7214
|
+
round.push(event);
|
|
7215
|
+
}
|
|
7216
|
+
if (!group || group.length === 0) {
|
|
7217
|
+
eventsByPassport.delete(key);
|
|
7218
|
+
}
|
|
7219
|
+
}
|
|
7220
|
+
for (let i = 0; i < round.length; i += C2_FLUSH_CONCURRENCY) {
|
|
7221
|
+
if (rateLimitedUntilMs !== null && Date.now() < rateLimitedUntilMs) {
|
|
7222
|
+
break;
|
|
7223
|
+
}
|
|
7224
|
+
const chunk = round.slice(i, i + C2_FLUSH_CONCURRENCY);
|
|
7225
|
+
await Promise.all(chunk.map(processSingleEvent));
|
|
7226
|
+
}
|
|
7180
7227
|
}
|
|
7181
7228
|
const lastSyncAt = attempted > 0 ? nowIso() : state.last_c2_sync_at;
|
|
7182
7229
|
const lastSyncError = firstError;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forkit-connect",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.33",
|
|
4
4
|
"description": "Forkit Connect Local Engine - The Global AI Governance Fabric",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
"cors": "^2.8.6",
|
|
35
35
|
"express": "^4.19.2",
|
|
36
36
|
"ps-list": "^8.1.1",
|
|
37
|
-
"uuid": "^10.0.0",
|
|
38
37
|
"ws": "^8.16.0",
|
|
39
38
|
"zod": "^3.22.0"
|
|
40
39
|
},
|
|
@@ -43,7 +42,6 @@
|
|
|
43
42
|
"@types/cors": "^2.8.19",
|
|
44
43
|
"@types/express": "^4.17.21",
|
|
45
44
|
"@types/node": "^20.0.0",
|
|
46
|
-
"@types/uuid": "^10.0.0",
|
|
47
45
|
"@types/ws": "^8.5.10",
|
|
48
46
|
"typescript": "^5.0.0"
|
|
49
47
|
},
|