freecodego 0.1.7-rc.2.2 → 0.1.7-rc.2.3
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.i18n.yaml +4 -4
- package/README.md +9 -9
- package/README.zh.md +9 -9
- package/dist/bootstrap.js +358 -71
- package/dist/client.cjs +828 -133
- package/package.json +3 -3
package/dist/bootstrap.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { createRequire as createRequire2 } from "node:module";
|
|
3
3
|
import path, { basename as basename2, delimiter, dirname as dirname2, extname, isAbsolute as isAbsolute2, join as join4, matchesGlob, normalize as normalize2, relative as relative2, resolve as resolve2, sep } from "node:path";
|
|
4
4
|
import { credentialRef as credentialRef2 } from "@deepseek-ai/dsh-credentials";
|
|
5
|
-
import { constants, createCipheriv, createHash as createHash3, createHmac, createPublicKey, publicEncrypt, randomBytes, randomUUID as
|
|
5
|
+
import { constants, createCipheriv, createHash as createHash3, createHmac, createPublicKey, publicEncrypt, randomBytes, randomUUID as randomUUID4, timingSafeEqual } from "node:crypto";
|
|
6
6
|
import fs, { appendFile, copyFile as copyFile2, mkdir as mkdir4, mkdtemp, open as open2, readFile as readFile3, readdir as readdir2, readlink, realpath, rename as rename3, rm as rm2, stat as stat2, symlink, unlink, writeFile as writeFile3 } from "node:fs/promises";
|
|
7
|
-
import { availableParallelism, homedir, platform as platform2, release, tmpdir } from "node:os";
|
|
7
|
+
import { availableParallelism, homedir, hostname, platform as platform2, release, tmpdir } from "node:os";
|
|
8
8
|
import { deflateRawSync, gunzipSync, inflateRawSync, inflateSync } from "node:zlib";
|
|
9
9
|
import { appendFileSync, chmodSync, constants as constants$1, createWriteStream, existsSync as existsSync2, lstatSync, mkdirSync, mkdtempSync, readFileSync as readFileSync2, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { writeFileAtomic } from "@deepseek-ai/dsh-atomic-write";
|
|
@@ -16,7 +16,7 @@ import { AttachmentId, requestImageDimensions } from "@deepseek-ai/dsh-attachmen
|
|
|
16
16
|
import { EventSourceParserStream } from "eventsource-parser/stream";
|
|
17
17
|
|
|
18
18
|
// packages/freecodego/freecodego-api/lib/index.js
|
|
19
|
-
import { createHash } from "node:crypto";
|
|
19
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
20
20
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
21
21
|
var FreeCodeGoMobileAuthClient = class {
|
|
22
22
|
/**
|
|
@@ -383,11 +383,21 @@ var HarnessFreeCodeGoCredentialVault = class {
|
|
|
383
383
|
* it — and erasing the session must not erase what the sign-in form prefills.
|
|
384
384
|
*/
|
|
385
385
|
passwordRef;
|
|
386
|
+
/**
|
|
387
|
+
* The installation's device identity, kept beside the session pair.
|
|
388
|
+
*
|
|
389
|
+
* It is a separate value rather than a field of the pair because it outlives
|
|
390
|
+
* every rotation: the pair is replaced on each refresh and erased on sign-out,
|
|
391
|
+
* while this is what makes the next sign-out-and-in land on the same device
|
|
392
|
+
* row instead of adding one.
|
|
393
|
+
*/
|
|
394
|
+
deviceRef;
|
|
386
395
|
constructor(credentials, origin) {
|
|
387
396
|
this.credentials = credentials;
|
|
388
397
|
const digest2 = createHash("sha256").update(origin).digest("hex").slice(0, 24).toUpperCase();
|
|
389
398
|
this.ref = credentialRef(`FREECODEGO_SESSION_${digest2}`);
|
|
390
399
|
this.passwordRef = credentialRef(`FREECODEGO_PASSWORD_${digest2}`);
|
|
400
|
+
this.deviceRef = credentialRef(`FREECODEGO_DEVICE_${digest2}`);
|
|
391
401
|
}
|
|
392
402
|
async load(_origin) {
|
|
393
403
|
const resolved = await this.credentials.resolve(this.ref);
|
|
@@ -414,6 +424,22 @@ var HarnessFreeCodeGoCredentialVault = class {
|
|
|
414
424
|
async deletePassword(_origin) {
|
|
415
425
|
await this.credentials.unset(this.passwordRef);
|
|
416
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Read this installation's device identity.
|
|
429
|
+
* @returns the stored identity, or undefined when this machine never named one.
|
|
430
|
+
*/
|
|
431
|
+
async loadDeviceId(_origin) {
|
|
432
|
+
const resolved = await this.credentials.resolve(this.deviceRef);
|
|
433
|
+
const value = resolved === void 0 ? "" : resolved.value.trim();
|
|
434
|
+
return value === "" ? void 0 : value;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Persist this installation's device identity.
|
|
438
|
+
* @param deviceId - the identity every later sign-in and rotation presents.
|
|
439
|
+
*/
|
|
440
|
+
async saveDeviceId(_origin, deviceId) {
|
|
441
|
+
await this.credentials.set(this.deviceRef, deviceId);
|
|
442
|
+
}
|
|
417
443
|
};
|
|
418
444
|
var FreeCodeGoAccountCoordinator = class {
|
|
419
445
|
auth;
|
|
@@ -421,6 +447,21 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
421
447
|
state = { status: "signed-out" };
|
|
422
448
|
pendingMfaToken;
|
|
423
449
|
refreshInFlight;
|
|
450
|
+
/**
|
|
451
|
+
* The settled resolution of this installation's device identity.
|
|
452
|
+
*
|
|
453
|
+
* Cached as the promise rather than the value so two concurrent sign-ins
|
|
454
|
+
* cannot each mint an identity and race the vault write; whichever asks first
|
|
455
|
+
* decides, and every later caller reads the same answer.
|
|
456
|
+
*/
|
|
457
|
+
deviceIdInFlight;
|
|
458
|
+
/**
|
|
459
|
+
* Whether a rotation has already been spent on a pair that states no device.
|
|
460
|
+
*
|
|
461
|
+
* Spent at most once per process: a gateway that keeps answering with an
|
|
462
|
+
* unbound pair must not make every authorized call rotate the session.
|
|
463
|
+
*/
|
|
464
|
+
unboundSessionRenewed = false;
|
|
424
465
|
/** Set by logout() so an in-flight refresh never writes after the erase. */
|
|
425
466
|
signingOut = false;
|
|
426
467
|
/**
|
|
@@ -592,13 +633,75 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
592
633
|
* @param signal - aborts the request when the caller cancels.
|
|
593
634
|
* @returns the account state after the issued tokens were stored.
|
|
594
635
|
*/
|
|
636
|
+
/**
|
|
637
|
+
* This installation's device identity, creating and persisting one on first use.
|
|
638
|
+
*
|
|
639
|
+
* The gateway binds a session to the device that opened it and will not serve a
|
|
640
|
+
* model to a token whose device has no live session, so a sign-in that states
|
|
641
|
+
* no device is a sign-in the gateway later refuses — every model, every turn.
|
|
642
|
+
* The identity is therefore resolved once and reused for the life of the
|
|
643
|
+
* installation, in the same vault as the session pair so a restart keeps it.
|
|
644
|
+
*
|
|
645
|
+
* `fcg-<uuid>` mirrors the identity the vendor's own desktop client presents,
|
|
646
|
+
* which keeps a mixed account's device list readable rather than one scheme per
|
|
647
|
+
* client.
|
|
648
|
+
* @returns the stable device id this installation signs in with.
|
|
649
|
+
*/
|
|
650
|
+
async deviceId() {
|
|
651
|
+
if (this.deviceIdInFlight === void 0) this.deviceIdInFlight = this.mintDeviceId();
|
|
652
|
+
return this.deviceIdInFlight;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* The identity to sign in with, honoring a device the caller stated.
|
|
656
|
+
*
|
|
657
|
+
* A stated device is an assertion about which device this session belongs to,
|
|
658
|
+
* so it is remembered rather than merely forwarded: the next rotation resolves
|
|
659
|
+
* the installation identity, and rotating a session onto a different device is
|
|
660
|
+
* how a working pair stops being accepted.
|
|
661
|
+
* @param statedDeviceId - the device the caller named, if any.
|
|
662
|
+
* @returns the identity to present to the gateway.
|
|
663
|
+
*/
|
|
664
|
+
async deviceIdFor(statedDeviceId) {
|
|
665
|
+
const stated = statedDeviceId?.trim() ?? "";
|
|
666
|
+
if (stated === "") return this.deviceId();
|
|
667
|
+
this.deviceIdInFlight = Promise.resolve(stated);
|
|
668
|
+
try {
|
|
669
|
+
await this.vault.saveDeviceId?.(this.auth.origin, stated);
|
|
670
|
+
} catch {
|
|
671
|
+
}
|
|
672
|
+
return stated;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Load the stored identity, or mint one and write it back.
|
|
676
|
+
*
|
|
677
|
+
* Both vault failures are recoverable rather than fatal: an unreadable entry is
|
|
678
|
+
* "no identity yet", and an unwritable one leaves the id live for this process
|
|
679
|
+
* — the session it binds is still usable, it just will not survive a restart.
|
|
680
|
+
* @returns the identity to present, stored when the vault accepts it.
|
|
681
|
+
*/
|
|
682
|
+
async mintDeviceId() {
|
|
683
|
+
try {
|
|
684
|
+
const stored = await this.vault.loadDeviceId?.(this.auth.origin);
|
|
685
|
+
if (stored !== void 0) return stored;
|
|
686
|
+
} catch {
|
|
687
|
+
}
|
|
688
|
+
const created = `fcg-${randomUUID()}`;
|
|
689
|
+
try {
|
|
690
|
+
await this.vault.saveDeviceId?.(this.auth.origin, created);
|
|
691
|
+
} catch {
|
|
692
|
+
}
|
|
693
|
+
return created;
|
|
694
|
+
}
|
|
595
695
|
async login(input, signal) {
|
|
596
696
|
this.pendingRemember = input.remember;
|
|
597
697
|
if (input.rememberPassword === void 0) this.pendingPassword = void 0;
|
|
598
698
|
else if (input.rememberPassword) this.pendingPassword = { keep: input.password };
|
|
599
699
|
else this.pendingPassword = { forget: true };
|
|
600
700
|
try {
|
|
601
|
-
return await this.consumeLoginResult(await this.auth.login(
|
|
701
|
+
return await this.consumeLoginResult(await this.auth.login({
|
|
702
|
+
...input,
|
|
703
|
+
deviceId: await this.deviceIdFor(input.deviceId)
|
|
704
|
+
}, signal));
|
|
602
705
|
} catch (error) {
|
|
603
706
|
this.pendingRemember = void 0;
|
|
604
707
|
this.pendingPassword = void 0;
|
|
@@ -613,7 +716,10 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
613
716
|
async register(input, signal) {
|
|
614
717
|
this.pendingRemember = input.remember;
|
|
615
718
|
try {
|
|
616
|
-
return await this.consumeLoginResult(await this.auth.register(
|
|
719
|
+
return await this.consumeLoginResult(await this.auth.register({
|
|
720
|
+
...input,
|
|
721
|
+
deviceId: await this.deviceIdFor(input.deviceId)
|
|
722
|
+
}, signal));
|
|
617
723
|
} catch (error) {
|
|
618
724
|
this.pendingRemember = void 0;
|
|
619
725
|
throw error;
|
|
@@ -622,12 +728,13 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
622
728
|
/** Complete MFA and store credentials only after the second factor succeeds.
|
|
623
729
|
* @param tempToken - the MFA challenge token the first factor issued.
|
|
624
730
|
* @param totpCode - the code the user's authenticator produced.
|
|
625
|
-
* @param deviceId - device identifier recorded with the session
|
|
731
|
+
* @param deviceId - device identifier recorded with the session; defaults to
|
|
732
|
+
* this installation's own, without which the session is not bound to a device.
|
|
626
733
|
* @param signal - aborts the request when the caller cancels.
|
|
627
734
|
* @returns the account state after the second factor succeeded.
|
|
628
735
|
*/
|
|
629
736
|
async login2FA(tempToken, totpCode, deviceId, signal) {
|
|
630
|
-
return this.consumeLoginResult(await this.auth.login2FA(tempToken, totpCode, deviceId, signal));
|
|
737
|
+
return this.consumeLoginResult(await this.auth.login2FA(tempToken, totpCode, await this.deviceIdFor(deviceId), signal));
|
|
631
738
|
}
|
|
632
739
|
/** Complete the pending Host-owned MFA challenge without exposing its temp token.
|
|
633
740
|
* @param totpCode - the code the user's authenticator produced.
|
|
@@ -704,7 +811,9 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
704
811
|
};
|
|
705
812
|
}
|
|
706
813
|
/** Rotate the stored session token; callers reauthenticate after any failure.
|
|
707
|
-
* @param deviceId - device identifier recorded with the rotated session
|
|
814
|
+
* @param deviceId - device identifier recorded with the rotated session;
|
|
815
|
+
* defaults to this installation's own, so a rotation never drops the binding
|
|
816
|
+
* the gateway checks.
|
|
708
817
|
* @param signal - bounds this caller's wait; the shared rotation keeps running.
|
|
709
818
|
*/
|
|
710
819
|
async refresh(deviceId, signal) {
|
|
@@ -723,7 +832,7 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
723
832
|
this.state = { status: "signed-out" };
|
|
724
833
|
return;
|
|
725
834
|
}
|
|
726
|
-
const exchange = await this.exchangeRefresh(tokens2.refreshToken, deviceId);
|
|
835
|
+
const exchange = await this.exchangeRefresh(tokens2.refreshToken, await this.deviceIdFor(deviceId));
|
|
727
836
|
if (!exchange.ok) {
|
|
728
837
|
if (this.signingOut) throw exchange.error;
|
|
729
838
|
if (erasableRefreshFailure(exchange.kinds)) {
|
|
@@ -786,6 +895,9 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
786
895
|
await this.refresh(void 0, signal);
|
|
787
896
|
tokens2 = await this.loadTokens();
|
|
788
897
|
if (tokens2 === void 0) throw new Error("FreeCodeGo authentication is required after token refresh");
|
|
898
|
+
} else if (this.shouldRenewUnboundSession(tokens2.accessToken)) {
|
|
899
|
+
await this.refresh(void 0, signal).catch(() => void 0);
|
|
900
|
+
tokens2 = await this.loadTokens() ?? tokens2;
|
|
789
901
|
}
|
|
790
902
|
try {
|
|
791
903
|
return await operation(tokens2.accessToken, signal);
|
|
@@ -801,6 +913,24 @@ var FreeCodeGoAccountCoordinator = class {
|
|
|
801
913
|
}
|
|
802
914
|
}
|
|
803
915
|
/**
|
|
916
|
+
* Whether to spend this process's one rotation on a pair that states no device.
|
|
917
|
+
*
|
|
918
|
+
* The gateway serves no model to a token whose device has no live session and
|
|
919
|
+
* answers a device-less token with `401`. That answer is not about the token's
|
|
920
|
+
* age, so the expiry check above never fires: every turn fails identically for
|
|
921
|
+
* the whole life of the pair. One rotation repairs it, because refresh() now
|
|
922
|
+
* states this installation's identity — and the replacement is bound, so this
|
|
923
|
+
* answers false from then on.
|
|
924
|
+
* @param accessToken - the stored access token about to be presented.
|
|
925
|
+
* @returns whether an unbound pair should be rotated before this call.
|
|
926
|
+
*/
|
|
927
|
+
shouldRenewUnboundSession(accessToken) {
|
|
928
|
+
if (this.unboundSessionRenewed) return false;
|
|
929
|
+
if (!tokenStatesNoDevice(accessToken)) return false;
|
|
930
|
+
this.unboundSessionRenewed = true;
|
|
931
|
+
return true;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
804
934
|
* Store a token pair issued by an out-of-band flow (browser OAuth) without
|
|
805
935
|
* returning it to the caller.
|
|
806
936
|
*
|
|
@@ -948,6 +1078,16 @@ function tokenNeedsRefresh(accessToken) {
|
|
|
948
1078
|
return false;
|
|
949
1079
|
}
|
|
950
1080
|
}
|
|
1081
|
+
function tokenStatesNoDevice(accessToken) {
|
|
1082
|
+
const parts = accessToken.split(".");
|
|
1083
|
+
if (parts.length !== 3) return false;
|
|
1084
|
+
try {
|
|
1085
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
|
|
1086
|
+
return typeof payload.device_id !== "string" || payload.device_id.trim() === "";
|
|
1087
|
+
} catch {
|
|
1088
|
+
return false;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
951
1091
|
function isUnauthorized(error) {
|
|
952
1092
|
const status = error !== null && typeof error === "object" && "status" in error && typeof error.status === "number" ? error.status : void 0;
|
|
953
1093
|
if (status !== void 0) return status === 401;
|
|
@@ -1280,6 +1420,47 @@ var FreeCodeGoApiClient = class {
|
|
|
1280
1420
|
}), "revoke device session");
|
|
1281
1421
|
return typeof payload.message === "string" ? payload.message.trim() : "";
|
|
1282
1422
|
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Read the announcements this account may see.
|
|
1425
|
+
*
|
|
1426
|
+
* The backend decides the audience: an announcement's targeting rules are
|
|
1427
|
+
* applied server-side against the account's balance and subscriptions, so a
|
|
1428
|
+
* row that comes back is one this account is meant to read. `read_at` is the
|
|
1429
|
+
* account's own record, not the client's, which is what lets a dismissal made
|
|
1430
|
+
* on one machine hold on the next.
|
|
1431
|
+
* @param request - the request this call projects from, and whether read rows may be left out.
|
|
1432
|
+
* @returns the visible announcements, newest first as the backend ordered them.
|
|
1433
|
+
*/
|
|
1434
|
+
async getAnnouncements(request) {
|
|
1435
|
+
const query2 = request.unreadOnly === true ? "?unread_only=1" : "";
|
|
1436
|
+
return array(await this.authorized(`/api/v1/announcements${query2}`, request), "announcements").map((value, index) => {
|
|
1437
|
+
const item = object(value, `announcements[${index}]`);
|
|
1438
|
+
return {
|
|
1439
|
+
id: finiteNumber(item.id, `announcements[${index}].id`),
|
|
1440
|
+
title: string(item.title, `announcements[${index}].title`),
|
|
1441
|
+
content: typeof item.content === "string" ? item.content : "",
|
|
1442
|
+
notifyMode: announcementNotifyMode(item.notify_mode),
|
|
1443
|
+
...typeof item.read_at === "string" && item.read_at.trim() !== "" ? { readAt: item.read_at.trim() } : {},
|
|
1444
|
+
...typeof item.starts_at === "string" && item.starts_at.trim() !== "" ? { startsAt: item.starts_at.trim() } : {},
|
|
1445
|
+
...typeof item.ends_at === "string" && item.ends_at.trim() !== "" ? { endsAt: item.ends_at.trim() } : {},
|
|
1446
|
+
createdAt: typeof item.created_at === "string" ? item.created_at : ""
|
|
1447
|
+
};
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Record that this account read one announcement.
|
|
1452
|
+
*
|
|
1453
|
+
* The backend owns the record, so closing a notice is an acknowledged fact
|
|
1454
|
+
* rather than a client-side memory: the same announcement stays closed on the
|
|
1455
|
+
* account's other machines, and the administrator's read report counts it.
|
|
1456
|
+
* @param request - the request this call projects from, and the announcement to mark.
|
|
1457
|
+
* @returns nothing; the backend's acknowledgement is not rendered.
|
|
1458
|
+
*/
|
|
1459
|
+
async markAnnouncementRead(request) {
|
|
1460
|
+
const id = request.announcementId;
|
|
1461
|
+
if (!Number.isFinite(id) || id <= 0) throw new Error("FreeCodeGo announcement id is required");
|
|
1462
|
+
await this.authorized(`/api/v1/announcements/${encodeURIComponent(String(id))}/read`, request, { method: "POST" });
|
|
1463
|
+
}
|
|
1283
1464
|
/** Revoke every session of the account and return how many the backend revoked.
|
|
1284
1465
|
* @param request - the request this call projects from.
|
|
1285
1466
|
* @returns how many sessions the backend revoked.
|
|
@@ -1978,6 +2159,9 @@ function freeAccessFlags(...sources) {
|
|
|
1978
2159
|
function channelMonitorStatus(value) {
|
|
1979
2160
|
return value === "operational" || value === "degraded" || value === "failed" || value === "error" ? value : "unknown";
|
|
1980
2161
|
}
|
|
2162
|
+
function announcementNotifyMode(value) {
|
|
2163
|
+
return value === "popup" ? "popup" : "silent";
|
|
2164
|
+
}
|
|
1981
2165
|
function normalizeBaseUrl(value, allowInsecureLocalhost) {
|
|
1982
2166
|
let url;
|
|
1983
2167
|
try {
|
|
@@ -2030,7 +2214,7 @@ import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
|
2030
2214
|
// packages/freecodego/native-runtime-host/lib/index.js
|
|
2031
2215
|
import { createRequire } from "node:module";
|
|
2032
2216
|
import { spawn } from "node:child_process";
|
|
2033
|
-
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
2217
|
+
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
2034
2218
|
|
|
2035
2219
|
// packages/freecodego/native-runtime-protocol/lib/index.js
|
|
2036
2220
|
var REDACTED = "<redacted>";
|
|
@@ -3096,7 +3280,7 @@ var NativeRuntimeHost = class {
|
|
|
3096
3280
|
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
|
3097
3281
|
}
|
|
3098
3282
|
this.start();
|
|
3099
|
-
const id =
|
|
3283
|
+
const id = randomUUID2();
|
|
3100
3284
|
const request = {
|
|
3101
3285
|
id,
|
|
3102
3286
|
method,
|
|
@@ -4752,7 +4936,7 @@ async function openCodexRootRuntime(runtime, options) {
|
|
|
4752
4936
|
}
|
|
4753
4937
|
|
|
4754
4938
|
// packages/freecodego/runtime-claude/lib/index.mjs
|
|
4755
|
-
import { randomUUID as
|
|
4939
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
4756
4940
|
import { mkdir as mkdir3, readFile as readFile2, rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
|
|
4757
4941
|
import { join as join3 } from "node:path";
|
|
4758
4942
|
import { createSdkMcpServer, query, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
@@ -5124,7 +5308,7 @@ var DirectClaudeSdkSession = class DirectClaudeSdkSession2 {
|
|
|
5124
5308
|
}
|
|
5125
5309
|
static async open(runtime, options) {
|
|
5126
5310
|
await mkdir3(runtime.stateDirectory, { recursive: true });
|
|
5127
|
-
const session = new DirectClaudeSdkSession2(runtime, options, options.nativeSessionId ??
|
|
5311
|
+
const session = new DirectClaudeSdkSession2(runtime, options, options.nativeSessionId ?? randomUUID3());
|
|
5128
5312
|
await options.prepare?.(async () => void 0);
|
|
5129
5313
|
return session;
|
|
5130
5314
|
}
|
|
@@ -5196,7 +5380,7 @@ var DirectClaudeSdkSession = class DirectClaudeSdkSession2 {
|
|
|
5196
5380
|
behavior: "deny",
|
|
5197
5381
|
message: sandboxDenial
|
|
5198
5382
|
};
|
|
5199
|
-
const requestId =
|
|
5383
|
+
const requestId = randomUUID3();
|
|
5200
5384
|
const pending = this.pending(this.pendingPermissions, requestId);
|
|
5201
5385
|
this.event("permission/requested", {
|
|
5202
5386
|
requestId,
|
|
@@ -5315,7 +5499,7 @@ var DirectClaudeSdkSession = class DirectClaudeSdkSession2 {
|
|
|
5315
5499
|
return promise.promise;
|
|
5316
5500
|
}
|
|
5317
5501
|
async askUser(questions) {
|
|
5318
|
-
const requestId =
|
|
5502
|
+
const requestId = randomUUID3();
|
|
5319
5503
|
const pending = this.pending(this.pendingQuestions, requestId);
|
|
5320
5504
|
this.event("question/requested", {
|
|
5321
5505
|
requestId,
|
|
@@ -5324,7 +5508,7 @@ var DirectClaudeSdkSession = class DirectClaudeSdkSession2 {
|
|
|
5324
5508
|
return await pending;
|
|
5325
5509
|
}
|
|
5326
5510
|
async bridgeCall(bridge, op, input) {
|
|
5327
|
-
const requestId =
|
|
5511
|
+
const requestId = randomUUID3();
|
|
5328
5512
|
const pending = this.pending(this.pendingBridges, requestId);
|
|
5329
5513
|
this.event("bridge/requested", {
|
|
5330
5514
|
requestId,
|
|
@@ -9680,7 +9864,7 @@ var PlanFileStore = class {
|
|
|
9680
9864
|
async write(sessionId, body) {
|
|
9681
9865
|
const file = planFilePath(sessionId);
|
|
9682
9866
|
await mkdir4(dirname2(file), { recursive: true });
|
|
9683
|
-
const temporary = `${file}.${
|
|
9867
|
+
const temporary = `${file}.${randomUUID4()}.tmp`;
|
|
9684
9868
|
await writeFile3(temporary, body.endsWith("\n") ? body : `${body}
|
|
9685
9869
|
`, "utf8");
|
|
9686
9870
|
await rename3(temporary, file);
|
|
@@ -12726,6 +12910,11 @@ function mediaCategoryForManagedModel(model) {
|
|
|
12726
12910
|
if (protocol === "audio_speech" || protocol === "audio-speech" || protocol === "audio_transcription" || protocol === "audio-transcription") return "audio";
|
|
12727
12911
|
return inferMediaCategory(`${model.id} ${model.displayName}`);
|
|
12728
12912
|
}
|
|
12913
|
+
function isTextConversationRoute(model, overrides = {}) {
|
|
12914
|
+
const configured = overrides[mediaCategoryOverrideKey(model.provider, model.id)];
|
|
12915
|
+
if (configured !== void 0) return configured === "text";
|
|
12916
|
+
return mediaCategoryForManagedModel(model) === void 0;
|
|
12917
|
+
}
|
|
12729
12918
|
function logfareMediaCategory(model) {
|
|
12730
12919
|
const endpoints = model.endpoints.join(" ").toLowerCase();
|
|
12731
12920
|
if (endpoints.includes("image")) return "image";
|
|
@@ -17018,7 +17207,7 @@ function cosyBuildPayload(info) {
|
|
|
17018
17207
|
cosyVersion: COSY_VERSION,
|
|
17019
17208
|
ideVersion: "",
|
|
17020
17209
|
info,
|
|
17021
|
-
requestId:
|
|
17210
|
+
requestId: randomUUID4(),
|
|
17022
17211
|
version: "v1"
|
|
17023
17212
|
}), "utf8").toString("base64");
|
|
17024
17213
|
}
|
|
@@ -17288,12 +17477,12 @@ function buildQoderChatBody(input, identity, defaults = {}) {
|
|
|
17288
17477
|
}
|
|
17289
17478
|
const prompt = lastUserPrompt(input.messages);
|
|
17290
17479
|
const maxTokens = input.maxTokens !== void 0 && input.maxTokens > 0 ? input.maxTokens : defaults.defaultMaxTokens ?? 32768;
|
|
17291
|
-
const requestId =
|
|
17292
|
-
const businessId =
|
|
17480
|
+
const requestId = randomUUID4();
|
|
17481
|
+
const businessId = randomUUID4();
|
|
17293
17482
|
const title = prompt.length > 30 ? prompt.slice(0, 30) : prompt;
|
|
17294
17483
|
return {
|
|
17295
17484
|
request_id: requestId,
|
|
17296
|
-
request_set_id:
|
|
17485
|
+
request_set_id: randomUUID4(),
|
|
17297
17486
|
chat_record_id: requestId,
|
|
17298
17487
|
stream: true,
|
|
17299
17488
|
chat_task: "FREE_INPUT",
|
|
@@ -17320,7 +17509,7 @@ function buildQoderChatBody(input, identity, defaults = {}) {
|
|
|
17320
17509
|
image_urls: null,
|
|
17321
17510
|
is_reply: true,
|
|
17322
17511
|
is_retry: false,
|
|
17323
|
-
session_id:
|
|
17512
|
+
session_id: randomUUID4(),
|
|
17324
17513
|
code_language: "",
|
|
17325
17514
|
source: 1,
|
|
17326
17515
|
version: "3",
|
|
@@ -20793,7 +20982,9 @@ var FreeCodeGoManagedCatalogs = class {
|
|
|
20793
20982
|
},
|
|
20794
20983
|
inputModalities: imageInputModalities(model.id, model.displayName)
|
|
20795
20984
|
});
|
|
20796
|
-
const
|
|
20985
|
+
const modelCategories = this.deps.settings()?.get()?.modelCategories ?? {};
|
|
20986
|
+
const chatModels = (managed?.models ?? []).filter((model) => isTextConversationRoute(model, modelCategories));
|
|
20987
|
+
const options = chatModels.flatMap((model) => {
|
|
20797
20988
|
const groupedChoices = model.choices.filter((choice) => choice.groupId !== void 0);
|
|
20798
20989
|
return groupedChoices.length === 0 ? [] : [{
|
|
20799
20990
|
model: model.id,
|
|
@@ -20813,7 +21004,7 @@ var FreeCodeGoManagedCatalogs = class {
|
|
|
20813
21004
|
}))
|
|
20814
21005
|
}];
|
|
20815
21006
|
}) ?? [];
|
|
20816
|
-
const rows = expandGroupPinnedModels(
|
|
21007
|
+
const rows = expandGroupPinnedModels(chatModels.map(availabilityRow), options).map((model) => {
|
|
20817
21008
|
const pinned = model.__groupLabel !== void 0;
|
|
20818
21009
|
const name2 = pinned ? `${model.displayName} \xB7 ${model.__groupLabel}` : model.displayName;
|
|
20819
21010
|
const groupBlock = modelRowGroupBlock(model);
|
|
@@ -23022,7 +23213,7 @@ var ClaudeProtocolBridge = class {
|
|
|
23022
23213
|
async endpoint(provider, model, reasoningEffort) {
|
|
23023
23214
|
await this.start();
|
|
23024
23215
|
this.pruneRoutes();
|
|
23025
|
-
const id =
|
|
23216
|
+
const id = randomUUID4();
|
|
23026
23217
|
this.routes.set(id, {
|
|
23027
23218
|
provider,
|
|
23028
23219
|
model,
|
|
@@ -23042,7 +23233,7 @@ var ClaudeProtocolBridge = class {
|
|
|
23042
23233
|
async openAIEndpoint(provider, model) {
|
|
23043
23234
|
await this.start();
|
|
23044
23235
|
this.pruneRoutes();
|
|
23045
|
-
const id =
|
|
23236
|
+
const id = randomUUID4();
|
|
23046
23237
|
this.routes.set(id, {
|
|
23047
23238
|
provider,
|
|
23048
23239
|
model,
|
|
@@ -23146,7 +23337,7 @@ var ClaudeProtocolBridge = class {
|
|
|
23146
23337
|
writeEvent(writer, "message_start", {
|
|
23147
23338
|
type: "message_start",
|
|
23148
23339
|
message: {
|
|
23149
|
-
id: `msg_${
|
|
23340
|
+
id: `msg_${randomUUID4()}`,
|
|
23150
23341
|
type: "message",
|
|
23151
23342
|
role: "assistant",
|
|
23152
23343
|
model,
|
|
@@ -23170,7 +23361,7 @@ var ClaudeProtocolBridge = class {
|
|
|
23170
23361
|
index,
|
|
23171
23362
|
content_block: {
|
|
23172
23363
|
type: "tool_use",
|
|
23173
|
-
id: call.id ?? `tool_${
|
|
23364
|
+
id: call.id ?? `tool_${randomUUID4()}`,
|
|
23174
23365
|
name: call.name ?? "tool",
|
|
23175
23366
|
input: {}
|
|
23176
23367
|
}
|
|
@@ -23353,8 +23544,8 @@ var ClaudeProtocolBridge = class {
|
|
|
23353
23544
|
connection: "keep-alive"
|
|
23354
23545
|
});
|
|
23355
23546
|
const writer = new StreamWriter(res);
|
|
23356
|
-
const responseId = `resp_${
|
|
23357
|
-
const itemId = `msg_${
|
|
23547
|
+
const responseId = `resp_${randomUUID4()}`;
|
|
23548
|
+
const itemId = `msg_${randomUUID4()}`;
|
|
23358
23549
|
writeData(writer, {
|
|
23359
23550
|
type: "response.created",
|
|
23360
23551
|
response: {
|
|
@@ -23416,7 +23607,7 @@ var ClaudeProtocolBridge = class {
|
|
|
23416
23607
|
if (call === void 0) {
|
|
23417
23608
|
call = {
|
|
23418
23609
|
itemIndex: nextCall++,
|
|
23419
|
-
itemId: `fc_${
|
|
23610
|
+
itemId: `fc_${randomUUID4()}`,
|
|
23420
23611
|
id: "",
|
|
23421
23612
|
name: chunk.name ?? "tool",
|
|
23422
23613
|
args: "",
|
|
@@ -23790,7 +23981,7 @@ async function anthropicMessages(value, resolve3) {
|
|
|
23790
23981
|
if (part.type === "tool_use") {
|
|
23791
23982
|
blocks.push({
|
|
23792
23983
|
type: "tool-call",
|
|
23793
|
-
id: callId$1(String(part.id ??
|
|
23984
|
+
id: callId$1(String(part.id ?? randomUUID4())),
|
|
23794
23985
|
name: String(part.name ?? "tool"),
|
|
23795
23986
|
arguments: JSON.stringify(part.input ?? {})
|
|
23796
23987
|
});
|
|
@@ -23880,7 +24071,7 @@ function toNonStreamingResponse(chunks, model) {
|
|
|
23880
24071
|
});
|
|
23881
24072
|
for (const call of accumulateToolCalls(chunks)) blocks.push({
|
|
23882
24073
|
type: "tool_use",
|
|
23883
|
-
id: call.id !== "" ? call.id : `tool_${
|
|
24074
|
+
id: call.id !== "" ? call.id : `tool_${randomUUID4()}`,
|
|
23884
24075
|
name: call.name,
|
|
23885
24076
|
input: parseArguments(call.args)
|
|
23886
24077
|
});
|
|
@@ -23888,7 +24079,7 @@ function toNonStreamingResponse(chunks, model) {
|
|
|
23888
24079
|
const usage2 = chunks.find((chunk) => chunk.type === "usage")?.usage;
|
|
23889
24080
|
const stopReason2 = finish?.reason.kind === "tool-calls" ? "tool_use" : finish?.reason.kind === "max-tokens" ? "max_tokens" : finish?.reason.kind === "error" ? "stop_sequence" : "end_turn";
|
|
23890
24081
|
return {
|
|
23891
|
-
id: `msg_${
|
|
24082
|
+
id: `msg_${randomUUID4()}`,
|
|
23892
24083
|
type: "message",
|
|
23893
24084
|
role: "assistant",
|
|
23894
24085
|
model,
|
|
@@ -23904,7 +24095,7 @@ function toNonStreamingResponse(chunks, model) {
|
|
|
23904
24095
|
function toResponsesObject(chunks, model) {
|
|
23905
24096
|
const text2 = chunks.filter((chunk) => chunk.type === "text-delta").map((chunk) => chunk.text).join("");
|
|
23906
24097
|
const output = [{
|
|
23907
|
-
id: `msg_${
|
|
24098
|
+
id: `msg_${randomUUID4()}`,
|
|
23908
24099
|
type: "message",
|
|
23909
24100
|
status: "completed",
|
|
23910
24101
|
role: "assistant",
|
|
@@ -23917,10 +24108,10 @@ function toResponsesObject(chunks, model) {
|
|
|
23917
24108
|
for (const call of accumulateToolCalls(chunks)) {
|
|
23918
24109
|
hasCalls = true;
|
|
23919
24110
|
output.push({
|
|
23920
|
-
id: `fc_${
|
|
24111
|
+
id: `fc_${randomUUID4()}`,
|
|
23921
24112
|
type: "function_call",
|
|
23922
24113
|
status: "completed",
|
|
23923
|
-
call_id: call.id !== "" ? call.id : `call_${
|
|
24114
|
+
call_id: call.id !== "" ? call.id : `call_${randomUUID4()}`,
|
|
23924
24115
|
name: call.name,
|
|
23925
24116
|
arguments: call.args
|
|
23926
24117
|
});
|
|
@@ -23928,7 +24119,7 @@ function toResponsesObject(chunks, model) {
|
|
|
23928
24119
|
const finish = chunks.find((chunk) => chunk.type === "finish");
|
|
23929
24120
|
const usage2 = chunks.find((chunk) => chunk.type === "usage")?.usage;
|
|
23930
24121
|
return {
|
|
23931
|
-
id: `resp_${
|
|
24122
|
+
id: `resp_${randomUUID4()}`,
|
|
23932
24123
|
object: "response",
|
|
23933
24124
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23934
24125
|
status: hasCalls || finish?.reason.kind !== "error" ? "completed" : "failed",
|
|
@@ -24688,7 +24879,7 @@ var GraphifyRuntimeManager = class {
|
|
|
24688
24879
|
if (input.packageId === "existing-python" && !existsSync2(resolve2(requestedPython))) throw new Error("\u6307\u5B9A\u7684 Python \u53EF\u6267\u884C\u6587\u4EF6\u4E0D\u5B58\u5728\u3002");
|
|
24689
24880
|
await this.ensurePrivateDirectory(this.rootDirectory);
|
|
24690
24881
|
const uv = await this.ensureUv();
|
|
24691
|
-
const staging = join4(this.rootDirectory, `.install-${
|
|
24882
|
+
const staging = join4(this.rootDirectory, `.install-${randomUUID4()}`);
|
|
24692
24883
|
await rm2(staging, {
|
|
24693
24884
|
recursive: true,
|
|
24694
24885
|
force: true
|
|
@@ -24826,8 +25017,8 @@ var GraphifyRuntimeManager = class {
|
|
|
24826
25017
|
await this.ensurePrivateDirectory(tools);
|
|
24827
25018
|
const executable = platform2() === "win32" ? "uv.exe" : "uv";
|
|
24828
25019
|
const target = join4(tools, executable);
|
|
24829
|
-
const staged = `${target}.${
|
|
24830
|
-
const archivePath = join4(tools, `.uv-archive-${
|
|
25020
|
+
const staged = `${target}.${randomUUID4()}`;
|
|
25021
|
+
const archivePath = join4(tools, `.uv-archive-${randomUUID4()}`);
|
|
24831
25022
|
await downloadVerifiedAsset({
|
|
24832
25023
|
url: archive.url,
|
|
24833
25024
|
digest: archive.digest,
|
|
@@ -26113,7 +26304,7 @@ var FreeCodeGoCapabilityRegistry = class {
|
|
|
26113
26304
|
if (!this.configuration().mcpEnabled) throw new Error("MCP is disabled in FreeCodeGo settings");
|
|
26114
26305
|
if (!name2.startsWith("mcp__") || !this.mcpTools(agent).some((tool2) => tool2.name === name2)) throw new Error(`MCP tool "${name2}" is not active`);
|
|
26115
26306
|
const result = await this.ctx.tools.execute({
|
|
26116
|
-
callId: callId2(`freecodego-mcp-${
|
|
26307
|
+
callId: callId2(`freecodego-mcp-${randomUUID4()}`),
|
|
26117
26308
|
name: name2,
|
|
26118
26309
|
arguments: args,
|
|
26119
26310
|
...agent === void 0 ? {} : { agent },
|
|
@@ -26142,7 +26333,7 @@ var FreeCodeGoCapabilityRegistry = class {
|
|
|
26142
26333
|
async executeHarnessTool(agent, name2, args, signal, options = {}) {
|
|
26143
26334
|
if (!this.harnessTools(agent).some((tool2) => tool2.name === name2)) throw new Error(`Harness tool "${name2}" is not available to this native Agent`);
|
|
26144
26335
|
const result = await this.ctx.tools.execute({
|
|
26145
|
-
callId: callId2(`freecodego-harness-${
|
|
26336
|
+
callId: callId2(`freecodego-harness-${randomUUID4()}`),
|
|
26146
26337
|
name: name2,
|
|
26147
26338
|
arguments: args,
|
|
26148
26339
|
...agent === void 0 ? {} : { agent },
|
|
@@ -26551,7 +26742,7 @@ function restoreRedactedMcpSecrets(input, previous) {
|
|
|
26551
26742
|
}
|
|
26552
26743
|
function normalizeMcpServer(input) {
|
|
26553
26744
|
const server = {
|
|
26554
|
-
id: input.id?.trim() ||
|
|
26745
|
+
id: input.id?.trim() || randomUUID4(),
|
|
26555
26746
|
enabled: input.enabled,
|
|
26556
26747
|
transport: input.transport,
|
|
26557
26748
|
serverName: input.serverName.trim(),
|
|
@@ -26570,7 +26761,7 @@ function normalizeSkillRoot(input) {
|
|
|
26570
26761
|
if (configuredPath === "") throw new Error("Skill root path is required");
|
|
26571
26762
|
if (!isAbsolute2(configuredPath)) throw new Error("Skill root path must be absolute");
|
|
26572
26763
|
return {
|
|
26573
|
-
id: input.id?.trim() ||
|
|
26764
|
+
id: input.id?.trim() || randomUUID4(),
|
|
26574
26765
|
enabled: input.enabled,
|
|
26575
26766
|
path: resolve2(configuredPath)
|
|
26576
26767
|
};
|
|
@@ -28024,7 +28215,7 @@ async function preparePendingUpdateStartup(profile, marker) {
|
|
|
28024
28215
|
}
|
|
28025
28216
|
async function writePendingUpdateMarker(profile, marker) {
|
|
28026
28217
|
const file = pendingUpdateMarkerPath(profile);
|
|
28027
|
-
const temporary = `${file}.${
|
|
28218
|
+
const temporary = `${file}.${randomUUID4()}.tmp`;
|
|
28028
28219
|
try {
|
|
28029
28220
|
await writeFile3(temporary, `${JSON.stringify(marker)}
|
|
28030
28221
|
`, {
|
|
@@ -30589,7 +30780,7 @@ var FreeCodeGoEngineCouncil = class {
|
|
|
30589
30780
|
}
|
|
30590
30781
|
const cwd = parent.session.header.cwd;
|
|
30591
30782
|
if (cwd === void 0 || cwd.trim() === "") throw new Error("engineering council child requires a workspace-backed parent session");
|
|
30592
|
-
const sessionId = SessionId(
|
|
30783
|
+
const sessionId = SessionId(randomUUID4());
|
|
30593
30784
|
const agentOptions = {
|
|
30594
30785
|
provider: runtime.provider,
|
|
30595
30786
|
...runtime.model === void 0 ? {} : { model: runtime.model },
|
|
@@ -30995,7 +31186,7 @@ function safeError(error) {
|
|
|
30995
31186
|
return redactCredentialShapes2(error instanceof Error ? error.message : String(error));
|
|
30996
31187
|
}
|
|
30997
31188
|
function councilId() {
|
|
30998
|
-
return `council_${
|
|
31189
|
+
return `council_${randomUUID4().replaceAll("-", "")}`;
|
|
30999
31190
|
}
|
|
31000
31191
|
function projectIdFor$3(cwd) {
|
|
31001
31192
|
return createHash3("sha256").update(resolve2(cwd).replaceAll("\\", "/").toLowerCase()).digest("hex").slice(0, 24);
|
|
@@ -31375,7 +31566,7 @@ var EngineeringMemoryStore = class {
|
|
|
31375
31566
|
const hash2 = createHash3("sha256").update(`${projectId}\0${title}\0${body}\0${kind}\0${JSON.stringify([...tags].sort())}`).digest("hex");
|
|
31376
31567
|
const duplicate = database.prepare("SELECT id, title, kind, trust, project_id, body, tags_json, source_engine, created_at FROM engineering_memories WHERE project_id = ? AND content_hash = ? ORDER BY created_at DESC LIMIT 1").get(projectId, hash2);
|
|
31377
31568
|
if (duplicate !== void 0) return this.detailFor(database, duplicate);
|
|
31378
|
-
const id = `mem_${
|
|
31569
|
+
const id = `mem_${randomUUID4().replaceAll("-", "")}`;
|
|
31379
31570
|
const now = Date.now();
|
|
31380
31571
|
database.prepare("INSERT INTO engineering_memories(id, project_id, title, kind, trust, body, tags_json, source_engine, created_at, updated_at, content_hash) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(id, projectId, title, kind, "draft", body, JSON.stringify(tags), sourceEngine ?? null, now, now, hash2);
|
|
31381
31572
|
return {
|
|
@@ -31403,7 +31594,7 @@ var EngineeringMemoryStore = class {
|
|
|
31403
31594
|
const payload = normalizeObservation(input);
|
|
31404
31595
|
const projectId = projectIdFor$2(payload.cwd);
|
|
31405
31596
|
const now = Date.now();
|
|
31406
|
-
const id = `out_${
|
|
31597
|
+
const id = `out_${randomUUID4().replaceAll("-", "")}`;
|
|
31407
31598
|
return {
|
|
31408
31599
|
queued: database.prepare("INSERT OR IGNORE INTO engineering_memory_outbox(id, project_id, generation_key, payload_json, state, attempts, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 0, ?, ?)").run(id, projectId, payload.generation, JSON.stringify(payload), "queued", now, now).changes === 1,
|
|
31409
31600
|
id
|
|
@@ -31494,7 +31685,7 @@ var EngineeringMemoryStore = class {
|
|
|
31494
31685
|
const hash2 = createHash3("sha256").update(`${projectId}\0${payload.generation}\0${title}\0${body}`).digest("hex");
|
|
31495
31686
|
const duplicate = database.prepare("SELECT id, title, kind, trust, project_id, body, tags_json, source_engine, created_at FROM engineering_memories WHERE project_id = ? AND content_hash = ? LIMIT 1").get(projectId, hash2);
|
|
31496
31687
|
if (duplicate !== void 0) return this.detailFor(database, duplicate);
|
|
31497
|
-
const id = `mem_${
|
|
31688
|
+
const id = `mem_${randomUUID4().replaceAll("-", "")}`;
|
|
31498
31689
|
const now = Date.now();
|
|
31499
31690
|
database.prepare("INSERT INTO engineering_memories(id, project_id, title, subject, kind, trust, body, tags_json, source_engine, created_at, updated_at, content_hash) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(id, projectId, title, subject ?? null, payload.kind, "captured", body, JSON.stringify(payload.tags), payload.sourceEngine ?? null, now, now, hash2);
|
|
31500
31691
|
const insertSource = database.prepare("INSERT INTO engineering_memory_sources(memory_id, source_index, session_id, event_sequence, event_type, turn, engine, provider, model, files_read_json, files_written_json, captured_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
@@ -31805,7 +31996,7 @@ var EngineeringMemoryStore = class {
|
|
|
31805
31996
|
async backup() {
|
|
31806
31997
|
const database = this.requireDatabase();
|
|
31807
31998
|
const createdAt = Date.now();
|
|
31808
|
-
const id = `backup_${createdAt}_${
|
|
31999
|
+
const id = `backup_${createdAt}_${randomUUID4().replaceAll("-", "").slice(0, 12)}`;
|
|
31809
32000
|
const directory = join4(dirname2(this.databasePath), "backups");
|
|
31810
32001
|
await mkdir4(directory, {
|
|
31811
32002
|
recursive: true,
|
|
@@ -33026,7 +33217,7 @@ var CodeGraphRuntimeManager = class {
|
|
|
33026
33217
|
const archive = codegraphArchive();
|
|
33027
33218
|
if (archive === void 0) throw new Error("\u5F53\u524D\u7CFB\u7EDF\u6CA1\u6709\u7ECF\u8FC7\u9A8C\u8BC1\u7684 CodeGraph \u5B98\u65B9\u5E73\u53F0\u5305\u3002");
|
|
33028
33219
|
await ensurePrivateDirectory(this.rootDirectory, "CodeGraph");
|
|
33029
|
-
const staging = join4(this.rootDirectory, `.install-${
|
|
33220
|
+
const staging = join4(this.rootDirectory, `.install-${randomUUID4()}`);
|
|
33030
33221
|
await rm2(staging, {
|
|
33031
33222
|
recursive: true,
|
|
33032
33223
|
force: true
|
|
@@ -33424,7 +33615,7 @@ var EngineeringVerificationJobs = class {
|
|
|
33424
33615
|
*/
|
|
33425
33616
|
start(cwd, stages, probes = []) {
|
|
33426
33617
|
const database = this.requireDatabase();
|
|
33427
|
-
const id = `job_${
|
|
33618
|
+
const id = `job_${randomUUID4().replaceAll("-", "")}`;
|
|
33428
33619
|
const createdAt = Date.now();
|
|
33429
33620
|
const projectId = projectIdFor$1(cwd);
|
|
33430
33621
|
database.prepare("INSERT INTO engineering_jobs(id, project_id, kind, state, created_at) VALUES (?, ?, ?, ?, ?)").run(id, projectId, "verification", "queued", createdAt);
|
|
@@ -33468,7 +33659,7 @@ var EngineeringVerificationJobs = class {
|
|
|
33468
33659
|
const current = this.get(job.id);
|
|
33469
33660
|
if (current.verification !== void 0) return current.verification;
|
|
33470
33661
|
if (current.state === "cancelled" || current.state === "interrupted" || current.state === "failed" || current.state === "completed") return {
|
|
33471
|
-
id: `verify_${
|
|
33662
|
+
id: `verify_${randomUUID4().replaceAll("-", "")}`,
|
|
33472
33663
|
checkedAt: Date.now(),
|
|
33473
33664
|
stages: [{
|
|
33474
33665
|
id: "scope",
|
|
@@ -33590,7 +33781,7 @@ var EngineeringVerificationJobs = class {
|
|
|
33590
33781
|
});
|
|
33591
33782
|
const redacted = (summary2) => redactJobSummary(summary2);
|
|
33592
33783
|
const view = {
|
|
33593
|
-
id: `verify_${
|
|
33784
|
+
id: `verify_${randomUUID4().replaceAll("-", "")}`,
|
|
33594
33785
|
checkedAt: Date.now(),
|
|
33595
33786
|
stages: result.stages.map((stage) => ({
|
|
33596
33787
|
...stage,
|
|
@@ -33843,7 +34034,7 @@ var EngineeringCheckpointStore = class {
|
|
|
33843
34034
|
continue;
|
|
33844
34035
|
}
|
|
33845
34036
|
const checkpoint = {
|
|
33846
|
-
id: `ckpt_${
|
|
34037
|
+
id: `ckpt_${randomUUID4().replaceAll("-", "").slice(0, 24)}`,
|
|
33847
34038
|
label: input.label.slice(0, 160).trim() || "checkpoint",
|
|
33848
34039
|
createdAt: Date.now(),
|
|
33849
34040
|
entries,
|
|
@@ -34128,7 +34319,7 @@ var EngineeringCheckpointStore = class {
|
|
|
34128
34319
|
recursive: true,
|
|
34129
34320
|
mode: 448
|
|
34130
34321
|
});
|
|
34131
|
-
const temporary = `${target}.${
|
|
34322
|
+
const temporary = `${target}.${randomUUID4()}.tmp`;
|
|
34132
34323
|
await writeFile3(temporary, content, { mode: 384 });
|
|
34133
34324
|
try {
|
|
34134
34325
|
await rename3(temporary, target);
|
|
@@ -34378,7 +34569,7 @@ var HunkTracker = class {
|
|
|
34378
34569
|
const at2 = input.at ?? Date.now();
|
|
34379
34570
|
const created = [];
|
|
34380
34571
|
for (const change of diffLines(before, after)) {
|
|
34381
|
-
const id =
|
|
34572
|
+
const id = randomUUID4();
|
|
34382
34573
|
created.push({
|
|
34383
34574
|
id,
|
|
34384
34575
|
file,
|
|
@@ -41399,7 +41590,7 @@ async function generateVideoWithFallback(host, args, signal) {
|
|
|
41399
41590
|
});
|
|
41400
41591
|
}
|
|
41401
41592
|
async function writeGeneratedMedia(file, bytes) {
|
|
41402
|
-
const temporary = `${file}.${
|
|
41593
|
+
const temporary = `${file}.${randomUUID4()}.tmp`;
|
|
41403
41594
|
try {
|
|
41404
41595
|
await fs.writeFile(temporary, bytes, {
|
|
41405
41596
|
mode: 384,
|
|
@@ -41446,7 +41637,7 @@ async function generateAudioWithFallback(host, args, cwd, signal) {
|
|
|
41446
41637
|
}
|
|
41447
41638
|
const directory = path.join(cwd, ".freecodego", "generated-media");
|
|
41448
41639
|
await fs.mkdir(directory, { recursive: true });
|
|
41449
|
-
const file = path.join(directory, `audio-${Date.now()}-${
|
|
41640
|
+
const file = path.join(directory, `audio-${Date.now()}-${randomUUID4().slice(0, 8)}.${extension}`);
|
|
41450
41641
|
await writeGeneratedMedia(file, bytes);
|
|
41451
41642
|
const mimeType = contentType.includes("json") || contentType === "" ? `audio/${extension}` : contentType;
|
|
41452
41643
|
return {
|
|
@@ -42454,7 +42645,7 @@ function validatePayloadFiles(files) {
|
|
|
42454
42645
|
return { ok: true };
|
|
42455
42646
|
}
|
|
42456
42647
|
async function writeStateFile(fs2, path3, text2) {
|
|
42457
|
-
const temp = `${path3}.${
|
|
42648
|
+
const temp = `${path3}.${randomUUID4()}.tmp`;
|
|
42458
42649
|
try {
|
|
42459
42650
|
await fs2.writeFile(temp, text2);
|
|
42460
42651
|
await fs2.rename(temp, path3);
|
|
@@ -42464,10 +42655,10 @@ async function writeStateFile(fs2, path3, text2) {
|
|
|
42464
42655
|
}
|
|
42465
42656
|
}
|
|
42466
42657
|
function stagingPath(root) {
|
|
42467
|
-
return join4(root, `.freecodego-staging-${
|
|
42658
|
+
return join4(root, `.freecodego-staging-${randomUUID4()}`);
|
|
42468
42659
|
}
|
|
42469
42660
|
function backupPath(root) {
|
|
42470
|
-
return join4(root, `.freecodego-backup-${
|
|
42661
|
+
return join4(root, `.freecodego-backup-${randomUUID4()}`);
|
|
42471
42662
|
}
|
|
42472
42663
|
async function installSkill(request, fs2 = NODE_INSTALLER_FS) {
|
|
42473
42664
|
const name2 = validateSkillName(request.payload.name);
|
|
@@ -50335,7 +50526,7 @@ var FolderTrustStore = class {
|
|
|
50335
50526
|
*/
|
|
50336
50527
|
async write(record3) {
|
|
50337
50528
|
await mkdir4(dirname2(this.file), { recursive: true });
|
|
50338
|
-
const temporary = `${this.file}.${
|
|
50529
|
+
const temporary = `${this.file}.${randomUUID4()}.tmp`;
|
|
50339
50530
|
await writeFile3(temporary, `${JSON.stringify(record3, null, 2)}
|
|
50340
50531
|
`, "utf8");
|
|
50341
50532
|
await rename3(temporary, this.file);
|
|
@@ -58618,7 +58809,7 @@ var DEFAULT_REVIEW_PLAN_TOOLS = [
|
|
|
58618
58809
|
];
|
|
58619
58810
|
async function runReview(deps, options) {
|
|
58620
58811
|
const now = deps.now ?? Date.now;
|
|
58621
|
-
const newId = deps.newId ??
|
|
58812
|
+
const newId = deps.newId ?? randomUUID4;
|
|
58622
58813
|
const limits = options.budget ?? DEFAULT_REVIEW_BUDGET;
|
|
58623
58814
|
const signal = options.signal;
|
|
58624
58815
|
const reviewerName = options.reviewerName ?? "reviewer";
|
|
@@ -59399,7 +59590,7 @@ function createSubagentFileReviewer(parent, options = {}) {
|
|
|
59399
59590
|
freeCodeGoReadOnly: true
|
|
59400
59591
|
};
|
|
59401
59592
|
return wrapChild(await parent.ctx.agents.create({
|
|
59402
|
-
sessionId: SessionId(
|
|
59593
|
+
sessionId: SessionId(randomUUID4()),
|
|
59403
59594
|
meta: {
|
|
59404
59595
|
cwd,
|
|
59405
59596
|
parentSession: parent.id,
|
|
@@ -60011,6 +60202,28 @@ function upstreamMessage(value, fallback) {
|
|
|
60011
60202
|
const message2 = typeof value === "string" ? value.trim() : "";
|
|
60012
60203
|
return redactCredentialShapes2(message2 === "" ? fallback : message2);
|
|
60013
60204
|
}
|
|
60205
|
+
async function accountAnnouncements(host) {
|
|
60206
|
+
if (host.account === void 0 || host.api === void 0) return [];
|
|
60207
|
+
try {
|
|
60208
|
+
await host.restoreAccount();
|
|
60209
|
+
return await host.account.withAccessToken((accessToken) => host.api.getAnnouncements({ accessToken }));
|
|
60210
|
+
} catch {
|
|
60211
|
+
return [];
|
|
60212
|
+
}
|
|
60213
|
+
}
|
|
60214
|
+
async function accountMarkAnnouncementRead(host, announcementId) {
|
|
60215
|
+
if (host.account === void 0 || host.api === void 0) return false;
|
|
60216
|
+
try {
|
|
60217
|
+
await host.restoreAccount();
|
|
60218
|
+
await host.account.withAccessToken((accessToken) => host.api.markAnnouncementRead({
|
|
60219
|
+
accessToken,
|
|
60220
|
+
announcementId
|
|
60221
|
+
}));
|
|
60222
|
+
return true;
|
|
60223
|
+
} catch {
|
|
60224
|
+
return false;
|
|
60225
|
+
}
|
|
60226
|
+
}
|
|
60014
60227
|
async function accountStatus(host) {
|
|
60015
60228
|
if (host.account === void 0 || host.api === void 0) return { status: "backend-not-configured" };
|
|
60016
60229
|
try {
|
|
@@ -60304,13 +60517,38 @@ async function nvidiaSetKey(host, value) {
|
|
|
60304
60517
|
host.ctx.emit("llm/adapters-updated");
|
|
60305
60518
|
return host.nvidiaStatus();
|
|
60306
60519
|
}
|
|
60520
|
+
async function bootstrapDeviceIdentity(host) {
|
|
60521
|
+
try {
|
|
60522
|
+
const deviceId = await host.account?.deviceId();
|
|
60523
|
+
if (deviceId === void 0) return {};
|
|
60524
|
+
const name2 = localDeviceName();
|
|
60525
|
+
return name2 === void 0 ? { deviceId } : {
|
|
60526
|
+
deviceId,
|
|
60527
|
+
deviceName: name2
|
|
60528
|
+
};
|
|
60529
|
+
} catch {
|
|
60530
|
+
return {};
|
|
60531
|
+
}
|
|
60532
|
+
}
|
|
60533
|
+
function localDeviceName() {
|
|
60534
|
+
try {
|
|
60535
|
+
const name2 = hostname().trim();
|
|
60536
|
+
return name2 === "" ? void 0 : name2;
|
|
60537
|
+
} catch {
|
|
60538
|
+
return;
|
|
60539
|
+
}
|
|
60540
|
+
}
|
|
60307
60541
|
async function backendBootstrap(host) {
|
|
60308
60542
|
if (host.api === void 0 || host.account === void 0) return { status: "backend-not-configured" };
|
|
60309
60543
|
try {
|
|
60310
60544
|
await host.restoreAccount();
|
|
60545
|
+
const identity = await bootstrapDeviceIdentity(host);
|
|
60311
60546
|
return {
|
|
60312
60547
|
status: "available",
|
|
60313
|
-
data: toJsonValue2(await host.account.withAccessToken((accessToken) => host.api.getBootstrap({
|
|
60548
|
+
data: toJsonValue2(await host.account.withAccessToken((accessToken) => host.api.getBootstrap({
|
|
60549
|
+
accessToken,
|
|
60550
|
+
...identity
|
|
60551
|
+
})))
|
|
60314
60552
|
};
|
|
60315
60553
|
} catch (error) {
|
|
60316
60554
|
return {
|
|
@@ -60397,7 +60635,11 @@ async function confirmAccountAuthorization(host, result) {
|
|
|
60397
60635
|
async function deviceSessions(host) {
|
|
60398
60636
|
if (host.api === void 0 || host.account === void 0) throw backendNotConfigured();
|
|
60399
60637
|
await host.restoreAccount();
|
|
60400
|
-
|
|
60638
|
+
const identity = await bootstrapDeviceIdentity(host);
|
|
60639
|
+
return host.account.withAccessToken((accessToken) => host.api.getDeviceSessions({
|
|
60640
|
+
accessToken,
|
|
60641
|
+
...identity
|
|
60642
|
+
}));
|
|
60401
60643
|
}
|
|
60402
60644
|
async function revokeDeviceSession(host, deviceId) {
|
|
60403
60645
|
if (host.api === void 0 || host.account === void 0) throw backendNotConfigured();
|
|
@@ -60972,7 +61214,7 @@ async function traeStartBrowserLogin(host, realmValue) {
|
|
|
60972
61214
|
const loginUrl = buildTraeLoginUrl(identity, traeCallbackUrl(listener.port), realm);
|
|
60973
61215
|
session = {
|
|
60974
61216
|
attempt: {
|
|
60975
|
-
state:
|
|
61217
|
+
state: randomUUID4(),
|
|
60976
61218
|
realm,
|
|
60977
61219
|
loginUrl,
|
|
60978
61220
|
machineId: identity.machineId,
|
|
@@ -75994,6 +76236,8 @@ var FreeCodeGoHarnessPlugin = (() => {
|
|
|
75994
76236
|
let _refreshAccount_decorators;
|
|
75995
76237
|
let _logout_decorators;
|
|
75996
76238
|
let _deviceSessions_decorators;
|
|
76239
|
+
let _announcements_decorators;
|
|
76240
|
+
let _markAnnouncementRead_decorators;
|
|
75997
76241
|
let _revokeDeviceSession_decorators;
|
|
75998
76242
|
let _revokeAllSessions_decorators;
|
|
75999
76243
|
let _backendCatalog_decorators;
|
|
@@ -76226,6 +76470,8 @@ var FreeCodeGoHarnessPlugin = (() => {
|
|
|
76226
76470
|
_refreshAccount_decorators = [Remote("accountRefresh")];
|
|
76227
76471
|
_logout_decorators = [Remote("accountLogout")];
|
|
76228
76472
|
_deviceSessions_decorators = [Remote("accountDeviceSessions")];
|
|
76473
|
+
_announcements_decorators = [Remote("accountAnnouncements")];
|
|
76474
|
+
_markAnnouncementRead_decorators = [Remote("accountMarkAnnouncementRead")];
|
|
76229
76475
|
_revokeDeviceSession_decorators = [Remote("accountRevokeDeviceSession")];
|
|
76230
76476
|
_revokeAllSessions_decorators = [Remote("accountRevokeAllSessions")];
|
|
76231
76477
|
_backendCatalog_decorators = [Remote("backendCatalog")];
|
|
@@ -77935,6 +78181,28 @@ var FreeCodeGoHarnessPlugin = (() => {
|
|
|
77935
78181
|
},
|
|
77936
78182
|
metadata: _metadata
|
|
77937
78183
|
}, null, _instanceExtraInitializers);
|
|
78184
|
+
__esDecorate(this, null, _announcements_decorators, {
|
|
78185
|
+
kind: "method",
|
|
78186
|
+
name: "announcements",
|
|
78187
|
+
static: false,
|
|
78188
|
+
private: false,
|
|
78189
|
+
access: {
|
|
78190
|
+
has: (obj) => "announcements" in obj,
|
|
78191
|
+
get: (obj) => obj.announcements
|
|
78192
|
+
},
|
|
78193
|
+
metadata: _metadata
|
|
78194
|
+
}, null, _instanceExtraInitializers);
|
|
78195
|
+
__esDecorate(this, null, _markAnnouncementRead_decorators, {
|
|
78196
|
+
kind: "method",
|
|
78197
|
+
name: "markAnnouncementRead",
|
|
78198
|
+
static: false,
|
|
78199
|
+
private: false,
|
|
78200
|
+
access: {
|
|
78201
|
+
has: (obj) => "markAnnouncementRead" in obj,
|
|
78202
|
+
get: (obj) => obj.markAnnouncementRead
|
|
78203
|
+
},
|
|
78204
|
+
metadata: _metadata
|
|
78205
|
+
}, null, _instanceExtraInitializers);
|
|
77938
78206
|
__esDecorate(this, null, _revokeDeviceSession_decorators, {
|
|
77939
78207
|
kind: "method",
|
|
77940
78208
|
name: "revokeDeviceSession",
|
|
@@ -82241,7 +82509,7 @@ ${detail.body}`
|
|
|
82241
82509
|
...outcome.fallbackReason === void 0 ? {} : { fallbackReason: outcome.fallbackReason }
|
|
82242
82510
|
};
|
|
82243
82511
|
},
|
|
82244
|
-
newSessionId: () =>
|
|
82512
|
+
newSessionId: () => randomUUID4(),
|
|
82245
82513
|
callerOf: (exec) => {
|
|
82246
82514
|
const agent = exec?.agent;
|
|
82247
82515
|
const cwd = agent?.session?.header?.cwd;
|
|
@@ -83868,6 +84136,25 @@ ${plan.text}
|
|
|
83868
84136
|
return deviceSessions(this.accountRemotesHost);
|
|
83869
84137
|
}
|
|
83870
84138
|
/**
|
|
84139
|
+
* Read the announcements the backend published to this account.
|
|
84140
|
+
*
|
|
84141
|
+
* Read by the notice bar on the chat surface, which polls it — the plugin has
|
|
84142
|
+
* no push channel to the backend, so "in time" means the next poll, not a
|
|
84143
|
+
* socket. An empty list is the answer for a signed-out or unreachable backend.
|
|
84144
|
+
* @returns the visible announcements, in the backend's own order.
|
|
84145
|
+
*/
|
|
84146
|
+
async announcements() {
|
|
84147
|
+
return accountAnnouncements(this.accountRemotesHost);
|
|
84148
|
+
}
|
|
84149
|
+
/**
|
|
84150
|
+
* Mark one announcement read for this account, so closing it holds everywhere.
|
|
84151
|
+
* @param announcementId - the announcement the user closed.
|
|
84152
|
+
* @returns whether the backend recorded the read.
|
|
84153
|
+
*/
|
|
84154
|
+
async markAnnouncementRead(announcementId) {
|
|
84155
|
+
return accountMarkAnnouncementRead(this.accountRemotesHost, announcementId);
|
|
84156
|
+
}
|
|
84157
|
+
/**
|
|
83871
84158
|
* Revoke one device session and report the sessions that remain.
|
|
83872
84159
|
* @param deviceId - id of the device session to revoke.
|
|
83873
84160
|
* @returns the sessions the account still has.
|