mirror of
http://192.168.0.88:13333/lywsvip/openclaw-zero-token.git
synced 2026-06-01 22:51:24 +08:00
Major upgrade from e26988a38 to upstream v2026.3.28 (f9b107928).
Key changes:
- Upstream src/, ui/, extensions/ (89 bundled extensions)
- Zero-token web providers preserved in src/zero-token/
- AskOnce plugin restored and registered as CLI command
- Added missing packages: @anthropic-ai/vertex-sdk, @modelcontextprotocol/sdk
- Fixed tsconfig rootDir, skipLibCheck for plugin-sdk DTS build
- Added askonce to bundled plugin metadata and package.json exports
- Fixed AskOnce CLI command registration (missing commands metadata)
- Restored AskOnce adapter imports (correct 5-level relative paths)
- Removed stale migration artifacts from root directory
69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
const OPERATOR_ROLE = "operator";
|
|
const OPERATOR_ADMIN_SCOPE = "operator.admin";
|
|
const OPERATOR_READ_SCOPE = "operator.read";
|
|
const OPERATOR_WRITE_SCOPE = "operator.write";
|
|
const OPERATOR_SCOPE_PREFIX = "operator.";
|
|
|
|
function normalizeScopeList(scopes: readonly string[]): string[] {
|
|
const out = new Set<string>();
|
|
for (const scope of scopes) {
|
|
const trimmed = scope.trim();
|
|
if (trimmed) {
|
|
out.add(trimmed);
|
|
}
|
|
}
|
|
return [...out];
|
|
}
|
|
|
|
function operatorScopeSatisfied(requestedScope: string, granted: Set<string>): boolean {
|
|
if (granted.has(OPERATOR_ADMIN_SCOPE) && requestedScope.startsWith(OPERATOR_SCOPE_PREFIX)) {
|
|
return true;
|
|
}
|
|
if (requestedScope === OPERATOR_READ_SCOPE) {
|
|
return granted.has(OPERATOR_READ_SCOPE) || granted.has(OPERATOR_WRITE_SCOPE);
|
|
}
|
|
if (requestedScope === OPERATOR_WRITE_SCOPE) {
|
|
return granted.has(OPERATOR_WRITE_SCOPE);
|
|
}
|
|
return granted.has(requestedScope);
|
|
}
|
|
|
|
export function roleScopesAllow(params: {
|
|
role: string;
|
|
requestedScopes: readonly string[];
|
|
allowedScopes: readonly string[];
|
|
}): boolean {
|
|
const requested = normalizeScopeList(params.requestedScopes);
|
|
if (requested.length === 0) {
|
|
return true;
|
|
}
|
|
const allowed = normalizeScopeList(params.allowedScopes);
|
|
if (allowed.length === 0) {
|
|
return false;
|
|
}
|
|
const allowedSet = new Set(allowed);
|
|
if (params.role.trim() !== OPERATOR_ROLE) {
|
|
return requested.every((scope) => allowedSet.has(scope));
|
|
}
|
|
return requested.every((scope) => operatorScopeSatisfied(scope, allowedSet));
|
|
}
|
|
|
|
export function resolveMissingRequestedScope(params: {
|
|
role: string;
|
|
requestedScopes: readonly string[];
|
|
allowedScopes: readonly string[];
|
|
}): string | null {
|
|
for (const scope of params.requestedScopes) {
|
|
if (
|
|
!roleScopesAllow({
|
|
role: params.role,
|
|
requestedScopes: [scope],
|
|
allowedScopes: params.allowedScopes,
|
|
})
|
|
) {
|
|
return scope;
|
|
}
|
|
}
|
|
return null;
|
|
}
|