release: prepare 0629001 portal updates
This commit is contained in:
+91
-29
@@ -32,6 +32,7 @@ import {
|
||||
PUBLISH_SKILL_NAME,
|
||||
resolvePublicBaseUrl,
|
||||
resolveLegacyPublishDir,
|
||||
resolveGoosedSandboxRoot,
|
||||
} from './user-publish.mjs';
|
||||
import {
|
||||
ensureUserSpaceLayout,
|
||||
@@ -1196,39 +1197,91 @@ export function createUserAuth(pool, options = {}) {
|
||||
};
|
||||
}
|
||||
const tokenState = normalizeTokenState(tokenStateRaw);
|
||||
const previous = await getBillingState(agentSessionId);
|
||||
if (
|
||||
previous &&
|
||||
tokenState.accumulatedInputTokens <= Number(previous.lastInputTokens ?? 0) &&
|
||||
tokenState.accumulatedOutputTokens <= Number(previous.lastOutputTokens ?? 0)
|
||||
) {
|
||||
const user = await getUserById(userId);
|
||||
return {
|
||||
ok: true,
|
||||
costCents: 0,
|
||||
balanceCents: user ? Number(user.balance_cents) : null,
|
||||
tokensUsed: user ? Number(user.tokens_used ?? 0) : null,
|
||||
deltaInputTokens: 0,
|
||||
deltaOutputTokens: 0,
|
||||
};
|
||||
}
|
||||
const config = loadBillingConfig();
|
||||
let costCents = computeDeltaCostCents(previous, tokenState, config);
|
||||
const deltaIn = Math.max(
|
||||
0,
|
||||
tokenState.accumulatedInputTokens - Number(previous?.lastInputTokens ?? 0),
|
||||
);
|
||||
const deltaOut = Math.max(
|
||||
0,
|
||||
tokenState.accumulatedOutputTokens - Number(previous?.lastOutputTokens ?? 0),
|
||||
);
|
||||
const deltaTokens = deltaIn + deltaOut;
|
||||
|
||||
const normalizedRequestId = requestId ? String(requestId).trim() || null : null;
|
||||
const now = Date.now();
|
||||
const conn = await pool.getConnection();
|
||||
try {
|
||||
await conn.beginTransaction();
|
||||
|
||||
if (normalizedRequestId) {
|
||||
const [existingUsage] = await conn.query(
|
||||
`SELECT cost_cents FROM h5_usage_records WHERE request_id = ? LIMIT 1`,
|
||||
[normalizedRequestId],
|
||||
);
|
||||
if (existingUsage[0]) {
|
||||
const [walletRows] = await conn.query(
|
||||
`SELECT balance_cents, tokens_used FROM h5_user_wallets WHERE user_id = ?`,
|
||||
[userId],
|
||||
);
|
||||
await conn.commit();
|
||||
return {
|
||||
ok: true,
|
||||
costCents: 0,
|
||||
balanceCents: walletRows[0] ? Number(walletRows[0].balance_cents) : null,
|
||||
tokensUsed: walletRows[0] ? Number(walletRows[0].tokens_used ?? 0) : null,
|
||||
deltaInputTokens: 0,
|
||||
deltaOutputTokens: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder insert so concurrent billers serialize on the same session row.
|
||||
await conn.query(
|
||||
`INSERT INTO h5_session_billing_state
|
||||
(agent_session_id, user_id, last_accumulated_cost, last_input_tokens, last_output_tokens, updated_at)
|
||||
VALUES (?, ?, NULL, 0, 0, ?)
|
||||
ON DUPLICATE KEY UPDATE agent_session_id = agent_session_id`,
|
||||
[agentSessionId, userId, now],
|
||||
);
|
||||
|
||||
const [stateRows] = await conn.query(
|
||||
`SELECT last_accumulated_cost, last_input_tokens, last_output_tokens
|
||||
FROM h5_session_billing_state
|
||||
WHERE agent_session_id = ?
|
||||
FOR UPDATE`,
|
||||
[agentSessionId],
|
||||
);
|
||||
const stateRow = stateRows[0];
|
||||
const previous = stateRow
|
||||
? {
|
||||
lastAccumulatedCost: stateRow.last_accumulated_cost,
|
||||
lastInputTokens: Number(stateRow.last_input_tokens ?? 0),
|
||||
lastOutputTokens: Number(stateRow.last_output_tokens ?? 0),
|
||||
}
|
||||
: null;
|
||||
|
||||
if (
|
||||
previous &&
|
||||
tokenState.accumulatedInputTokens <= Number(previous.lastInputTokens ?? 0) &&
|
||||
tokenState.accumulatedOutputTokens <= Number(previous.lastOutputTokens ?? 0)
|
||||
) {
|
||||
const [walletRows] = await conn.query(
|
||||
`SELECT balance_cents, tokens_used FROM h5_user_wallets WHERE user_id = ?`,
|
||||
[userId],
|
||||
);
|
||||
await conn.commit();
|
||||
return {
|
||||
ok: true,
|
||||
costCents: 0,
|
||||
balanceCents: walletRows[0] ? Number(walletRows[0].balance_cents) : null,
|
||||
tokensUsed: walletRows[0] ? Number(walletRows[0].tokens_used ?? 0) : null,
|
||||
deltaInputTokens: 0,
|
||||
deltaOutputTokens: 0,
|
||||
};
|
||||
}
|
||||
|
||||
let costCents = computeDeltaCostCents(previous, tokenState, config);
|
||||
const deltaIn = Math.max(
|
||||
0,
|
||||
tokenState.accumulatedInputTokens - Number(previous?.lastInputTokens ?? 0),
|
||||
);
|
||||
const deltaOut = Math.max(
|
||||
0,
|
||||
tokenState.accumulatedOutputTokens - Number(previous?.lastOutputTokens ?? 0),
|
||||
);
|
||||
const deltaTokens = deltaIn + deltaOut;
|
||||
|
||||
await conn.query(
|
||||
`INSERT INTO h5_session_billing_state
|
||||
(agent_session_id, user_id, last_accumulated_cost, last_input_tokens, last_output_tokens, updated_at)
|
||||
@@ -1287,7 +1340,16 @@ export function createUserAuth(pool, options = {}) {
|
||||
`INSERT INTO h5_usage_records
|
||||
(user_id, agent_session_id, request_id, input_tokens, output_tokens, cost_cents, balance_after_cents, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[userId, agentSessionId, requestId, deltaIn, deltaOut, costCents, nextBalance, now],
|
||||
[
|
||||
userId,
|
||||
agentSessionId,
|
||||
normalizedRequestId,
|
||||
deltaIn,
|
||||
deltaOut,
|
||||
costCents,
|
||||
nextBalance,
|
||||
now,
|
||||
],
|
||||
);
|
||||
|
||||
await conn.query(
|
||||
@@ -1668,7 +1730,7 @@ export function createUserAuth(pool, options = {}) {
|
||||
// paths instead. Unset (e.g. local dev, co-located native goosed) => fall back to
|
||||
// the portal's own paths, so behavior is unchanged.
|
||||
serverPath: resolveSandboxMcpServerPath(process.env.GOOSED_MCP_SERVER_PATH),
|
||||
sandboxRoot: layout.publishDir,
|
||||
sandboxRoot: resolveGoosedSandboxRoot(h5Root, user),
|
||||
userId: user.id,
|
||||
nodeExecPath: process.env.GOOSED_MCP_NODE_PATH,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user