@clawos-dev/clawd 0.2.687 → 0.2.691
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.cjs +270 -95
- package/dist/cloud-persona-conversations.html +1 -1
- package/dist/cloud-persona-metrics.html +1 -1
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-CKWAbuoe.js → guest-DK7O40Xi.js} +144 -144
- package/dist/share-ui/assets/guest-bkR2YgJq.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-4rwUzpVX.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -43380,7 +43380,7 @@ var require_websocket = __commonJS({
|
|
|
43380
43380
|
var http2 = require("http");
|
|
43381
43381
|
var net2 = require("net");
|
|
43382
43382
|
var tls = require("tls");
|
|
43383
|
-
var { randomBytes: randomBytes2, createHash:
|
|
43383
|
+
var { randomBytes: randomBytes2, createHash: createHash6 } = require("crypto");
|
|
43384
43384
|
var { Duplex, Readable: Readable4 } = require("stream");
|
|
43385
43385
|
var { URL: URL2 } = require("url");
|
|
43386
43386
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -44040,7 +44040,7 @@ var require_websocket = __commonJS({
|
|
|
44040
44040
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
44041
44041
|
return;
|
|
44042
44042
|
}
|
|
44043
|
-
const digest =
|
|
44043
|
+
const digest = createHash6("sha1").update(key + GUID).digest("base64");
|
|
44044
44044
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
44045
44045
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
44046
44046
|
return;
|
|
@@ -44407,7 +44407,7 @@ var require_websocket_server = __commonJS({
|
|
|
44407
44407
|
var EventEmitter2 = require("events");
|
|
44408
44408
|
var http2 = require("http");
|
|
44409
44409
|
var { Duplex } = require("stream");
|
|
44410
|
-
var { createHash:
|
|
44410
|
+
var { createHash: createHash6 } = require("crypto");
|
|
44411
44411
|
var extension2 = require_extension();
|
|
44412
44412
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
44413
44413
|
var subprotocol2 = require_subprotocol();
|
|
@@ -44708,7 +44708,7 @@ var require_websocket_server = __commonJS({
|
|
|
44708
44708
|
);
|
|
44709
44709
|
}
|
|
44710
44710
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
44711
|
-
const digest =
|
|
44711
|
+
const digest = createHash6("sha1").update(key + GUID).digest("base64");
|
|
44712
44712
|
const headers = [
|
|
44713
44713
|
"HTTP/1.1 101 Switching Protocols",
|
|
44714
44714
|
"Upgrade: websocket",
|
|
@@ -46776,7 +46776,7 @@ function requireEnvironmentIdentity(stores, environment) {
|
|
|
46776
46776
|
var import_node_path89 = __toESM(require("path"), 1);
|
|
46777
46777
|
var import_node_fs68 = __toESM(require("fs"), 1);
|
|
46778
46778
|
var import_node_os33 = __toESM(require("os"), 1);
|
|
46779
|
-
var
|
|
46779
|
+
var import_node_crypto31 = require("crypto");
|
|
46780
46780
|
var import_node_url6 = require("url");
|
|
46781
46781
|
|
|
46782
46782
|
// src/logger.ts
|
|
@@ -48375,7 +48375,9 @@ function pushEventToBufferInPlace(next, event, deps) {
|
|
|
48375
48375
|
next.file = {
|
|
48376
48376
|
...next.file,
|
|
48377
48377
|
updatedAt: nowIso(deps),
|
|
48378
|
-
|
|
48378
|
+
// Only a local send carries `sender`. A user_text echoed by the engine stream (skill hint, interrupt marker) has no
|
|
48379
|
+
// turn stream of its own, so recording it would leave a pending turn that startup recovery replays to the Pod.
|
|
48380
|
+
...cloudPerTurn && isUserText && withSeq.sender && next.status !== "error" ? {
|
|
48379
48381
|
cloudConversationId: next.file.cloudConversationId ?? next.file.cloudExecutionId ?? cloudTurnId,
|
|
48380
48382
|
cloudPendingTurns: [...next.file.cloudPendingTurns ?? [], { id: cloudTurnId, text: withSeq.text }]
|
|
48381
48383
|
} : {},
|
|
@@ -53581,6 +53583,10 @@ async function centralRequest(opts, path111, init) {
|
|
|
53581
53583
|
}
|
|
53582
53584
|
clearTimeout(timer);
|
|
53583
53585
|
if (res.status === 401) {
|
|
53586
|
+
const detail = await res.json().catch(() => null);
|
|
53587
|
+
if (path111 === "/api/persona-cloud/github/oauth/token" && detail?.errorCode === "GITHUB_REAUTH_REQUIRED") {
|
|
53588
|
+
throw new CentralClientError("API_ERROR", typeof detail.message === "string" ? detail.message : "\u8BF7\u91CD\u65B0\u5173\u8054 GitHub", void 0, 401);
|
|
53589
|
+
}
|
|
53584
53590
|
throw new CentralClientError("UNAUTHORIZED", "login pass rejected by center");
|
|
53585
53591
|
}
|
|
53586
53592
|
if (!res.ok) {
|
|
@@ -53759,11 +53765,12 @@ async function centralGithubAuthToken(opts) {
|
|
|
53759
53765
|
const body = await centralRequest(opts, "/api/persona-cloud/github/oauth/token", {
|
|
53760
53766
|
method: "POST",
|
|
53761
53767
|
bearer: opts.loginPass,
|
|
53762
|
-
body: {}
|
|
53768
|
+
body: { ...opts.rejectedToken ? { rejectedToken: opts.rejectedToken } : {} }
|
|
53763
53769
|
});
|
|
53764
53770
|
if (body.token === null || body.token === void 0) return void 0;
|
|
53765
53771
|
if (typeof body.token !== "string" || !body.token) throw new CentralClientError("BAD_RESPONSE", "github/oauth/token: malformed token");
|
|
53766
|
-
|
|
53772
|
+
if (body.expiresAt !== void 0 && (typeof body.expiresAt !== "string" || !Number.isFinite(Date.parse(body.expiresAt)))) throw new CentralClientError("BAD_RESPONSE", "github/oauth/token: malformed expiry");
|
|
53773
|
+
return { token: body.token, login: typeof body.login === "string" ? body.login : "", ...typeof body.expiresAt === "string" ? { expiresAt: body.expiresAt } : {} };
|
|
53767
53774
|
}
|
|
53768
53775
|
async function centralClaimPublisher(opts) {
|
|
53769
53776
|
await centralRequest(opts, `/api/persona-cloud/personas/${encodeURIComponent(opts.personaId)}/publisher`, {
|
|
@@ -57519,8 +57526,8 @@ function createGhRunner(defaults) {
|
|
|
57519
57526
|
const baseTimeoutMs = defaults?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
57520
57527
|
const spawn17 = defaults?.execFile ?? import_node_child_process9.execFile;
|
|
57521
57528
|
return {
|
|
57522
|
-
run(args, opts) {
|
|
57523
|
-
const token = defaults?.token?.();
|
|
57529
|
+
async run(args, opts) {
|
|
57530
|
+
const token = await defaults?.token?.();
|
|
57524
57531
|
return new Promise((resolve9, reject) => {
|
|
57525
57532
|
spawn17(
|
|
57526
57533
|
"gh",
|
|
@@ -58044,25 +58051,59 @@ var CloudGatewayClient = class {
|
|
|
58044
58051
|
return list.find((p3) => p3.personaId === gatewayPersonaId)?.connectors ?? [];
|
|
58045
58052
|
}
|
|
58046
58053
|
async workspaceCommand(personaId2, input) {
|
|
58047
|
-
const
|
|
58048
|
-
const
|
|
58049
|
-
|
|
58050
|
-
|
|
58051
|
-
|
|
58052
|
-
|
|
58053
|
-
|
|
58054
|
-
|
|
58055
|
-
|
|
58056
|
-
|
|
58057
|
-
|
|
58054
|
+
const started = performance.now();
|
|
58055
|
+
const traceId = typeof input.traceId === "string" && /^[A-Za-z0-9:_-]{1,128}$/.test(input.traceId) ? input.traceId : crypto.randomUUID();
|
|
58056
|
+
const { traceId: _trace, ...body } = input;
|
|
58057
|
+
const meta = {
|
|
58058
|
+
traceId,
|
|
58059
|
+
sessionId: input.sessionId,
|
|
58060
|
+
personaId: personaId2,
|
|
58061
|
+
action: input.action,
|
|
58062
|
+
page: typeof input.page === "number" && Number.isInteger(input.page) && input.page >= 1 && input.page <= 1e3 ? input.page : void 0,
|
|
58063
|
+
hasSearch: typeof input.search === "string" && input.search.length > 0,
|
|
58064
|
+
searchLength: typeof input.search === "string" ? input.search.length : 0,
|
|
58065
|
+
hasCursor: typeof input.cursor === "string"
|
|
58066
|
+
};
|
|
58067
|
+
const log = (event, detail) => {
|
|
58068
|
+
try {
|
|
58069
|
+
this.deps.logger?.info("cloud.workspace.daemon." + event, { ...meta, ...detail });
|
|
58070
|
+
} catch {
|
|
58058
58071
|
}
|
|
58059
|
-
|
|
58060
|
-
const
|
|
58061
|
-
|
|
58062
|
-
|
|
58063
|
-
|
|
58064
|
-
|
|
58065
|
-
|
|
58072
|
+
};
|
|
58073
|
+
const measure = async (stage, run) => {
|
|
58074
|
+
const at3 = performance.now();
|
|
58075
|
+
let outcome2 = "error";
|
|
58076
|
+
try {
|
|
58077
|
+
const value = await run();
|
|
58078
|
+
outcome2 = "ok";
|
|
58079
|
+
return value;
|
|
58080
|
+
} finally {
|
|
58081
|
+
log("stage", { stage, outcome: outcome2, durationMs: Math.round(performance.now() - at3) });
|
|
58082
|
+
}
|
|
58083
|
+
};
|
|
58084
|
+
let outcome = "error";
|
|
58085
|
+
let statusCode;
|
|
58086
|
+
log("started", {});
|
|
58087
|
+
try {
|
|
58088
|
+
const { apiKey, gatewayUrl } = await measure("credentials", () => this.credentials());
|
|
58089
|
+
const res = await measure("gateway.headers", () => this.fetchImpl(
|
|
58090
|
+
gatewayUrl + GATEWAY_ROUTES.workspace(personaId2),
|
|
58091
|
+
{
|
|
58092
|
+
method: "POST",
|
|
58093
|
+
headers: { authorization: "Bearer " + apiKey, "content-type": "application/json", "x-trace-id": traceId },
|
|
58094
|
+
body: JSON.stringify(body),
|
|
58095
|
+
signal: AbortSignal.timeout(3e5)
|
|
58096
|
+
}
|
|
58097
|
+
));
|
|
58098
|
+
statusCode = res.status;
|
|
58099
|
+
const result = await measure("gateway.body", () => res.json());
|
|
58100
|
+
if (!res.ok) throw new Error(result.error?.message ?? "Cloud workspace request failed (" + res.status + ")");
|
|
58101
|
+
const parsed = CloudWorkspaceResultSchema.parse(result);
|
|
58102
|
+
outcome = "ok";
|
|
58103
|
+
return parsed;
|
|
58104
|
+
} finally {
|
|
58105
|
+
log("finished", { outcome, statusCode, durationMs: Math.round(performance.now() - started) });
|
|
58106
|
+
}
|
|
58066
58107
|
}
|
|
58067
58108
|
async openTurn(personaId2, opts) {
|
|
58068
58109
|
const { apiKey, gatewayUrl } = await this.credentials();
|
|
@@ -62165,23 +62206,38 @@ function createGithubApi(args) {
|
|
|
62165
62206
|
const seal = args.seal ?? sealWithSodium;
|
|
62166
62207
|
const timeoutMs = args.timeoutMs ?? TIMEOUT_MS;
|
|
62167
62208
|
const secretsPath = (slug, environment) => `/repos/${slug}/${environment ? `environments/${encodeURIComponent(environment)}` : "actions"}/secrets`;
|
|
62168
|
-
async function
|
|
62169
|
-
let
|
|
62170
|
-
|
|
62171
|
-
|
|
62172
|
-
|
|
62173
|
-
|
|
62174
|
-
|
|
62175
|
-
|
|
62176
|
-
|
|
62177
|
-
|
|
62178
|
-
}
|
|
62179
|
-
|
|
62180
|
-
|
|
62181
|
-
}
|
|
62182
|
-
|
|
62183
|
-
|
|
62209
|
+
async function authenticatedFetch(path111, init) {
|
|
62210
|
+
let token = args.identity ? (await args.identity.refresh())?.token : args.token;
|
|
62211
|
+
if (!token) throw new GithubApiError(401, "\u8BF7\u5148\u5173\u8054 GitHub");
|
|
62212
|
+
for (let attempt = 0; ; attempt++) {
|
|
62213
|
+
let res;
|
|
62214
|
+
try {
|
|
62215
|
+
res = await doFetch(API + path111, {
|
|
62216
|
+
...init,
|
|
62217
|
+
headers: { ...init.headers, Authorization: "Bearer " + token },
|
|
62218
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
62219
|
+
});
|
|
62220
|
+
} catch (err) {
|
|
62221
|
+
throw new GithubApiError(0, "\u8FDE\u4E0D\u4E0A GitHub\uFF1A" + (err instanceof Error ? err.message : String(err)));
|
|
62222
|
+
}
|
|
62223
|
+
if (res.status !== 401 || attempt !== 0 || !args.identity) return res;
|
|
62224
|
+
const renewed = await args.identity.recover(token);
|
|
62225
|
+
if (!renewed || renewed.token === token) return res;
|
|
62226
|
+
await res.body?.cancel();
|
|
62227
|
+
token = renewed.token;
|
|
62184
62228
|
}
|
|
62229
|
+
}
|
|
62230
|
+
async function request(method, path111, body) {
|
|
62231
|
+
const res = await authenticatedFetch(path111, {
|
|
62232
|
+
method,
|
|
62233
|
+
redirect: "error",
|
|
62234
|
+
headers: {
|
|
62235
|
+
Accept: "application/vnd.github+json",
|
|
62236
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
62237
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
62238
|
+
},
|
|
62239
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
62240
|
+
});
|
|
62185
62241
|
const text = await res.text();
|
|
62186
62242
|
let json = void 0;
|
|
62187
62243
|
if (text) {
|
|
@@ -62266,8 +62322,8 @@ function createGithubApi(args) {
|
|
|
62266
62322
|
const signal = AbortSignal.timeout(timeoutMs);
|
|
62267
62323
|
let res;
|
|
62268
62324
|
try {
|
|
62269
|
-
res = await
|
|
62270
|
-
headers: {
|
|
62325
|
+
res = await authenticatedFetch(`/repos/${slug}/actions/artifacts/${artifactId}/zip`, {
|
|
62326
|
+
headers: { Accept: "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28" },
|
|
62271
62327
|
redirect: "manual",
|
|
62272
62328
|
signal
|
|
62273
62329
|
});
|
|
@@ -62892,7 +62948,8 @@ function networkOptions(auth) {
|
|
|
62892
62948
|
return auth?.source === "file" ? { prefix: [...QUIET_GIT_ARGS, "-c", "credential.helper=", "-c", `credential.helper=${INLINE_HELPER}`], env: { ...QUIET_GIT_ENV, CLAWD_GITHUB_TOKEN: auth.token } } : { prefix: [...QUIET_GIT_ARGS], env: QUIET_GIT_ENV };
|
|
62893
62949
|
}
|
|
62894
62950
|
async function networkGit(exec, dir, auth, args, what) {
|
|
62895
|
-
const
|
|
62951
|
+
const current = typeof auth === "function" ? await auth() : auth;
|
|
62952
|
+
const opts = networkOptions(current);
|
|
62896
62953
|
return mustGit(exec, dir, [...opts.prefix, ...args], what, { timeoutMs: 12e4, env: opts.env });
|
|
62897
62954
|
}
|
|
62898
62955
|
async function gitPush(exec, dir, auth, refspec = "HEAD:refs/heads/integration") {
|
|
@@ -63807,7 +63864,11 @@ function buildDeployHandlers(deps) {
|
|
|
63807
63864
|
async function requireGithub() {
|
|
63808
63865
|
const auth = await deps.githubIdentity.refresh();
|
|
63809
63866
|
if (!auth) throw new ClawdError(ERROR_CODES.INTERNAL, NO_GITHUB_AUTH);
|
|
63810
|
-
return { auth
|
|
63867
|
+
return { auth: async () => {
|
|
63868
|
+
const current = await deps.githubIdentity.refresh();
|
|
63869
|
+
if (!current) throw new ClawdError(ERROR_CODES.INTERNAL, NO_GITHUB_AUTH);
|
|
63870
|
+
return current;
|
|
63871
|
+
}, api: deps.githubApi(auth.token) };
|
|
63811
63872
|
}
|
|
63812
63873
|
function mustPersona(personaId2) {
|
|
63813
63874
|
if (!deps.hasPersona(personaId2)) {
|
|
@@ -65032,13 +65093,82 @@ function createGithubIdentity(deps) {
|
|
|
65032
65093
|
let pendingOauth = null;
|
|
65033
65094
|
let staleCenterToken;
|
|
65034
65095
|
const listeners = /* @__PURE__ */ new Set();
|
|
65035
|
-
|
|
65036
|
-
|
|
65037
|
-
|
|
65038
|
-
|
|
65039
|
-
|
|
65096
|
+
let managedToken;
|
|
65097
|
+
const oauthCandidate = (token) => /^gh[ou]_/.test(token);
|
|
65098
|
+
const oauthManaged = (token) => oauthCandidate(token) && (managedToken === token || deps.isManaged?.(token) === true);
|
|
65099
|
+
let acquisition;
|
|
65100
|
+
let centerFlight;
|
|
65101
|
+
let centerCache;
|
|
65102
|
+
let writes = Promise.resolve();
|
|
65103
|
+
function remember(got) {
|
|
65104
|
+
const expiry = got.expiresAt ? Date.parse(got.expiresAt) - 6e4 : Infinity;
|
|
65105
|
+
centerCache = { token: got.token, until: Math.min(deps.now() + 2e4, expiry) };
|
|
65106
|
+
}
|
|
65107
|
+
function persist(token, generation, managed = false) {
|
|
65108
|
+
const write = writes.catch(() => {
|
|
65109
|
+
}).then(async () => {
|
|
65110
|
+
if (generation !== seq) return;
|
|
65111
|
+
const stored = await deps.store(token);
|
|
65112
|
+
if (generation !== seq) return;
|
|
65113
|
+
deps.markManaged?.(managed ? token : void 0);
|
|
65114
|
+
managedToken = managed ? token : void 0;
|
|
65115
|
+
auth = stored;
|
|
65116
|
+
statusCache.clear();
|
|
65117
|
+
pendingOauth = null;
|
|
65118
|
+
for (const cb of listeners) cb();
|
|
65119
|
+
});
|
|
65120
|
+
writes = write;
|
|
65121
|
+
return write;
|
|
65122
|
+
}
|
|
65123
|
+
async function syncCenter(local, rejectedToken) {
|
|
65124
|
+
if (!oauthCandidate(local.token)) return local;
|
|
65125
|
+
const managed = oauthManaged(local.token);
|
|
65126
|
+
if (!rejectedToken && centerCache?.token === local.token && deps.now() < centerCache.until) return local;
|
|
65127
|
+
if (centerFlight) return centerFlight;
|
|
65128
|
+
const generation = seq;
|
|
65129
|
+
const task = (async () => {
|
|
65130
|
+
let got;
|
|
65131
|
+
try {
|
|
65132
|
+
got = await deps.oauth.token(rejectedToken);
|
|
65133
|
+
} catch (err) {
|
|
65134
|
+
if (managed) throw err;
|
|
65135
|
+
return local;
|
|
65136
|
+
}
|
|
65137
|
+
if (generation !== seq) return auth;
|
|
65138
|
+
if (!got || !managed && got.token !== local.token) {
|
|
65139
|
+
remember({ token: local.token });
|
|
65140
|
+
return local;
|
|
65141
|
+
}
|
|
65142
|
+
if (!managed || got.token !== local.token) await persist(got.token, generation, true);
|
|
65143
|
+
if (generation !== seq) return auth;
|
|
65144
|
+
remember(got);
|
|
65145
|
+
return auth ?? local;
|
|
65146
|
+
})().finally(() => {
|
|
65147
|
+
if (centerFlight === task) centerFlight = void 0;
|
|
65148
|
+
});
|
|
65149
|
+
centerFlight = task;
|
|
65150
|
+
return task;
|
|
65151
|
+
}
|
|
65152
|
+
function refresh() {
|
|
65153
|
+
if (acquisition) return acquisition;
|
|
65154
|
+
const generation = seq;
|
|
65155
|
+
const task = (async () => {
|
|
65156
|
+
const resolved = await deps.resolve();
|
|
65157
|
+
if (generation !== seq) return auth;
|
|
65158
|
+
auth = resolved;
|
|
65159
|
+
return resolved ? syncCenter(resolved) : void 0;
|
|
65160
|
+
})().finally(() => {
|
|
65161
|
+
if (acquisition === task) acquisition = void 0;
|
|
65162
|
+
});
|
|
65163
|
+
acquisition = task;
|
|
65164
|
+
return task;
|
|
65040
65165
|
}
|
|
65041
|
-
async function
|
|
65166
|
+
async function recover(rejectedToken) {
|
|
65167
|
+
const current = await refresh();
|
|
65168
|
+
if (!current || current.token !== rejectedToken || !oauthManaged(current.token)) return current;
|
|
65169
|
+
return syncCenter(current, rejectedToken);
|
|
65170
|
+
}
|
|
65171
|
+
async function whoami(a2, recovering = false) {
|
|
65042
65172
|
const hit = statusCache.get(a2.token);
|
|
65043
65173
|
if (hit && deps.now() - hit.at < cacheMs) return hit.status;
|
|
65044
65174
|
let status2;
|
|
@@ -65046,19 +65176,26 @@ function createGithubIdentity(deps) {
|
|
|
65046
65176
|
const { login } = await deps.api(a2.token).whoami();
|
|
65047
65177
|
status2 = { status: "authorized", login, source: a2.source };
|
|
65048
65178
|
} catch (err) {
|
|
65179
|
+
if (!recovering && err instanceof GithubApiError && err.status === 401 && oauthManaged(a2.token)) {
|
|
65180
|
+
try {
|
|
65181
|
+
const renewed = await recover(a2.token);
|
|
65182
|
+
if (renewed && renewed.token !== a2.token) return whoami(renewed, true);
|
|
65183
|
+
} catch (recoveryError) {
|
|
65184
|
+
return { status: "invalid", message: recoveryError instanceof Error ? recoveryError.message : String(recoveryError) };
|
|
65185
|
+
}
|
|
65186
|
+
}
|
|
65049
65187
|
status2 = { status: "invalid", message: err instanceof Error ? err.message : String(err) };
|
|
65050
65188
|
}
|
|
65051
65189
|
statusCache.set(a2.token, { at: deps.now(), status: status2 });
|
|
65052
65190
|
return status2;
|
|
65053
65191
|
}
|
|
65054
65192
|
async function adopt(token) {
|
|
65055
|
-
|
|
65056
|
-
|
|
65057
|
-
|
|
65058
|
-
pendingOauth = null;
|
|
65059
|
-
for (const cb of listeners) cb();
|
|
65193
|
+
const generation = ++seq;
|
|
65194
|
+
centerCache = void 0;
|
|
65195
|
+
await persist(token, generation);
|
|
65060
65196
|
}
|
|
65061
65197
|
async function claimCenterToken() {
|
|
65198
|
+
const generation = seq;
|
|
65062
65199
|
let got;
|
|
65063
65200
|
try {
|
|
65064
65201
|
got = await deps.oauth.token();
|
|
@@ -65072,7 +65209,9 @@ function createGithubIdentity(deps) {
|
|
|
65072
65209
|
if (err instanceof GithubApiError && err.status === 401) staleCenterToken = got.token;
|
|
65073
65210
|
return false;
|
|
65074
65211
|
}
|
|
65075
|
-
|
|
65212
|
+
if (generation !== seq) return false;
|
|
65213
|
+
await persist(got.token, ++seq, true);
|
|
65214
|
+
remember(got);
|
|
65076
65215
|
return true;
|
|
65077
65216
|
}
|
|
65078
65217
|
async function settlePendingOauth() {
|
|
@@ -65090,13 +65229,19 @@ function createGithubIdentity(deps) {
|
|
|
65090
65229
|
}
|
|
65091
65230
|
async function status() {
|
|
65092
65231
|
await settlePendingOauth();
|
|
65093
|
-
|
|
65232
|
+
let a2;
|
|
65233
|
+
try {
|
|
65234
|
+
a2 = await refresh();
|
|
65235
|
+
} catch (err) {
|
|
65236
|
+
return { status: "invalid", message: err instanceof Error ? err.message : String(err) };
|
|
65237
|
+
}
|
|
65094
65238
|
const current = a2 ? await whoami(a2) : { status: "missing" };
|
|
65095
65239
|
return pendingOauth && current.status !== "authorized" ? { status: "pending", authUrl: pendingOauth.authUrl } : current;
|
|
65096
65240
|
}
|
|
65097
65241
|
return {
|
|
65098
65242
|
cached: () => auth,
|
|
65099
65243
|
refresh,
|
|
65244
|
+
recover,
|
|
65100
65245
|
status,
|
|
65101
65246
|
adopt,
|
|
65102
65247
|
async authorize(raw) {
|
|
@@ -65111,7 +65256,7 @@ function createGithubIdentity(deps) {
|
|
|
65111
65256
|
},
|
|
65112
65257
|
// 已有身份时重新授权;直接返回 pending 链接,不能经 status() 被旧的 authorized 状态遮掉。
|
|
65113
65258
|
async oauthStart(returnTo) {
|
|
65114
|
-
const local = await
|
|
65259
|
+
const local = await deps.resolve();
|
|
65115
65260
|
if (!local && await claimCenterToken()) return status();
|
|
65116
65261
|
try {
|
|
65117
65262
|
staleCenterToken = (await deps.oauth.token())?.token;
|
|
@@ -69800,7 +69945,7 @@ var ContactStore = class {
|
|
|
69800
69945
|
};
|
|
69801
69946
|
|
|
69802
69947
|
// src/contact/connect-remote.ts
|
|
69803
|
-
var
|
|
69948
|
+
var crypto6 = __toESM(require("crypto"), 1);
|
|
69804
69949
|
init_protocol();
|
|
69805
69950
|
var HANDSHAKE_TIMEOUT_MS = 5e3;
|
|
69806
69951
|
var RPC_TIMEOUT_MS = 5e3;
|
|
@@ -69855,7 +70000,7 @@ async function connectRemote(args) {
|
|
|
69855
70000
|
ws.once("close", onClose);
|
|
69856
70001
|
});
|
|
69857
70002
|
function call(method, payload) {
|
|
69858
|
-
const requestId =
|
|
70003
|
+
const requestId = crypto6.randomUUID();
|
|
69859
70004
|
return new Promise((resolve9, reject) => {
|
|
69860
70005
|
const onMessage = (raw) => {
|
|
69861
70006
|
let f2;
|
|
@@ -72324,7 +72469,7 @@ function buildDeviceHandlers(deps) {
|
|
|
72324
72469
|
}
|
|
72325
72470
|
|
|
72326
72471
|
// src/feishu-auth/verify-token.ts
|
|
72327
|
-
var
|
|
72472
|
+
var crypto13 = __toESM(require("crypto"), 1);
|
|
72328
72473
|
var CONNECT_TOKEN_PREFIX = "clawdtk1";
|
|
72329
72474
|
function verifyConnectToken(args) {
|
|
72330
72475
|
const now = args.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
@@ -72336,7 +72481,7 @@ function verifyConnectToken(args) {
|
|
|
72336
72481
|
const data = `${prefix}.${payloadB64}`;
|
|
72337
72482
|
let signatureValid = false;
|
|
72338
72483
|
try {
|
|
72339
|
-
signatureValid =
|
|
72484
|
+
signatureValid = crypto13.verify(
|
|
72340
72485
|
null,
|
|
72341
72486
|
Buffer.from(data, "utf8"),
|
|
72342
72487
|
args.publicKeyPem,
|
|
@@ -74996,6 +75141,7 @@ function buildCloudConnectorsHandlers(deps) {
|
|
|
74996
75141
|
|
|
74997
75142
|
// src/handlers/cloud-workspace.ts
|
|
74998
75143
|
init_protocol();
|
|
75144
|
+
var import_node_crypto26 = require("crypto");
|
|
74999
75145
|
function buildCloudWorkspaceHandlers(deps) {
|
|
75000
75146
|
return {
|
|
75001
75147
|
"cloud:workspace": async (frame, _client, ctx) => {
|
|
@@ -75023,17 +75169,34 @@ function buildCloudWorkspaceHandlers(deps) {
|
|
|
75023
75169
|
) || file.cloudPendingTurns?.length))
|
|
75024
75170
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u5B8C\u6210");
|
|
75025
75171
|
const conversationId = file.cloudConversationId ?? file.cloudExecutionId ?? file.sessionId;
|
|
75026
|
-
const
|
|
75027
|
-
|
|
75028
|
-
|
|
75029
|
-
|
|
75030
|
-
|
|
75031
|
-
|
|
75032
|
-
}
|
|
75033
|
-
|
|
75034
|
-
|
|
75035
|
-
|
|
75036
|
-
|
|
75172
|
+
const traceId = typeof frame.requestId === "string" && /^[A-Za-z0-9:_-]{1,128}$/.test(frame.requestId) ? frame.requestId : (0, import_node_crypto26.randomUUID)();
|
|
75173
|
+
const started = performance.now();
|
|
75174
|
+
const meta = { traceId, sessionId: args.sessionId, action: args.action };
|
|
75175
|
+
const log = (event, detail) => {
|
|
75176
|
+
try {
|
|
75177
|
+
deps.logger?.info("cloud.workspace.rpc." + event, { ...meta, ...detail });
|
|
75178
|
+
} catch {
|
|
75179
|
+
}
|
|
75180
|
+
};
|
|
75181
|
+
let outcome = "error";
|
|
75182
|
+
log("started", {});
|
|
75183
|
+
try {
|
|
75184
|
+
const result = CloudWorkspaceResultSchema.parse(
|
|
75185
|
+
await deps.command(file, {
|
|
75186
|
+
...args,
|
|
75187
|
+
traceId,
|
|
75188
|
+
workspaceId: file.cloudWorkspace?.workspaceId ?? file.sessionId,
|
|
75189
|
+
conversationId,
|
|
75190
|
+
...file.toolSessionId ? { threadId: file.toolSessionId } : {}
|
|
75191
|
+
})
|
|
75192
|
+
);
|
|
75193
|
+
if (result.binding && !file.cloudWorkspace)
|
|
75194
|
+
deps.bind(file.sessionId, result.binding, conversationId);
|
|
75195
|
+
outcome = "ok";
|
|
75196
|
+
return { response: { type: "cloud:workspace:ok", ...result } };
|
|
75197
|
+
} finally {
|
|
75198
|
+
log("finished", { outcome, durationMs: Math.round(performance.now() - started) });
|
|
75199
|
+
}
|
|
75037
75200
|
}
|
|
75038
75201
|
};
|
|
75039
75202
|
}
|
|
@@ -75363,7 +75526,7 @@ function computeMethodAccess(args) {
|
|
|
75363
75526
|
}
|
|
75364
75527
|
|
|
75365
75528
|
// src/version.ts
|
|
75366
|
-
var version = "0.2.
|
|
75529
|
+
var version = "0.2.691".length > 0 ? "0.2.691" : "dev";
|
|
75367
75530
|
|
|
75368
75531
|
// src/cli-probe/probe.ts
|
|
75369
75532
|
var fs86 = __toESM(require("fs"), 1);
|
|
@@ -75759,7 +75922,7 @@ init_protocol();
|
|
|
75759
75922
|
// src/extension/bundle-zip.ts
|
|
75760
75923
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
75761
75924
|
var import_node_path78 = __toESM(require("path"), 1);
|
|
75762
|
-
var
|
|
75925
|
+
var import_node_crypto27 = __toESM(require("crypto"), 1);
|
|
75763
75926
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
75764
75927
|
async function bundleExtensionDir(dir) {
|
|
75765
75928
|
const entries = await listFilesSorted(dir);
|
|
@@ -75774,7 +75937,7 @@ async function bundleExtensionDir(dir) {
|
|
|
75774
75937
|
compression: "DEFLATE",
|
|
75775
75938
|
compressionOptions: { level: 6 }
|
|
75776
75939
|
});
|
|
75777
|
-
const sha256 =
|
|
75940
|
+
const sha256 = import_node_crypto27.default.createHash("sha256").update(buffer).digest("hex");
|
|
75778
75941
|
return { buffer, sha256 };
|
|
75779
75942
|
}
|
|
75780
75943
|
var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
@@ -75842,7 +76005,7 @@ function computePublishCheck(args) {
|
|
|
75842
76005
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
75843
76006
|
var import_node_path80 = __toESM(require("path"), 1);
|
|
75844
76007
|
var import_node_os30 = __toESM(require("os"), 1);
|
|
75845
|
-
var
|
|
76008
|
+
var import_node_crypto28 = __toESM(require("crypto"), 1);
|
|
75846
76009
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
75847
76010
|
|
|
75848
76011
|
// src/extension/paths.ts
|
|
@@ -75871,7 +76034,7 @@ var InstallError = class extends Error {
|
|
|
75871
76034
|
};
|
|
75872
76035
|
async function installFromChannel(args, deps) {
|
|
75873
76036
|
const { channelRef, snapshotHash, bundleZip } = args;
|
|
75874
|
-
const computed =
|
|
76037
|
+
const computed = import_node_crypto28.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
75875
76038
|
if (computed !== snapshotHash) {
|
|
75876
76039
|
throw new InstallError(
|
|
75877
76040
|
"HASH_MISMATCH",
|
|
@@ -75963,7 +76126,7 @@ async function installFromChannel(args, deps) {
|
|
|
75963
76126
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
75964
76127
|
var import_node_path81 = __toESM(require("path"), 1);
|
|
75965
76128
|
var import_node_os31 = __toESM(require("os"), 1);
|
|
75966
|
-
var
|
|
76129
|
+
var import_node_crypto29 = __toESM(require("crypto"), 1);
|
|
75967
76130
|
var import_jszip5 = __toESM(require_lib3(), 1);
|
|
75968
76131
|
var UpdateError = class extends Error {
|
|
75969
76132
|
constructor(code, message) {
|
|
@@ -76001,7 +76164,7 @@ async function updateFromChannel(args, deps) {
|
|
|
76001
76164
|
if (e instanceof UpdateError) throw e;
|
|
76002
76165
|
throw e;
|
|
76003
76166
|
}
|
|
76004
|
-
const computed =
|
|
76167
|
+
const computed = import_node_crypto29.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
76005
76168
|
if (computed !== snapshotHash) {
|
|
76006
76169
|
throw new UpdateError(
|
|
76007
76170
|
"HASH_MISMATCH",
|
|
@@ -77129,7 +77292,7 @@ async function uninstall(deps) {
|
|
|
77129
77292
|
}
|
|
77130
77293
|
|
|
77131
77294
|
// src/handlers/index.ts
|
|
77132
|
-
var
|
|
77295
|
+
var import_node_crypto30 = require("crypto");
|
|
77133
77296
|
|
|
77134
77297
|
// src/handlers/peer-exec.ts
|
|
77135
77298
|
init_protocol();
|
|
@@ -77286,7 +77449,7 @@ function buildMethodHandlers(deps) {
|
|
|
77286
77449
|
const c2 = deps.contactStore.get(deviceId);
|
|
77287
77450
|
return c2 ? { deviceId: c2.deviceId, remoteUrl: c2.remoteUrl, connectToken: c2.connectToken } : null;
|
|
77288
77451
|
},
|
|
77289
|
-
genId: () => (0,
|
|
77452
|
+
genId: () => (0, import_node_crypto30.randomUUID)(),
|
|
77290
77453
|
now: () => Date.now(),
|
|
77291
77454
|
forwardInboxPostToPeer,
|
|
77292
77455
|
logger: deps.logger
|
|
@@ -78011,7 +78174,7 @@ async function startDaemon(config) {
|
|
|
78011
78174
|
const channelStore = createChannelStore({
|
|
78012
78175
|
filePath: import_node_path89.default.join(config.dataDir, "channels.json"),
|
|
78013
78176
|
now: () => Date.now(),
|
|
78014
|
-
genId: () => `ch-${(0,
|
|
78177
|
+
genId: () => `ch-${(0, import_node_crypto31.randomUUID)().slice(0, 8)}`,
|
|
78015
78178
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
78016
78179
|
reason: err instanceof Error ? err.message : String(err)
|
|
78017
78180
|
})
|
|
@@ -78020,7 +78183,7 @@ async function startDaemon(config) {
|
|
|
78020
78183
|
const topicStore = createTopicStore({
|
|
78021
78184
|
filePath: import_node_path89.default.join(config.dataDir, "topics.json"),
|
|
78022
78185
|
now: () => Date.now(),
|
|
78023
|
-
genId: () => `tp-${(0,
|
|
78186
|
+
genId: () => `tp-${(0, import_node_crypto31.randomUUID)().slice(0, 8)}`,
|
|
78024
78187
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
78025
78188
|
reason: err instanceof Error ? err.message : String(err)
|
|
78026
78189
|
})
|
|
@@ -78028,7 +78191,7 @@ async function startDaemon(config) {
|
|
|
78028
78191
|
await topicStore.load();
|
|
78029
78192
|
let deliverPendingRef;
|
|
78030
78193
|
const personaDispatchManager = new PersonaDispatchManager({
|
|
78031
|
-
genId: () => (0,
|
|
78194
|
+
genId: () => (0, import_node_crypto31.randomUUID)(),
|
|
78032
78195
|
store: dispatchStore,
|
|
78033
78196
|
now: () => Date.now(),
|
|
78034
78197
|
onCompleted: (sid) => deliverPendingRef?.(sid),
|
|
@@ -78051,7 +78214,14 @@ async function startDaemon(config) {
|
|
|
78051
78214
|
const localSecretsDir = import_node_path89.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
|
|
78052
78215
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
78053
78216
|
const githubTokenFile = import_node_path89.default.join(localSecretsDir, GITHUB_TOKEN_FILE);
|
|
78217
|
+
const managedGithubVar = "CLAWD_GITHUB_MANAGED_TOKEN_SHA256";
|
|
78218
|
+
const githubFingerprint = (token) => (0, import_node_crypto31.createHash)("sha256").update(token).digest("hex");
|
|
78054
78219
|
const githubIdentity = createGithubIdentity({
|
|
78220
|
+
isManaged: (token) => readEnvFileVar(githubTokenFile, managedGithubVar) === githubFingerprint(token),
|
|
78221
|
+
markManaged: (token) => {
|
|
78222
|
+
if (token) upsertEnvFileVar(githubTokenFile, managedGithubVar, githubFingerprint(token));
|
|
78223
|
+
else removeEnvFileVar(githubTokenFile, managedGithubVar);
|
|
78224
|
+
},
|
|
78055
78225
|
resolve: () => resolveGithubAuth({ exec: runCommand, fileToken: () => readEnvFileVar(githubTokenFile, GITHUB_TOKEN_VAR) }),
|
|
78056
78226
|
store: (token) => storeGithubAuth({
|
|
78057
78227
|
exec: runCommand,
|
|
@@ -78073,19 +78243,23 @@ async function startDaemon(config) {
|
|
|
78073
78243
|
throw new ClawdError(ERROR_CODES.INTERNAL, `\u5411\u4E2D\u5FC3\u8981 GitHub \u6388\u6743\u94FE\u63A5\u6CA1\u6210\uFF1A${err instanceof Error ? err.message : String(err)}`);
|
|
78074
78244
|
}
|
|
78075
78245
|
},
|
|
78076
|
-
token: async () => {
|
|
78246
|
+
token: async (rejectedToken) => {
|
|
78077
78247
|
const r2 = ownerIdentityStore.read();
|
|
78078
78248
|
if (!r2) return void 0;
|
|
78079
|
-
return centralGithubAuthToken({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, loginPass: r2.loginPass });
|
|
78249
|
+
return centralGithubAuthToken({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, loginPass: r2.loginPass, ...rejectedToken ? { rejectedToken } : {} });
|
|
78080
78250
|
}
|
|
78081
78251
|
},
|
|
78082
78252
|
now: () => Date.now(),
|
|
78083
78253
|
logger
|
|
78084
78254
|
});
|
|
78085
|
-
void githubIdentity.refresh()
|
|
78255
|
+
void githubIdentity.refresh().catch(() => {
|
|
78256
|
+
logger.warn("github.identity.warm-failed");
|
|
78257
|
+
});
|
|
78086
78258
|
const resolvePersonaMcpConfig = (personaId2) => {
|
|
78087
78259
|
const secrets = secretsWithGithubIdentity(readSecrets(), githubIdentity.cached());
|
|
78088
|
-
void githubIdentity.refresh()
|
|
78260
|
+
void githubIdentity.refresh().catch(() => {
|
|
78261
|
+
logger.warn("github.identity.sync-failed");
|
|
78262
|
+
});
|
|
78089
78263
|
return renderPersonaMcpSecrets({
|
|
78090
78264
|
personaId: personaId2,
|
|
78091
78265
|
personaDir: import_node_path89.default.join(config.dataDir, "personas", personaId2),
|
|
@@ -78881,6 +79055,7 @@ async function startDaemon(config) {
|
|
|
78881
79055
|
}
|
|
78882
79056
|
},
|
|
78883
79057
|
cloudWorkspace: {
|
|
79058
|
+
logger,
|
|
78884
79059
|
getFile: (id) => manager.get({ sessionId: id }).response,
|
|
78885
79060
|
status: (id) => manager.getCurrentStatus(id),
|
|
78886
79061
|
bind: (id, binding, conversationId) => manager.bindCloudWorkspace(id, binding, conversationId),
|
|
@@ -78913,7 +79088,7 @@ async function startDaemon(config) {
|
|
|
78913
79088
|
shiftStore,
|
|
78914
79089
|
shiftOwnerIdProvider: () => ownerPrincipalId,
|
|
78915
79090
|
// PR 收件箱:github:* handler spawn 本机 gh CLI,凭据是 clawd 的 GitHub 身份(GH_TOKEN),没有才是 gh 自己的登录态
|
|
78916
|
-
ghRunner: createGhRunner({ token: () => githubIdentity.
|
|
79091
|
+
ghRunner: createGhRunner({ token: async () => (await githubIdentity.refresh())?.token }),
|
|
78917
79092
|
githubIdentity,
|
|
78918
79093
|
visitorStore
|
|
78919
79094
|
})
|
|
@@ -79023,7 +79198,7 @@ async function startDaemon(config) {
|
|
|
79023
79198
|
fetchArtifact: downloadArtifact(runCommand),
|
|
79024
79199
|
debianPackage: lookupDebianPackage(),
|
|
79025
79200
|
githubIdentity,
|
|
79026
|
-
githubApi: (token) => createGithubApi({ token }),
|
|
79201
|
+
githubApi: (token) => createGithubApi({ token, identity: githubIdentity }),
|
|
79027
79202
|
org: PERSONA_REPO_ORG,
|
|
79028
79203
|
claimPublisher: async (personaId2, environment = "production") => {
|
|
79029
79204
|
const loginPass = targetLoginPass(environment);
|