forkit-connect 0.1.5 → 0.1.6
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/QUICKSTART.md +10 -1
- package/README.md +12 -1
- package/dist/cli.js +763 -37
- package/dist/launcher.js +471 -73
- package/dist/resource-meter.d.ts +15 -0
- package/dist/resource-meter.js +60 -0
- package/dist/v1/api.d.ts +41 -0
- package/dist/v1/api.js +57 -0
- package/dist/v1/daemon.js +9 -0
- package/dist/v1/repo-discovery.d.ts +42 -0
- package/dist/v1/repo-discovery.js +206 -0
- package/dist/v1/runtime-activity.d.ts +55 -0
- package/dist/v1/runtime-activity.js +388 -0
- package/dist/v1/runtime-context.d.ts +18 -0
- package/dist/v1/runtime-context.js +96 -0
- package/dist/v1/runtime-editor-activity.d.ts +47 -0
- package/dist/v1/runtime-editor-activity.js +821 -0
- package/dist/v1/runtime-observation-runner.d.ts +49 -0
- package/dist/v1/runtime-observation-runner.js +508 -0
- package/dist/v1/runtime-observer.d.ts +50 -0
- package/dist/v1/runtime-observer.js +867 -0
- package/dist/v1/runtime-registration.d.ts +58 -0
- package/dist/v1/runtime-registration.js +319 -0
- package/dist/v1/service.d.ts +44 -1
- package/dist/v1/service.js +165 -10
- package/dist/v1/state.d.ts +4 -1
- package/dist/v1/state.js +28 -0
- package/dist/v1/types.d.ts +14 -0
- package/package.json +1 -1
package/dist/v1/service.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ConnectV1Service = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
10
|
const node_child_process_1 = require("node:child_process");
|
|
10
11
|
const node_crypto_1 = require("node:crypto");
|
|
@@ -54,6 +55,24 @@ const SMART_INBOX_FRESH_MAX_AGE_MS = 45 * 1000;
|
|
|
54
55
|
function isRecord(value) {
|
|
55
56
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
56
57
|
}
|
|
58
|
+
function extractApiErrorCode(body) {
|
|
59
|
+
if (!isRecord(body))
|
|
60
|
+
return null;
|
|
61
|
+
const directKeys = ['code', 'errorCode', 'error_code'];
|
|
62
|
+
for (const key of directKeys) {
|
|
63
|
+
const value = body[key];
|
|
64
|
+
if (typeof value === 'string' && value.trim())
|
|
65
|
+
return value.trim();
|
|
66
|
+
}
|
|
67
|
+
if (isRecord(body.error)) {
|
|
68
|
+
for (const key of directKeys) {
|
|
69
|
+
const value = body.error[key];
|
|
70
|
+
if (typeof value === 'string' && value.trim())
|
|
71
|
+
return value.trim();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
57
76
|
function smartInboxItemTimestamp(item) {
|
|
58
77
|
const details = isRecord(item.details_received_automatically) ? item.details_received_automatically : {};
|
|
59
78
|
const rawTimestamp = [
|
|
@@ -583,6 +602,7 @@ class ConnectV1Service {
|
|
|
583
602
|
this.credentialStore = new credential_store_1.ConnectCredentialStore(this.stateStore.getPaths().stateDir, options?.credentialBackend, options?.legacyCredentialBackend);
|
|
584
603
|
this.credentialStore.migrateLegacyPlaintextFile();
|
|
585
604
|
this.migrateLegacyCredentials();
|
|
605
|
+
this.syncRuntimeIdentityMetadata();
|
|
586
606
|
this.syncIdentityFromLocalState();
|
|
587
607
|
this.syncServiceEntitlements();
|
|
588
608
|
}
|
|
@@ -1203,6 +1223,7 @@ class ConnectV1Service {
|
|
|
1203
1223
|
return entitlements;
|
|
1204
1224
|
}
|
|
1205
1225
|
syncIdentityFromLocalState() {
|
|
1226
|
+
this.syncRuntimeIdentityMetadata();
|
|
1206
1227
|
const state = this.stateStore.readState();
|
|
1207
1228
|
const identity = this.getIdentityState(state);
|
|
1208
1229
|
const hasIdentity = Boolean(identity.connect_device_id && identity.connect_public_key && this.hasStoredPrivateKey());
|
|
@@ -1227,6 +1248,22 @@ class ConnectV1Service {
|
|
|
1227
1248
|
this.stateStore.updateConnectIdentity(nextIdentity);
|
|
1228
1249
|
return nextIdentity;
|
|
1229
1250
|
}
|
|
1251
|
+
syncRuntimeIdentityMetadata() {
|
|
1252
|
+
const state = this.stateStore.readState();
|
|
1253
|
+
const nextHostname = node_os_1.default.hostname();
|
|
1254
|
+
const nextPlatform = process.platform;
|
|
1255
|
+
const nextArch = process.arch;
|
|
1256
|
+
if (state.runtime_identity.hostname === nextHostname
|
|
1257
|
+
&& state.runtime_identity.platform === nextPlatform
|
|
1258
|
+
&& state.runtime_identity.arch === nextArch) {
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
this.stateStore.updateRuntimeIdentity({
|
|
1262
|
+
hostname: nextHostname,
|
|
1263
|
+
platform: nextPlatform,
|
|
1264
|
+
arch: nextArch,
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1230
1267
|
createConnectIdentity() {
|
|
1231
1268
|
const { privateKey, publicKey } = (0, node_crypto_1.generateKeyPairSync)('ed25519');
|
|
1232
1269
|
const publicKeyValue = publicKey.export({ type: 'spki', format: 'der' }).toString('base64url');
|
|
@@ -1633,6 +1670,12 @@ class ConnectV1Service {
|
|
|
1633
1670
|
sessionRef: this.readSessionRef(),
|
|
1634
1671
|
});
|
|
1635
1672
|
}
|
|
1673
|
+
getApiClientWithSessionToken(sessionRef) {
|
|
1674
|
+
return new api_1.ConnectApiClient({
|
|
1675
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
1676
|
+
sessionRef,
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1636
1679
|
ensureRuntimePassportIdentity() {
|
|
1637
1680
|
const state = this.stateStore.readState();
|
|
1638
1681
|
if (state.connect_identity.connect_device_id) {
|
|
@@ -2757,18 +2800,20 @@ class ConnectV1Service {
|
|
|
2757
2800
|
}
|
|
2758
2801
|
setRuntimeSignalApiKeyForGaid(gaid, apiKey) {
|
|
2759
2802
|
if (!gaid || !apiKey)
|
|
2760
|
-
return;
|
|
2803
|
+
return null;
|
|
2804
|
+
const metadata = this.credentialStore.setRuntimeSignalApiKey(gaid, apiKey);
|
|
2761
2805
|
const state = this.stateStore.readState();
|
|
2762
2806
|
const binding = this.findBindingByGaid(state, gaid);
|
|
2763
|
-
if (!binding)
|
|
2764
|
-
return;
|
|
2765
|
-
|
|
2807
|
+
if (!binding) {
|
|
2808
|
+
return metadata;
|
|
2809
|
+
}
|
|
2766
2810
|
this.stateStore.upsertModelBinding({
|
|
2767
2811
|
...binding,
|
|
2768
2812
|
runtimeSignalKeyPresent: true,
|
|
2769
2813
|
runtimeSignalKeyRef: metadata.credentialRef,
|
|
2770
2814
|
updatedAt: nowIso(),
|
|
2771
2815
|
});
|
|
2816
|
+
return metadata;
|
|
2772
2817
|
}
|
|
2773
2818
|
clearRuntimeSignalApiKeyForGaid(gaid, source = 'reset') {
|
|
2774
2819
|
if (!gaid)
|
|
@@ -2858,10 +2903,10 @@ class ConnectV1Service {
|
|
|
2858
2903
|
if (/^[_\-x0]+$/i.test(trimmedKey)) {
|
|
2859
2904
|
return { stored: false, backfilled: 0, gaid: trimmedGaid, keyRef: null };
|
|
2860
2905
|
}
|
|
2861
|
-
this.setRuntimeSignalApiKeyForGaid(trimmedGaid, trimmedKey);
|
|
2906
|
+
const credentialMetadata = this.setRuntimeSignalApiKeyForGaid(trimmedGaid, trimmedKey);
|
|
2862
2907
|
const afterState = this.stateStore.readState();
|
|
2863
2908
|
const binding = this.findBindingByGaid(afterState, trimmedGaid);
|
|
2864
|
-
const keyRef = binding?.runtimeSignalKeyRef ?? null;
|
|
2909
|
+
const keyRef = binding?.runtimeSignalKeyRef ?? credentialMetadata?.credentialRef ?? null;
|
|
2865
2910
|
const backfilled = this.backfillLocalOnlyC2Events(trimmedGaid);
|
|
2866
2911
|
this.stateStore.addEvidenceEvent({
|
|
2867
2912
|
type: 'runtimeSignal_key_configured',
|
|
@@ -2874,6 +2919,72 @@ class ConnectV1Service {
|
|
|
2874
2919
|
});
|
|
2875
2920
|
return { stored: true, backfilled, gaid: trimmedGaid, keyRef };
|
|
2876
2921
|
}
|
|
2922
|
+
registerRuntimeObserverTarget(input) {
|
|
2923
|
+
const now = nowIso();
|
|
2924
|
+
const runtimeGaid = String(input.gaid || '').trim();
|
|
2925
|
+
const rawRepoRoot = String(input.repoRoot || '').trim();
|
|
2926
|
+
if (!runtimeGaid || !rawRepoRoot) {
|
|
2927
|
+
throw new Error('RUNTIME_OBSERVER_TARGET_INVALID');
|
|
2928
|
+
}
|
|
2929
|
+
const repoRoot = node_path_1.default.resolve(rawRepoRoot);
|
|
2930
|
+
const state = this.stateStore.readState();
|
|
2931
|
+
const existing = state.runtime_observer_targets.find((item) => item.runtime_gaid === runtimeGaid);
|
|
2932
|
+
const nextTarget = {
|
|
2933
|
+
runtime_gaid: runtimeGaid,
|
|
2934
|
+
repo_root: repoRoot,
|
|
2935
|
+
client_name: normalizeDisplayText(input.clientName) ?? existing?.client_name ?? null,
|
|
2936
|
+
subject_id: normalizeDisplayText(input.subjectId) ?? existing?.subject_id ?? null,
|
|
2937
|
+
worktree_id: normalizeDisplayText(input.worktreeId) ?? existing?.worktree_id ?? null,
|
|
2938
|
+
last_observed_at: existing?.last_observed_at ?? null,
|
|
2939
|
+
last_emitted_at: existing?.last_emitted_at ?? null,
|
|
2940
|
+
last_fingerprint: existing?.last_fingerprint ?? null,
|
|
2941
|
+
last_summary: existing?.last_summary ?? null,
|
|
2942
|
+
last_error: existing?.last_error ?? null,
|
|
2943
|
+
updated_at: now,
|
|
2944
|
+
};
|
|
2945
|
+
this.stateStore.upsertRuntimeObserverTarget(nextTarget);
|
|
2946
|
+
return nextTarget;
|
|
2947
|
+
}
|
|
2948
|
+
listRuntimeObserverTargets() {
|
|
2949
|
+
return [...this.stateStore.readState().runtime_observer_targets];
|
|
2950
|
+
}
|
|
2951
|
+
hasRuntimeSignalKey(gaid) {
|
|
2952
|
+
return Boolean(this.credentialStore.getRuntimeSignalApiKey(String(gaid || '').trim()));
|
|
2953
|
+
}
|
|
2954
|
+
hasStoredRuntimeSignalKey(gaid) {
|
|
2955
|
+
const trimmedGaid = String(gaid || '').trim();
|
|
2956
|
+
if (!trimmedGaid)
|
|
2957
|
+
return false;
|
|
2958
|
+
return this.hasRuntimeSignalKey(trimmedGaid);
|
|
2959
|
+
}
|
|
2960
|
+
removeRuntimeObserverTarget(gaid) {
|
|
2961
|
+
const runtimeGaid = String(gaid || '').trim();
|
|
2962
|
+
if (!runtimeGaid)
|
|
2963
|
+
return false;
|
|
2964
|
+
const state = this.stateStore.readState();
|
|
2965
|
+
const existing = state.runtime_observer_targets.find((item) => item.runtime_gaid === runtimeGaid);
|
|
2966
|
+
if (!existing)
|
|
2967
|
+
return false;
|
|
2968
|
+
this.stateStore.removeRuntimeObserverTarget(runtimeGaid);
|
|
2969
|
+
return true;
|
|
2970
|
+
}
|
|
2971
|
+
updateRuntimeObserverTargetResult(input) {
|
|
2972
|
+
const state = this.stateStore.readState();
|
|
2973
|
+
const existing = state.runtime_observer_targets.find((item) => item.runtime_gaid === String(input.gaid || '').trim());
|
|
2974
|
+
if (!existing)
|
|
2975
|
+
return null;
|
|
2976
|
+
const nextTarget = {
|
|
2977
|
+
...existing,
|
|
2978
|
+
last_observed_at: typeof input.observedAt === 'string' ? input.observedAt : existing.last_observed_at,
|
|
2979
|
+
last_emitted_at: typeof input.emittedAt === 'string' ? input.emittedAt : existing.last_emitted_at,
|
|
2980
|
+
last_fingerprint: input.fingerprint !== undefined ? (normalizeDisplayText(input.fingerprint) ?? null) : existing.last_fingerprint,
|
|
2981
|
+
last_summary: input.summary !== undefined ? (normalizeDisplayText(input.summary) ?? null) : existing.last_summary,
|
|
2982
|
+
last_error: input.error !== undefined ? (normalizeDisplayText(input.error) ?? null) : existing.last_error,
|
|
2983
|
+
updated_at: nowIso(),
|
|
2984
|
+
};
|
|
2985
|
+
this.stateStore.upsertRuntimeObserverTarget(nextTarget);
|
|
2986
|
+
return nextTarget;
|
|
2987
|
+
}
|
|
2877
2988
|
// ─── Auto-provisioning ────────────────────────────────────────────────────
|
|
2878
2989
|
/**
|
|
2879
2990
|
* After login, automatically create a runtime-signal API key for every bound
|
|
@@ -2887,7 +2998,12 @@ class ConnectV1Service {
|
|
|
2887
2998
|
if (!this.hasSessionRef()) {
|
|
2888
2999
|
return { provisioned: [], skipped: [], failed: [] };
|
|
2889
3000
|
}
|
|
2890
|
-
const gaidsNeedingKeys =
|
|
3001
|
+
const gaidsNeedingKeys = [...new Set([
|
|
3002
|
+
...(0, lifecycle_monitor_1.findPassportsNeedingApiKeyProvisioning)(state),
|
|
3003
|
+
...state.runtime_observer_targets
|
|
3004
|
+
.map((target) => normalizeDisplayText(target.runtime_gaid))
|
|
3005
|
+
.filter((gaid) => Boolean(gaid)),
|
|
3006
|
+
])].filter((gaid) => !this.hasRuntimeSignalKey(gaid));
|
|
2891
3007
|
if (gaidsNeedingKeys.length === 0) {
|
|
2892
3008
|
return { provisioned: [], skipped: [], failed: [] };
|
|
2893
3009
|
}
|
|
@@ -3086,6 +3202,8 @@ class ConnectV1Service {
|
|
|
3086
3202
|
const completionTokens = Math.max(0, Math.trunc(input.completionTokens ?? 0));
|
|
3087
3203
|
const totalTokens = promptTokens + completionTokens;
|
|
3088
3204
|
const { workspaceId, projectId } = this.resolveRuntimeRunScope(state, gaid);
|
|
3205
|
+
const runtimeMetadata = isRecord(input.metadata) ? input.metadata : {};
|
|
3206
|
+
const steps = Array.isArray(input.steps) ? input.steps.filter((step) => isRecord(step)) : [];
|
|
3089
3207
|
return this.getApiClient(state).pushRuntimeRunLog({
|
|
3090
3208
|
gaid,
|
|
3091
3209
|
apiKey,
|
|
@@ -3116,13 +3234,50 @@ class ConnectV1Service {
|
|
|
3116
3234
|
...(input.summary ? { summary: String(input.summary).trim().slice(0, 4000) } : {}),
|
|
3117
3235
|
metadata: {
|
|
3118
3236
|
source: 'forkit-connect-cli',
|
|
3237
|
+
sourceSurface: 'connect_assisted',
|
|
3119
3238
|
safe_metadata_only: true,
|
|
3120
3239
|
connect_device_id: state.connect_identity.connect_device_id,
|
|
3240
|
+
...runtimeMetadata,
|
|
3121
3241
|
},
|
|
3122
3242
|
},
|
|
3123
|
-
steps
|
|
3243
|
+
steps,
|
|
3124
3244
|
});
|
|
3125
3245
|
}
|
|
3246
|
+
async emitRuntimeObserverCheckin(input) {
|
|
3247
|
+
const state = this.stateStore.readState();
|
|
3248
|
+
const gaid = String(input.gaid || '').trim();
|
|
3249
|
+
const apiKey = String(input.apiKey || this.resolveRuntimeSignalApiKeyForEvent(state, gaid) || '').trim();
|
|
3250
|
+
if (!gaid || !apiKey) {
|
|
3251
|
+
return {
|
|
3252
|
+
ok: false,
|
|
3253
|
+
status: 0,
|
|
3254
|
+
body: {
|
|
3255
|
+
error: 'Runtime signal API key required for runtime observer check-ins.',
|
|
3256
|
+
code: 'MISSING_RUNTIME_SIGNAL_API_KEY',
|
|
3257
|
+
},
|
|
3258
|
+
contract: null,
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
const metadata = isRecord(input.metadata) ? input.metadata : {};
|
|
3262
|
+
const client = this.getApiClientWithSessionToken(apiKey);
|
|
3263
|
+
return client.sendRuntimeCheckin(gaid, {
|
|
3264
|
+
...(input.sessionLabel ? { sessionLabel: String(input.sessionLabel).trim() } : {}),
|
|
3265
|
+
...(input.environment ? { environment: String(input.environment).trim() } : {}),
|
|
3266
|
+
...(input.region ? { region: String(input.region).trim() } : {}),
|
|
3267
|
+
...(input.hostLabel ? { hostLabel: String(input.hostLabel).trim() } : {}),
|
|
3268
|
+
...(input.runtimeLabel ? { runtimeLabel: String(input.runtimeLabel).trim() } : {}),
|
|
3269
|
+
...(input.runtimeMode ? { runtimeMode: String(input.runtimeMode).trim() } : {}),
|
|
3270
|
+
...(input.resourceAccuracy ? { resourceAccuracy: String(input.resourceAccuracy).trim() } : {}),
|
|
3271
|
+
...(input.resourceNote ? { resourceNote: String(input.resourceNote).trim() } : {}),
|
|
3272
|
+
...(input.cpuPercent !== undefined ? { cpuPercent: input.cpuPercent } : {}),
|
|
3273
|
+
...(input.memoryMb !== undefined ? { memoryMb: input.memoryMb } : {}),
|
|
3274
|
+
...(input.vramMb !== undefined ? { vramMb: input.vramMb } : {}),
|
|
3275
|
+
...(input.promptTokens !== undefined ? { promptTokens: Math.max(0, Math.trunc(input.promptTokens)) } : {}),
|
|
3276
|
+
...(input.completionTokens !== undefined ? { completionTokens: Math.max(0, Math.trunc(input.completionTokens)) } : {}),
|
|
3277
|
+
...(input.executionMs !== undefined ? { executionMs: Math.max(0, Math.trunc(input.executionMs)) } : {}),
|
|
3278
|
+
metadata,
|
|
3279
|
+
}, input.sessionId || null);
|
|
3280
|
+
}
|
|
3126
3281
|
findAgentByIdOrName(state, selector) {
|
|
3127
3282
|
const normalized = selector.trim().toLowerCase();
|
|
3128
3283
|
const exactId = state.detected_agents.find((agent) => agent.agent_id === selector || agent.agent_id.startsWith(selector));
|
|
@@ -6423,7 +6578,7 @@ class ConnectV1Service {
|
|
|
6423
6578
|
source: 'draft_sync',
|
|
6424
6579
|
});
|
|
6425
6580
|
if (!this.shouldFallbackToQueuedTrainingDraft(result.status)) {
|
|
6426
|
-
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' : `DRAFT_CREATE_FAILED:${result.status}`);
|
|
6581
|
+
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' : (extractApiErrorCode(result.body) || `DRAFT_CREATE_FAILED:${result.status}`));
|
|
6427
6582
|
}
|
|
6428
6583
|
}
|
|
6429
6584
|
else {
|
|
@@ -7789,7 +7944,7 @@ class ConnectV1Service {
|
|
|
7789
7944
|
body: result.body,
|
|
7790
7945
|
source: 'draft_sync',
|
|
7791
7946
|
});
|
|
7792
|
-
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' : `DRAFT_CREATE_FAILED:${result.status}`);
|
|
7947
|
+
throw new Error(result.status === 409 ? 'DRAFT_ALREADY_EXISTS' : (extractApiErrorCode(result.body) || `DRAFT_CREATE_FAILED:${result.status}`));
|
|
7793
7948
|
}
|
|
7794
7949
|
const parsed = this.parseDraftResponse(result);
|
|
7795
7950
|
let finalGaid = parsed.gaid;
|
package/dist/v1/state.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentModelUsageRecord, BuildSession, C2SessionState, C2LifecycleEvent, ConnectIdentityState, ConnectConfig, ConnectEffectiveBindingState, ConnectState, DaemonStatus, DetectedAgent, DetectedModel, DetectedRuntime, DeliveredNotification, EvidenceEvent, LifecycleMonitorRecord, ModelEvolutionCandidate, ModelBinding, PendingReview, RuntimePassport, ServiceEntitlements, SyncQueueItem, VitalityPulseEvent, VitalityPulseSummary } from './types';
|
|
1
|
+
import type { AgentModelUsageRecord, BuildSession, C2SessionState, C2LifecycleEvent, ConnectIdentityState, ConnectConfig, ConnectEffectiveBindingState, ConnectState, DaemonStatus, DetectedAgent, DetectedModel, DetectedRuntime, DeliveredNotification, EvidenceEvent, LifecycleMonitorRecord, ModelEvolutionCandidate, ModelBinding, PendingReview, RuntimePassport, RuntimeIdentity, RuntimeObserverTarget, ServiceEntitlements, SyncQueueItem, VitalityPulseEvent, VitalityPulseSummary } from './types';
|
|
2
2
|
import type { AgentLink } from './types';
|
|
3
3
|
export interface StatePaths {
|
|
4
4
|
stateDir: string;
|
|
@@ -26,6 +26,7 @@ export declare class LocalStateStore {
|
|
|
26
26
|
updateEffectiveBinding(effectiveBinding: ConnectEffectiveBindingState | null): ConnectState;
|
|
27
27
|
updateConnectConfig(configPatch: Partial<Pick<ConnectConfig, 'discovery_mode' | 'daemon_interval_seconds' | 'notifications_enabled' | 'notification_min_interval_seconds' | 'evolution_bridge_enabled'>>): ConnectState;
|
|
28
28
|
updateConnectIdentity(identityPatch: Partial<ConnectIdentityState>): ConnectState;
|
|
29
|
+
updateRuntimeIdentity(identityPatch: Partial<RuntimeIdentity>): ConnectState;
|
|
29
30
|
updateServiceEntitlements(entitlements: ServiceEntitlements): ConnectState;
|
|
30
31
|
updateDaemonStatus(statusPatch: Partial<DaemonStatus>): ConnectState;
|
|
31
32
|
appendC2Events(events: C2LifecycleEvent[]): ConnectState;
|
|
@@ -46,6 +47,8 @@ export declare class LocalStateStore {
|
|
|
46
47
|
upsertDetectedRuntime(runtime: DetectedRuntime): ConnectState;
|
|
47
48
|
upsertRuntimePassport(runtimePassport: RuntimePassport): ConnectState;
|
|
48
49
|
replaceRuntimePassports(runtimePassports: RuntimePassport[]): ConnectState;
|
|
50
|
+
upsertRuntimeObserverTarget(target: RuntimeObserverTarget): ConnectState;
|
|
51
|
+
removeRuntimeObserverTarget(runtimeGaid: string): ConnectState;
|
|
49
52
|
upsertC2Session(session: C2SessionState): ConnectState;
|
|
50
53
|
replaceC2Sessions(sessions: C2SessionState[]): ConnectState;
|
|
51
54
|
upsertBuildSession(buildSession: BuildSession): ConnectState;
|
package/dist/v1/state.js
CHANGED
|
@@ -65,6 +65,7 @@ const STATE_SECTION_NAMES = [
|
|
|
65
65
|
'agent_model_usage',
|
|
66
66
|
'detected_runtimes',
|
|
67
67
|
'runtime_passports',
|
|
68
|
+
'runtime_observer_targets',
|
|
68
69
|
'c2_sessions',
|
|
69
70
|
'evolution_candidates',
|
|
70
71
|
'detected_models',
|
|
@@ -413,6 +414,7 @@ function normalizeState(parsed) {
|
|
|
413
414
|
agent_model_usage: Array.isArray(value.agent_model_usage) ? value.agent_model_usage : [],
|
|
414
415
|
detected_runtimes: Array.isArray(value.detected_runtimes) ? value.detected_runtimes : [],
|
|
415
416
|
runtime_passports: Array.isArray(value.runtime_passports) ? value.runtime_passports : [],
|
|
417
|
+
runtime_observer_targets: Array.isArray(value.runtime_observer_targets) ? value.runtime_observer_targets : [],
|
|
416
418
|
c2_sessions: Array.isArray(value.c2_sessions) ? value.c2_sessions : [],
|
|
417
419
|
evolution_candidates: Array.isArray(value.evolution_candidates) ? value.evolution_candidates : [],
|
|
418
420
|
detected_models: Array.isArray(value.detected_models) ? value.detected_models : [],
|
|
@@ -477,6 +479,7 @@ function buildInitialState() {
|
|
|
477
479
|
agent_model_usage: [],
|
|
478
480
|
detected_runtimes: [],
|
|
479
481
|
runtime_passports: [],
|
|
482
|
+
runtime_observer_targets: [],
|
|
480
483
|
c2_sessions: [],
|
|
481
484
|
evolution_candidates: [],
|
|
482
485
|
detected_models: [],
|
|
@@ -593,6 +596,14 @@ class LocalStateStore {
|
|
|
593
596
|
};
|
|
594
597
|
});
|
|
595
598
|
}
|
|
599
|
+
updateRuntimeIdentity(identityPatch) {
|
|
600
|
+
return this.mutateState((state) => {
|
|
601
|
+
state.runtime_identity = {
|
|
602
|
+
...state.runtime_identity,
|
|
603
|
+
...identityPatch,
|
|
604
|
+
};
|
|
605
|
+
});
|
|
606
|
+
}
|
|
596
607
|
updateServiceEntitlements(entitlements) {
|
|
597
608
|
return this.mutateState((state) => {
|
|
598
609
|
state.service_entitlements = entitlements;
|
|
@@ -813,6 +824,23 @@ class LocalStateStore {
|
|
|
813
824
|
state.runtime_passports = [...seen.values()].sort((left, right) => right.last_seen_at.localeCompare(left.last_seen_at));
|
|
814
825
|
});
|
|
815
826
|
}
|
|
827
|
+
upsertRuntimeObserverTarget(target) {
|
|
828
|
+
return this.mutateState((state) => {
|
|
829
|
+
const index = state.runtime_observer_targets.findIndex((item) => item.runtime_gaid === target.runtime_gaid);
|
|
830
|
+
if (index >= 0) {
|
|
831
|
+
state.runtime_observer_targets[index] = target;
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
state.runtime_observer_targets.push(target);
|
|
835
|
+
}
|
|
836
|
+
state.runtime_observer_targets.sort((left, right) => right.updated_at.localeCompare(left.updated_at));
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
removeRuntimeObserverTarget(runtimeGaid) {
|
|
840
|
+
return this.mutateState((state) => {
|
|
841
|
+
state.runtime_observer_targets = state.runtime_observer_targets.filter((item) => item.runtime_gaid !== runtimeGaid);
|
|
842
|
+
});
|
|
843
|
+
}
|
|
816
844
|
upsertC2Session(session) {
|
|
817
845
|
return this.mutateState((state) => {
|
|
818
846
|
const index = state.c2_sessions.findIndex((item) => item.session_id === session.session_id && item.passport_gaid === session.passport_gaid);
|
package/dist/v1/types.d.ts
CHANGED
|
@@ -268,6 +268,19 @@ export interface RuntimeHandoffSummary {
|
|
|
268
268
|
unlinked_runtimes: string[];
|
|
269
269
|
unhealthy_runtimes: string[];
|
|
270
270
|
}
|
|
271
|
+
export interface RuntimeObserverTarget {
|
|
272
|
+
runtime_gaid: string;
|
|
273
|
+
repo_root: string;
|
|
274
|
+
client_name: string | null;
|
|
275
|
+
subject_id: string | null;
|
|
276
|
+
worktree_id: string | null;
|
|
277
|
+
last_observed_at: string | null;
|
|
278
|
+
last_emitted_at: string | null;
|
|
279
|
+
last_fingerprint: string | null;
|
|
280
|
+
last_summary: string | null;
|
|
281
|
+
last_error: string | null;
|
|
282
|
+
updated_at: string;
|
|
283
|
+
}
|
|
271
284
|
export interface C2SessionState {
|
|
272
285
|
session_id: string;
|
|
273
286
|
passport_gaid: string;
|
|
@@ -895,6 +908,7 @@ export interface ConnectState {
|
|
|
895
908
|
agent_model_usage: AgentModelUsageRecord[];
|
|
896
909
|
detected_runtimes: DetectedRuntime[];
|
|
897
910
|
runtime_passports: RuntimePassport[];
|
|
911
|
+
runtime_observer_targets: RuntimeObserverTarget[];
|
|
898
912
|
c2_sessions: C2SessionState[];
|
|
899
913
|
evolution_candidates: ModelEvolutionCandidate[];
|
|
900
914
|
detected_models: DetectedModel[];
|